首先,让我们澄清HEAD是什么以及当它被分离时意味着什么。
HEAD是当前检出提交的符号名称。当HEAD未被分离(“正常”的情况:您已经检出一个分支),HEAD实际上指向分支的“ref”,而该分支指向提交。因此,HEAD“附加”到分支上。当您创建新的提交时,HEAD所指向的分支将更新为指向新的提交。由于HEAD只是指向分支,因此HEAD会自动跟随分支。
git symbolic-ref HEAD
产生 refs/heads/master
检出了名为“master”的分支。
git rev-parse refs/heads/master
产生 17a02998078923f2d62811326d130de991d1a95a
该提交是主分支的当前末端或“head”。
git rev-parse HEAD
也产生 17a02998078923f2d62811326d130de991d1a95a
这就是“符号引用”的含义。它通过其他引用指向对象。
(符号引用最初是作为符号链接实现的,但后来更改为带有额外解释的普通文件,以便在没有符号链接的平台上使用。)
我们有
HEAD
→
refs/heads/master
→
17a02998078923f2d62811326d130de991d1a95a
当HEAD处于分离状态时,它直接指向一个提交,而不是通过分支间接地指向一个提交。你可以将分离的HEAD视为位于未命名分支上。
git symbolic-ref HEAD
会提示错误:fatal: ref HEAD is not a symbolic ref
git rev-parse HEAD
得到结果17a02998078923f2d62811326d130de991d1a95a
由于它不是符号引用,因此必须直接指向提交本身。
我们有
HEAD
→
17a02998078923f2d62811326d130de991d1a95a
分离的HEAD需要记住的重要事情是:如果它所指向的提交在其他引用无法到达的情况下,则在你检出其他提交时它将变成“悬空”的。最终,这样的悬空提交将通过垃圾回收过程被剪枝(默认情况下,它们被保留至少两周,并可能通过HEAD的reflog被保留更长时间)。
1使用分离的HEAD进行“正常”工作完全没有问题,只需要跟踪你正在做什么,以避免从reflog中挖掘丢失的历史记录。
交互式变基的中间步骤使用分离的HEAD进行(部分是为了避免污染活动分支的reflog)。如果完成整个变基操作,它将使用变基操作的累积结果更新您的原始分支,并重新附加HEAD到原始分支。我猜你从未完全完成变基过程;这会让你拥有一个指向最近被变基操作处理的提交的分离HEAD。
要从您的情况中恢复,您应该创建一个分支,该分支指向当前由您的分离HEAD指向的提交:
git branch temp
git checkout temp
(这两个命令可以缩写为git checkout -b temp
)
这将把您的HEAD重新附加到新的temp
分支。
接下来,您应该将当前提交(及其历史记录)与您期望工作的正常分支进行比较:
git log --graph --decorate --pretty=oneline --abbrev-commit master origin/master temp
git diff master temp
git diff origin/master temp
你可能想要尝试日志选项:添加-p
,省略--pretty=…
以查看整个日志消息等。
如果你的新temp
分支看起来不错,你可能想要更新(例如)master
指向它:
git branch -f master temp
git checkout master
(这两个命令可以缩写为 git checkout -B master temp
)
然后您可以删除临时分支:
git branch -d temp
最后,您可能希望推送重新建立的历史记录:
git push origin master
如果远程分支无法“快进”到新提交(即您删除或重写某些现有提交或以其他方式重写了某些历史记录),则可能需要在此命令的末尾添加--force
才能推送。
如果您正在进行rebase操作,则应该清理它。您可以通过查找目录.git/rebase-merge/
来检查是否正在进行rebase操作。您可以通过删除该目录(例如,如果您不再记得活动rebase操作的目的和上下文)来手动清理正在进行的rebase。通常,您会使用git rebase --abort
,但那会做一些额外的重置,您可能要避免这样做(它将HEAD移回原始分支并将其重置回原始提交,这将撤消我们上面完成的一些工作)。
我重置了一些文件以将它们移出提交暂存区
这部分的操作吗?抱歉问这么多问题 :) - manojlds