git reflog 看不到刚删掉的提交,先确认 head 是否真的移动过;reflog 仅记录 checkout、reset、commit 等指针移动操作,不记录 git clean 或未 add 的文件删除,且默认只显示 head 日志,查分支需用 git reflog main,刚 reset 后目标提交通常在 head@{1}。

git reflog 看不到刚删掉的提交?先确认 HEAD 是否真的移动过
reflog 不是万能日志,它只记录 HEAD 或分支指针的本地移动历史,比如 checkout、reset、commit、merge 等操作。如果误删的是远程分支或只是本地文件没 add,reflog 里根本不会出现对应条目。
执行 git reflog 前,先运行 git status 和 git log --oneline -10,对比当前 HEAD 指向和你记忆中“丢失提交”的哈希前缀是否曾出现在最近几条 reflog 记录里。常见错误是以为 git clean -fd 或误删工作区文件会导致 reflog 更新——它不会。
-
git reflog默认只显示 HEAD 的移动,想查某分支(如main)的 reflog,用git reflog main - 如果刚执行过
git reset --hard,reflog 第一条通常是HEAD@{0}(重置后),第二条HEAD@{1}就是被覆盖的提交位置 - reflog 条目有效期默认 30 天(
gc.reflogExpire),但新仓库或频繁操作下可能更短;长期未提交的仓库,老记录可能已被git gc清理
从 reflog 找到提交哈希后,用 git reset --hard 回退到它
找到目标条目(例如 HEAD@{2} 或 main@{3}),直接硬重置即可恢复分支指针。这是最常用也最直接的恢复方式,但会覆盖当前工作区和暂存区 —— 如果你改过代码但没提交,这步会丢弃未提交变更。
示例:你想恢复 HEAD@{3} 对应的提交:
git reset --hard HEAD@{3}
- 别用
git checkout <hash></hash>切到那个提交再创建新分支——虽然可行,但多一步且容易混淆当前分支状态 - 如果目标提交在另一个分支上(比如
feature/login曾指向它),优先用git reset --hard feature/login@{1},避免依赖HEAD的路径 -
--hard是必须的;--soft只改 HEAD,--mixed(默认)不清空工作区,都不算真正“恢复”到那个提交的状态
恢复后 push 失败:非快进拒绝怎么办
本地恢复了旧提交,但远程分支已前进,直接 git push 会被拒绝。强制推送(git push --force-with-lease)是标准解法,但它有风险:如果别人在这期间往同一分支 push 过新提交,--force-with-lease 会失败并提醒你,防止覆盖他人工作。
- 绝对不要用
git push --force,它绕过所有安全检查 - 如果多人协作且你不确定远程是否有新提交,先
git fetch origin查看origin/main是否比你本地新 - 若远程确实有新提交,且你恢复的提交不包含它们,就得做
git rebase或git merge整合,而不是强行覆盖 - 恢复的是已删除的远程分支?用
git push origin <local-branch-name>:<remote-branch-name></remote-branch-name></local-branch-name>(如git push origin main:feature/old-fix)重新发布
reflog 被清空或找不到目标?试试 git fsck 和 .git/logs 的残迹
reflog 被 git gc 清理、或误执行 git reflog expire --expire=now --all 后,git reflog 就空了。这时还能抢救,因为 Git 对象只要没被 GC 回收,就还在 .git/objects 里。
运行 git fsck --lost-found,它会列出所有“悬空”(dangling)提交对象。输出里类似 dangling commit abc1234... 的行,就是可能的候选提交:
git fsck --lost-found # 找到 dangling commit abc1234... git show abc1234 # 确认是不是你要的提交
- 检查
.git/logs/目录下的文件(如.git/logs/HEAD、.git/logs/refs/heads/main),里面是纯文本 reflog 记录,即使git reflog命令看不到,文件可能还在 -
git fsck找到的提交,可用git branch rescue-branch abc1234先挂载成分支,再决定怎么合并回主干 - Git 2.22+ 支持
git reflog expire --expire=never防止自动清理,但需提前设置,出事后再设没用
reflog 是本地安全网,不是备份。真正关键的提交,早该推到远程或打 tag —— 恢复过程越靠后,不确定性越大,尤其是涉及多人协作时,沟通比技术操作更重要。











