我对Git的分支复杂性很陌生。我总是在一个分支上工作,提交更改,然后定期推送到远程源。

最近的某个时候,我对一些文件进行了重置,以使它们脱离提交阶段,后来又进行了重新base-I,以消除最近的几个本地提交。现在我处于一种我不太理解的状态。

在我的工作区,git日志显示了我所期望的一切——我在正确的火车上,有我不想要的提交,还有新的提交,等等。

但我只是推到了远程存储库,这是不同的——我在rebase中删除的几个提交被推送了,而本地提交的新提交不在那里。

我认为“master/origin”与HEAD是分离的,但我不完全清楚这意味着什么,如何使用命令行工具将其可视化,以及如何修复它。


当前回答

如果您在master上执行了一些提交,并且只想在那里“向后合并”master(即您希望master指向HEAD),那么一行代码将是:

git checkout -B master HEAD

这将创建一个名为master的新分支,即使它已经存在(这就像移动master,这就是我们想要的)。新创建的分支被设置为指向HEAD,也就是您所在的位置。新的分支已签出,因此之后您将成为master。

我发现这在子存储库的情况下特别有用,而子存储库也经常处于分离状态。

其他回答

将分离的提交放到它自己的分支上

只需运行git checkout-b mynewbranch。

然后运行gitlog,您将看到这个新分支上的commit现在是HEAD。

首先,让我们澄清HEAD是什么,以及当它被分离时它意味着什么。

HEAD是当前签出提交的符号名称。当HEAD未分离时(“正常”1情况:您签出了一个分支),HEAD实际上指向分支的“ref”,而分支指向提交。因此,HEAD“连接”到分支。当您进行新的提交时,HEAD指向的分支将更新为指向新的提交。HEAD会自动跟随,因为它只指向分支。

git符号ref HEAD产生refs/heads/master将签出名为“master”的分支。git rev parse refs/heads/master产量17a02998078923f2d62811326d130de991d1a95a该提交是主分支的当前提示或“头”。git-rev-parse HEAD还生成17a02998078923f2d62811326d130de991d1a95a这就是“符号引用”的含义。它通过其他引用指向对象。(符号引用最初是作为符号链接实现的,但后来改为具有额外解释的普通文件,以便可以在没有符号链接的平台上使用。)

我们有头→ 参考/主管/主管→ 17a02998078923f2d62811326d130代码991d1a95a

分离HEAD时,它直接指向提交,而不是通过分支间接指向提交。你可以把一个独立的HEAD看作是在一个未命名的分支上。

git符号ref HEAD失败,出现致命错误:ref HEAD不是符号refgit-rev-parse HEAD生成17a02998078923f2d62811326d130de991d1a95a由于它不是符号引用,因此必须直接指向提交本身。

我们有头→ 17a02998078923f2d62811326d130代码991d1a95a

使用分离的HEAD需要记住的重要一点是,如果它指向的提交是未被引用的(没有其他引用可以访问它),那么当您签出其他提交时,它将变为“悬空”。最终,这些悬空的提交将通过垃圾收集过程被删除(默认情况下,它们至少保留2周,并且可以通过HEAD的reflog引用而保留更长时间)。

1.使用分离的HEAD进行“正常”工作是非常好的,您只需跟踪正在进行的操作,以避免从重新记录中提取掉的历史。


交互式rebase的中间步骤是用分离的HEAD完成的(部分是为了避免污染活动分支的reflog)。如果您完成了完全重基操作,它将使用重基操作的累积结果更新原始分支,并将HEAD重新附加到原始分支。我的猜测是,你从未完全完成重新启动过程;这将留下一个分离的HEAD,指向rebase操作最近处理的提交。

要从您的情况中恢复,您应该创建一个分支,该分支指向分离的HEAD当前指向的提交:

git branch temp
git checkout temp

(这两个命令可以缩写为gitcheckout-b temp)

这将把HEAD重新连接到新的临时分支。

接下来,您应该将当前提交(及其历史记录)与预期要处理的正常分支进行比较:

git log --graph --decorate --pretty=oneline --abbrev-commit master origin/master temp
git diff master temp
git diff origin/master temp

(您可能希望尝试使用日志选项:add-p、off--pretty=…查看整个日志消息等)

如果新的临时分支看起来不错,您可能需要更新(例如)master以指向它:

git branch -f master temp
git checkout master

(这两个命令可以缩写为git checkout-B master temp)

然后可以删除临时分支:

git branch -d temp

最后,您可能希望推动重建的历史:

git push origin master

如果远程分支无法“快速转发”到新提交(即,您删除或重写了一些现有提交,或以其他方式重写了一些历史记录),则可能需要在该命令的末尾添加--force以进行推送。

如果你正在进行一个重设基操作,你可能应该清理它。您可以通过查找目录.git/rebasemerge/来检查是否正在进行重基。您可以通过删除该目录来手动清理正在进行的重基(例如,如果您不再记得活动重基操作的目的和上下文)。通常您会使用gitrebase--abort,但这会进行一些您可能希望避免的额外重置(它会将HEAD移回原始分支,并将其重置回原始提交,这将撤消我们上面所做的一些工作)。

我今天刚刚遇到这个问题,我很确定我通过以下方式解决了这个问题:

git branch temp
git checkout master
git merge temp

当我在工作电脑上发现如何做到这一点时,现在我在个人电脑上遇到了同样的问题。所以我必须等到星期一我回到工作电脑前,看看我是怎么做到的。

以下操作对我有效(仅使用分支主机):

git push origin HEAD:master
git checkout master        
git pull

第一个将分离的HEAD推到远程原点。

第二个移动到分支主机。

第三个恢复连接到分支主机的HEAD。

如果推送被拒绝,第一个命令可能会出现问题。但这将不再是分离头的问题,而是关于分离头不知道一些远程更改的事实。

如果你有一个主分支,想回到“开发”或功能,就这样做:

git checkout origin/develop

注意:检查起源/发展。

您处于分离HEAD状态。你可以四处看看,做实验更改并提交它们,您可以放弃在此过程中所做的任何提交通过执行另一个签出,状态而不影响任何分支。。。

then

git checkout -b develop

它有效:)