Git 提交突然消失:用 reflog 找回改写前的分支
执行 git commit --amend 后突然发现原提交还有一份需要保留的内容。当前分支只显示新提交,但本地 reflog 可能保存分支移动前的提交 ID。先确认旧提交的内容,然后为它创建救援分支。
1. 在临时仓库模拟一次 amend
保存为 reflog_lab.py,运行 python reflog_lab.py。需要 Git 在 PATH 中。脚本只改动临时仓库。
from pathlib import Path
import subprocess
from tempfile import TemporaryDirectory
with TemporaryDirectory() as tmp:
def git(*args):
return subprocess.check_output(["git", *args], cwd=tmp, text=True).strip()
git("init", "-q")
git("config", "core.logAllRefUpdates", "true")
git("config", "user.name", "Reflog Lab")
git("config", "user.email", "lab@example.com")
git("config", "commit.gpgsign", "false")
git("config", "core.hooksPath", str(Path(tmp) / "empty-hooks"))
path = Path(tmp) / "notes.txt"
path.write_text("first draft", encoding="utf-8")
git("add", "notes.txt")
git("commit", "-qm", "first draft")
original = git("rev-parse", "HEAD")
path.write_text("revised draft", encoding="utf-8")
git("add", "notes.txt")
git("commit", "--amend", "-qm", "revise draft")
revised = git("rev-parse", "HEAD")
assert original != revised
candidate = git("rev-parse", "HEAD@{1}")
assert candidate == original
assert git("show", f"{candidate}:notes.txt") == "first draft"
git("branch", "rescue/draft", candidate)
assert git("show", "rescue/draft:notes.txt") == "first draft"
assert git("show", "HEAD:notes.txt") == "revised draft"
print("reflog: old commit found")
print("rescue/draft: first draft")
print("current HEAD: revised draft")
本地实测输出如下。
reflog: old commit found
rescue/draft: first draft
current HEAD: revised draft
2. 在实际仓库恢复已有提交
先运行 git reflog --date=iso,根据操作时间与 amend、reset 或 rebase 记录找候选。查看特定分支的移动记录时,使用 git reflog show <分支>。演练中的 HEAD@{1} 刚好指向上一次提交,平时的 checkout、reset 等操作会不断推进编号,因此找到候选后应抄下完整 ID。
| 操作 | 命令 |
|---|---|
| 检查候选提交及改动 | git show <提交ID> |
| 建立可以长期引用的分支 | git branch rescue/draft <提交ID> |
| 比较救援分支和当前版本 | git diff HEAD rescue/draft |
救援分支建立后,可以选择从旧版本恢复特定文件,或把需要的改动合入当前分支。reflog 属于本地仓库,重新克隆通常无法提供旧机器上的操作记录。记录可能过期,已经被清理的对象无法用此法找回。未进入提交的编辑应先查看编辑器历史和备份。
小结
先从 reflog 找提交 ID,再从该 ID 校验内容并创建救援引用。恢复过程中可以保留当前分支,等 diff 确认后再决定如何合入。
数据来源与检索时间
检索时间 2026-11-13。
| 来源 | URL | 对应内容 |
|---|---|---|
| Git reflog 手册 | https://git-scm.com/docs/git-reflog | 引用历史、时间选择器与过期行为 |
核验说明
- Git 2.54.0.windows.1 实测 amend 后按完整 ID 恢复旧提交。案例覆盖已提交的文件。