2005年,Git作为一个源代码管理系统的引入,从根本上改变了软件开发的过程。Git允许开发者维护其代码的修改历史,或称提交,并在出错时在几秒钟内恢复到之前的提交。它通过允许分支来保持不同功能的代码分开,以及无缝合并不同人的提交,使协作更加容易。它速度快,可扩展性强,比老的版本控制工具如Apache Subversion(SVN)和Concurrent Versions System(CVS)拥有更多的命令和灵活性。
然而,学习Git比学习SVN或CVS更复杂。复杂的命令和不太直观的用户界面有时会导致不需要的状态,包括一种叫做分离的HEAD的状态。在这篇文章中,我们将探讨什么是Git的分离HEAD状态,以及导致它的一些情况。然后,我们将演示如何在分离的HEAD中保存或丢弃更改,以便你能快速恢复这种情况。
脱离的 HEAD 是什么意思?
在 Git 中,HEAD 指的是当前签出的分支的最新提交。然而,在 detached HEAD 状态下,HEAD 并不指向任何分支,而是指向一个特定的提交或远程存储库。
下面是正常状态下的 Git HEAD 图,指向主分支的最新提交。
在这张图中,HEAD 指向当前分支中每个提交的最新提交和当前签出的分支。
在处理多个分支时,HEAD 也是一种常见的状态。
在这种情况下,你有两个分支,主分支和特性分支。由于你被检出到特性分支,HEAD指向那里。你可以用以下 Git 命令来创建这种情况。
git branch feature
git checkout feature
git commit -m “checked out to feature”
git checkout Main
git commit
git commit -m “Latest commit”
git checkout feature
在上面两张图中,HEAD 都指向当前签出的分支中的最新提交,这是它的正常状态。在 Git 中,你也可以签出某个特定的提交,这将导致 HEAD 的分离状态。继续前面的场景,如果你签出到主分支的第一个提交,你会看到 HEAD 现在是分离的。
在这种情况下,HEAD 并没有指向任何分支--它引用了一个提交。
可能导致 HEAD 脱离的情况
你可能主要通过两种情况发现自己处于分离的 HEAD 状态。
签出一个特定的安全哈希算法1(SHA-1)提交哈希值
签出到一个远程分支而不先获取它
我们已经证明,如果你检查出 SHA-1 提交哈希值,你将处于分离的 HEAD 状态。另一种导致脱离 HEAD 的情况是签出远程分支。如果你签出的是只读的origin(主)分支,那么你将处于分离的HEAD状态。
其他一些情况也会导致分离的 HEAD。例如,签出到一个特定的标签名或在任何给定的分支上添加^0
,都会导致分离的 HEAD 状态。
如何在分离的 HEAD 中保存更改
如果你发现自己处于分离的 HEAD 状态并很快意识到这一点,你可以通过签出前一个分支来迅速恢复。但如果你错误地处于分离的 HEAD 状态,然后在提交中执行提交,该怎么办?如果你在分离的 HEAD 状态下进行提交,是否意味着你的修改没有被保存?
完全不是。它只是意味着您当前没有连接到任何分支,因此您的 HEAD 是分离的。如果你想保留你在分离的 HEAD 状态下所做的修改,你可以通过三个简单的步骤来解决这个问题:创建一个新的分支,提交修改,以及合并修改。
创建一个新的分支
为了保存在分离的 HEAD 状态下提交的更改,你首先需要创建一个新的分支。
继续上面描述的方案,创建一个名为temp-branch
的新分支。一旦你创建了这个分支并签出到它,HEAD 就不再是分离的了。
签出到新的分支后,您可以提交修改,Git 会保留这些修改。
合并修改内容
现在,您可以签出到您想要修改的那个分支。在这个例子中,你想把这些改动合并到主分支。所以,你首先需要检出主分支,然后合并来自temp-branch
的修改,并添加最后的提交信息。
通过这些简单的步骤,你已经成功地保留了你的修改,并从 Git 的 detached HEAD 状态中恢复过来。
如何丢弃分离HEAD中的改动
如果您想丢弃脱离HEAD状态下的修改,您只需要签出到现有的或之前的分支。脱离的 HEAD 状态上的提交不会影响你现有的分支,Git 会将它们归档。
下图显示了这样一种情况:在进入分离的 HEAD 状态后,您做了两个您不想保留的提交。然后,您检出到主分支。虚线圈表示这些提交不再是任何分支的一部分,Git 将会删除它们。
请注意,一旦 Git 删除了您的分离的 HEAD 状态的提交,就没有办法再把它们找回来。然而,如果它们没有被删除,您可以检出该 SHA-1 提交哈希值,创建一个分支,并将其合并到所需的分支,以保留这些更改。
Git是一个很有价值的开发工具,比CVS和Subversion等老版本工具更受欢迎。尽管如此,它可能更复杂,更难掌握,有时会导致混乱的情况,如分离的 HEAD 状态。
如果你发现自己处于分离的HEAD状态,请记住,你总是可以通过创建并签出到一个新的分支,然后提交并合并所需分支中的修改来保存你的修改。如果你不想保存这些改动,你可以简单地签出到任何一个分支,Git 会删除这些提交的内容。
另外,Git 2.23 有一个新命令,git switch
。这不是一个新功能,而是一个替代git checkout
的命令,所以你可以在各分支之间切换,并创建一个新的分支。要从一个分支换到另一个分支,可以用git switch branchName
创建一个新的分支,然后用git switch -c branchName
命令切换到该分支。
虽然在分离的HEAD状态下发现你的代码并不理想,但你可以用这些方法来移动或删除你的提交,并迅速让你的项目回到正轨。