如果 Git 显示 HEAD detached,你的文件仍然检出在某个提交上,但在你创建分支之前,新的提交不会推进任何分支。在 Mac 上,打开终端,前往仓库,检查是否有未提交的更改,然后要么将当前工作附加到一个新分支,要么安全地返回你原本打算使用的分支。Git 的 switch 命令同时支持这两种途径。Apple 的“终端”使用指南介绍了如何打开终端;Git 的 switch 文档记录了分支和游离 HEAD 的行为。

1. 检查 Git 当前检出的内容

从“应用程序”>“实用工具”打开“终端”,然后切换到你的仓库目录。将示例路径替换为你项目所在的文件夹;使用引号可支持路径中包含空格。macOS 终端默认使用 zsh,这些命令在 zsh 以及常用 shell 中均可正常运行。

cd "/path/to/your/repository"
git status

如果 git status 显示“HEAD detached”或“不在任何分支上(not on any branch)”,则表明你正处于游离 HEAD 状态。Git 直接检出了某个提交,而不是某个分支。该提交和工作文件依然可用;风险在于在此处生成的提交不会自动附加到任何分支上。Git 的 checkout 手册描述了这种状态,以及分支如何保留在此状态下生成的提交。

在切换到任何地方之前,请先阅读 git status 的其余部分。如果它列出了已修改(modified)或未跟踪(untracked)的文件,这些就是尚未提交的更改。你可以继续就地工作,也可以立即创建一个分支;在当前提交处创建分支本身并不会丢弃修改。在恢复过程中,请避免使用 force(强制)或 discard(丢弃)选项。

2. 将当前工作保存在分支上

如果你在游离状态下进行了提交,或者想从当前完全相同的快照继续工作,请在当前位置创建一个分支:

git switch -c recovered-work
git status

请使用具有描述性的分支名称替换 recovered-work。Git 会在当前提交处创建该分支并切换到该分支,这样后续的提交就会属于该分支。确认 git status 现在显示了该分支名称。当游离状态下的快照正是你想保留的工作时,这是最简捷的恢复方法。Git 文档将 switch -c 定义为创建并切换到分支。

如果你有未提交的修改,在创建分支时它们通常会保留在工作区中。随后请检查 git status 以验证它们是否仍然存在。如果命令因同名分支已存在而报错,请选择其他名称;不要添加 -C,因为这可能会将现有分支重置为新的起始点。

3. 返回你打算使用的分支

如果你只是查看了某个提交,并没有需要保留的更改,只需按名称切换到目标分支即可。例如:

git switch main

如果不是 main,请使用你仓库的实际分支名称。如果 Git 提示本地更改会被覆盖,请停下来并先保留它们:如上所述创建一个恢复分支,或者提交这些工作。当切换分支会导致丢失本地修改时,Git 通常会阻止该操作;恢复期间请避免使用 --discard-changes,因为这会重置暂存区和工作区以匹配目标分支。The git switch 手册解释了这些保护机制和选项。

如果你只是误切出了分支,git switch - 可以返回到 Git 最近切换历史记录中的上一个分支或提交。切换后请检查 git status,以确认你当前所在的位置。

4. 找回之前遗留的游离提交

如果你已经切换到其他地方,并且记不清游离提交的具体位置,可以查看本地 reflog:

git reflog

reflog 记录了本地引用的近期更新,而 HEAD 的 reflog 还记录了分支切换历史。寻找与你的工作相符的提交信息或时间的条目。如果想在不更改任何内容的情况下查看某个候选提交,请从 reflog 中复制其简短提交 ID 并运行:

git show --stat COMMIT_ID

将 COMMIT_ID 替换为实际的 ID——不要逐字输入占位符。如果是正确的提交,请在该提交处创建一个分支以将其保留:

git switch -c recovered-work COMMIT_ID

这将使该提交重新可以通过分支访问。reflog 属于本地记录,并且条目可能会过期;Git 的文档将其描述为近期引用更新的记录,并指出了其过期行为。参见 git reflog。

5. 继续操作前进行验证

运行 git status 和 git log -1 --oneline 确认当前分支和最新提交。如果你的工作之前尚未提交,请检查其文件是否仍显示在 status 输出中。如果 reflog 中没有出现候选条目,恢复工作可能需要检查悬空对象(dangling objects);这是一个单独的、需要更加谨慎的步骤,在搜索期间应避免运行诸如 git gc 之类的清理命令。

处于游离 HEAD 状态并不意味着你的工作丢失了。正确的恢复方式取决于你是需要保留当前提交、返回现有分支,还是在切走之后找回某个提交。在正确的提交处创建分支,就能为 Git 提供一个命名的引用,供你在后续继续跟进。

参考来源