问题记录
我在本地编写了代码,突然想查看之前提交的代码,并且想保留当前所在分支所做的修改
通过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 时才可能冲突 |