問題記錄
我在本地編寫了代碼,突然想查看之前提交的代碼,并且想保留當前所在分支所做的修改
通過git stash
對本地的代碼進行暫存
使用git checkout <commit-hash>
切換到之前的提交記錄。
查看完之后我想切換回來,恢復暫存的本地代碼
使用git stash pop
恢復我本地暫存區的代碼,這時候出現了 git 沖突
我需要解決沖突,通過git status
查看暫存區的內容
對于Unmerged paths
和Untracked files
的內容,都通過git add
將這些文件添加到暫存區
git add .
完成之后,我以為已經完全恢復了切換分支之前本地的代碼,于是將分支切換為主分支。
此時提示我需要commit
執行git commit 操作后
切回自己的master分支
此時發現,現在的代碼是所切換的代碼,切換指定提交之前的本地代碼丟失了
問題原因
-
沒有使用
git checkout master
切換原來的分支就進行git stash pop
-
沒有切換回主分支,直接用
git stash pop
,會將暫存的修改(stash
)應用到當前所在的歷史提交(detached HEAD
),才會導致沖突-
如果你在
detached HEAD
狀態下stash pop
后直接切換分支:git stash pop ? ? ? # 修改應用到歷史提交 git checkout master # 切換分支
Git 會提示“本地修改會被覆蓋”,你必須選擇:
-
git commit
→ 提交會留在游離狀態,容易被遺忘。 -
git stash
→ 再次暫存,但需手動恢復。 -
丟棄修改 → 代碼丟失。
-
-
-
-
git stash push
未添加-u
參數導致未追蹤的文件未被添加到暫存區-
git stash
默認不保存未跟蹤文件。最初執行git stash
時沒有加-u
或--include-untracked
參數
-
什么是未跟蹤文件
從未執行過
git add
新創建的文件默認是未跟蹤的。
例如:你新建了一個
test.py
,但還沒用git add test.py
。被
.gitignore
忽略的文件
如果文件匹配
.gitignore
中的規則,即使手動git add
也會被忽略。例如:IDE 配置文件(如
.idea/
)、編譯生成的*.class
文件等。已從 Git 中刪除,但仍在本地磁盤
如果文件曾被跟蹤,但后來被
git rm
刪除,而本地文件仍保留,它會變成未跟蹤狀態。
如何恢復丟失的代碼?
1. 檢查是否還能找回 stash
運行以下命令查看是否還有 stash 記錄:
git stash list
如果仍有記錄(如 stash@{0}
),可以嘗試重新應用:
git stash apply 'stash@{0}' ?# 不刪除 stash ? #或者 git stash pop stash@{0} # 彈出刪除 stash
這時候暫存區的代碼就會恢復到工作區中了
2.未追蹤代碼未被恢復
這些文件沒有被 git stash apply
恢復,是因為:
主要原因
-
git stash
默認不保存未跟蹤文件-
你最初執行
git stash
時沒有加-u
或--include-untracked
參數 -
導致 IDE 配置文件(
.idea/
)和新創建的 Java 文件未被暫存
-
如果文件還在本地(未被刪除)
-
這些文件可能仍然在你的工作目錄中,只是 Git 沒有跟蹤它們。你可以手動檢查這些路徑是否存在:
ls habbit/.idea/ ? ? ? ? ?# 查看 .idea 目錄是否存在 ls habbit/HELP.md ? ? ? ? # 查看 HELP.md 是否存在
-
如果存在,可以直接用
git add
開始跟蹤:git add habbit/HELP.md
如果文件已被刪除
-
檢查 IDE(如 IntelliJ/VSCode)的 本地歷史記錄(Local History),可能會找到備份。
-
使用文件恢復工具(如
Recuva
)掃描硬盤。
正確操作流程
1. 切換分支前
-
推薦提交代碼(而不是 stash):
git add . git commit -m "臨時保存當前修改"
這樣即使切換分支,代碼也會在提交歷史中。
后續也能通過
git checkout <commit-hash>
切換回來 -
如果必須用 stash:
git stash push -u -m "暫存所有修改" ?# -u 包含未跟蹤文件
2. 切換分支后
-
恢復 stash 時正確處理沖突:
git stash pop ?# 或 git stash apply
如果沖突:
-
用
git status
查看沖突文件。 -
手動決定保留哪些代碼(不要直接
git add .
)。 -
確認無誤后再提交。
-
3. 切換回原分支
-
確保所有代碼已提交或 stash:
git status ?# 確認沒有未提交的修改 git checkout master
不添加暫存區直接git checkout 可以嗎?
對比項 | git checkout <commit> (第一種) | git stash + git checkout (第三種) |
---|---|---|
是否保留本地更改 | ? 保留(工作目錄和暫存區) | ? 不保留(先存到 stash,再恢復) |
工作目錄狀態 | 仍然有未提交的更改 | 切換到歷史提交時是干凈的 |
適用場景 | 臨時查看歷史版本,同時繼續修改 | 完全回到歷史版本,稍后恢復更改 |
是否進入 detached HEAD | ? 是 | ? 是 |
沖突風險 | 可能直接沖突(如果歷史版本和本地更改沖突) | 切換時無沖突,stash pop 時才可能沖突 |