检出旧的提交并保持master分支的头吗?

问题描述

| 当前要切换到另一个git commit(在同一分支上...实际上是在master分支上!),我正在执行命令
git checkout ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a
现在,每次执行此操作时,git都会告诉我,我现在头顶分离。我该如何进行较早的提交,并且仍然将头保持在同一分支上?     

解决方法

在大多数情况下,我会签出到临时分支:
git checkout -b temp-branch-name ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a
然后,我完成后就删除分支     ,这取决于签出该提交时要执行的操作。如果您正在做的只是检查出来,以便您可以构建或测试该修订版,那么使用分离的头没有任何问题。只需记住在进行任何提交(例如,
git checkout master
)之前签出一个实际的分支,这样就不会创建未包含在任何分支中的提交。 但是,如果您希望从那时开始进行更多提交,则应创建一个分支。如果您进行的提交未被分支引用,则它们很容易丢失,最终将被git的垃圾收集器清除,因为没有东西引用它们。您可以通过运行以下命令创建一个新分支:
git checkout -b newbranch ea3d5ed
为了便于可视化,这里有一些图表,展示了在分离的头上进行处理与在分支上进行处理有何不同。 让我们以在
master
,A,B和C上的3个提交开始。
master
是当前分支,所以
HEAD
指向
master
,它指向提交C。 A B C *-*-* <-主<-头 现在,如果我们提交,git将创建一个以C作为父提交的提交(因为这是当前提交,从
HEAD
master
指向),并将更新
master
指向该新提交。现在,我们所有的提交都在
master
中,而
HEAD
通过
master
指向新的提交。 A B C D *-*-*-* <-主<-头 现在让我们检查B,给我们一个独立的
HEAD
。 A B C D *-*-*-* <-主    ^     \\-头 这里一切正常。我们可以查看所有文件,构建程序,对其进行测试,等等。我们甚至可以创建新的提交。但是,如果这样做,就没有分支,因此我们无法将任何分支指向该新提交。唯一指向它的是
HEAD
: A B C D *-*-*-* <-主     \\      * <-头      Ë 如果我们以后决定再次检出
master
,将没有任何内容涉及E。 A B C D *-*-*-* <-主<-头     \\      *      Ë 由于没有任何引用,因此很难找到它,并且git认为没有引用的提交将被放弃(如果您变基,压缩补丁或进行其他有趣的历史操作,它们会很常见;通常代表您不再关心的废弃补丁)。在一定时间后,git会将其视为垃圾,在下次运行垃圾收集时将其丢弃。 因此,如果您感觉要进行更多提交,而不是签出裸露的修订版本并弄乱了头,应该使用should17ѭ创建分支并将其签出。现在,您的提交不会丢失,因为它们将包含在一个分支中,您可以轻松地引用它,并在以后合并。 A B C D *-*-*-* <-主    ^     \\-分支<-HEAD 如果您忘记执行此操作,而是在分支上创建了提交,则无需担心。您可以使用ѭ18create引用主修订版来创建分支。如果您已经切换回
master
分支,并且意识到自己忘记了一个杂项提交,则可以使用ѭ20find找到它,它将向您显示
HEAD
在过去几天中指出的提交的历史。仍保留在reflog中的所有内容都不会被垃圾回收,通常,引用在reflog中至少保留30天。     ,如果您只是想返回到较早的提交而不进行任何更改就可以使用它,则可以执行
git co <previous-commit-id>
执行此命令后,您将位于一个名为\“(无分支)\”的分支上。 通过确认
git br
在使用了之前提交的代码后,您可以切换到您所在的分支
git co <the-branch-you-were-on>
\“(无分支)\”将被自动删除。这样,您无需创建临时分支。     ,Git的HEAD只是一个指示工作目录中内容的指针。如果要签出不是分支头的提交,则只需重定向HEAD指向该提交即可。没有办法解决。您可以在该提交处创建一个临时分支,但是HEAD仍将与master分开。 这就是简短的解释。以下详细信息将有助于理解HEAD和master的不同之处: 通常情况如下:
C ← refs/heads/master ← HEAD 
↓
B
↓
A
就是说:“ C的父是B,B的父是A。分支master指向C,目前我已检出master的内容。另外,当我提交时,master将会被更新。” 其中一些假设是隐含的,这些假设对于全面理解提交图是必需的。即,提交仅引用其父级,而分支的内容是可以通过跟随父级链接到达的那些提交(并且仅是那些提交)。工作树(未修改)的内容和索引必须与HEAD命名的提交相对应,可以是间接(“符号”)或直接(“分离”)。 因此,如果您想签出旧的提交,则必须更新HEAD以指向所需的提交。
git-checkout
只是这样做:
C ← refs/heads/master 
↓
B ← HEAD
↓
A
现在,由于您正在查看旧的东西,因此您已经将分支机构抛在了身后。完全可以,“冷静的头脑”建议会冷静地告诉您(强调我的意思):   您可以环顾四周,进行实验性更改并将其提交,也可以放弃在此状态下所做的任何提交,而不会通过执行另一次签帐而影响任何分支。 另一方面,在重置分支的同时也会使HEAD到达需要的位置,但效果会大不相同!
C
↓
B ← refs/heads/master ← HEAD
↓
A
提交C将变为垃圾,因为您已经声明不希望它成为master分支的一部分。 简而言之,您要做的就是了解git对“ HEAD”的含义-它在您所在的位置,而不是任何给定分支的位置。而且,如果您所在的位置与分支所在的位置不同,则别无选择,只能使用分离的HEAD。 (如果您的HEAD出轨仍然让您感到烦恼,也许还可以查看GitHub,gitk或gitweb来浏览提交历史记录。)     ,这个问题有点含糊,但是如果您只想更改工作树中的文件,则只需执行以下操作:
git checkout [commit|branch] -- .
然后,您可以进行更改并根据需要创建新的提交。有时候这很有用。     ,我想我理解你的问题。这是我发现要解决的问题。而且它没有GUI解决方案,您只能使用命令来解决它,而且非常简单。 步骤1:为您要返回的旧提交创建标签。 像标签v2.0 步骤2:git checkout v2.0 就是这样,现在您的HEAD指向\'v2.0 \'提交,但是master仍指向最后的提交。
C:\\Program Files\\Git\\doc\\git\\html\\git-checkout.html
本文档可能会为您提供帮助 或输入git help