从Git分离的HEAD状态恢复的方法

2,118 阅读6分钟

2005年,Git作为一个源代码管理系统的引入,从根本上改变了软件开发的过程。Git允许开发者维护其代码的修改历史,或称提交,并在出错时在几秒钟内恢复到之前的提交。它通过允许分支来保持不同功能的代码分开,以及无缝合并不同人的提交,使协作更加容易。它速度快,可扩展性强,比老的版本控制工具如Apache Subversion(SVN)和Concurrent Versions System(CVS)拥有更多的命令和灵活性。

然而,学习Git比学习SVN或CVS更复杂。复杂的命令和不太直观的用户界面有时会导致不需要的状态,包括一种叫做分离的HEAD的状态。在这篇文章中,我们将探讨什么是Git的分离HEAD状态,以及导致它的一些情况。然后,我们将演示如何在分离的HEAD中保存或丢弃更改,以便你能快速恢复这种情况。

脱离的 HEAD 是什么意思?

在 Git 中,HEAD 指的是当前签出的分支的最新提交。然而,在detachedHEAD 状态下,HEAD 并不指向任何分支,而是指向一个特定的提交或远程存储库。

下面是正常状态下的 Git HEAD 图,指向主分支的最新提交。

Git HEAD pointing to the latest commit in main

在这张图中,HEAD 指向当前分支中每个提交的最新提交和当前签出的分支。

在处理多个分支时,HEAD 也是一种常见的状态。

Git HEAD pointing to the latest commit in feature branch

在这种情况下,你有两个分支,主分支和特性分支。由于你被检出到特性分支,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 现在是分离的。

Git detached HEAD pointing to a previous commit

在这种情况下,HEAD 并没有指向任何分支--它引用了一个提交。

可能导致 HEAD 脱离的情况

你可能主要通过两种情况发现自己处于分离的 HEAD 状态。

  1. 签出一个特定的安全哈希算法1(SHA-1)提交哈希值
  2. 签出到一个远程分支而不先获取它

我们已经证明,如果你检查出 SHA-1 提交哈希值,你将处于分离的 HEAD 状态。另一种导致脱离 HEAD 的情况是签出远程分支。如果你签出的是只读的origin(主)分支,那么你将处于分离的HEAD状态。

其他一些情况也会导致分离的 HEAD。例如,签出到一个特定的标签名或在任何给定的分支上添加^0 ,都会导致分离的 HEAD 状态。

如何在分离的 HEAD 中保存更改

如果你发现自己处于分离的 HEAD 状态并很快意识到这一点,你可以通过签出前一个分支来迅速恢复。但如果你错误地处于分离的 HEAD 状态,然后在提交中执行提交,该怎么办?如果你在分离的 HEAD 状态下进行提交,是否意味着你的修改没有被保存?

完全不是。它只是意味着您当前没有连接到任何分支,因此您的 HEAD 是分离的。如果你想保留你在分离的 HEAD 状态下所做的修改,你可以通过三个简单的步骤来解决这个问题:创建一个新的分支,提交修改,以及合并修改。

创建一个新的分支

为了保存在分离的 HEAD 状态下提交的更改,你首先需要创建一个新的分支。

Create and check out to a new branch

继续上面描述的方案,创建一个名为temp-branch 的新分支。一旦你创建了这个分支并签出到它,HEAD 就不再是分离的了。

提交修改

签出到新的分支后,您可以提交修改,Git 会保留这些修改。

Commit changes to the new branch

合并修改内容

现在,您可以签出到您想要修改的那个分支。在这个例子中,你想把这些改动合并到主分支。所以,你首先需要检出主分支,然后合并来自temp-branch 的修改,并添加最后的提交信息。

Merge changes to the main branch

通过这些简单的步骤,你已经成功地保留了你的修改,并从 Git 的 detached HEAD 状态中恢复过来。

如何丢弃分离HEAD中的改动

如果您想丢弃脱离HEAD状态下的修改,您只需要签出到现有的或之前的分支。脱离的 HEAD 状态上的提交不会影响你现有的分支,Git 会将它们归档。

下图显示了这样一种情况:在进入分离的 HEAD 状态后,您做了两个您不想保留的提交。然后,您检出到主分支。虚线圈表示这些提交不再是任何分支的一部分,Git 将会删除它们。

Discard changes in detached HEAD

请注意,一旦 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状态下发现你的代码并不理想,但你可以用这些方法来移动或删除你的提交,并迅速让你的项目回到正轨。