签出一个旧的提交和维护主分支上的头?

目前切换到另一个git提交(在同一分支上…实际上,在主分支!),我正在执行该命令

git checkout ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a 

现在,每当我做这个git告诉我,我现在是一个独立的头。 我如何去一个较旧的提交,仍然保持头在同一分支?

当我这样做的时候,大部分时间我都会结账到一个临时分支:

 git checkout -b temp-branch-name ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a 

然后我完成后,我只是删除分支

这取决于你签出提交时想要做什么。 如果你所做的只是检查出来,所以你可以build立或testing该修订版本,那么使用分离的头部就没有任何问题。 只要记住在进行任何提交(例如, git checkout master )之前签出一个实际的分支,这样你就不会创build不包含在任何分支中的提交。

但是,如果你想从这一点开始进行更多的提交,你应该创build一个分支。 如果你提交了一个没有被分支引用的提交,他们很容易丢失,并且最终会被git的垃圾回收器清理掉,因为没有任何引用。 您可以运行以下命令创build一个新的分支:

 git checkout -b newbranch ea3d5ed 

为了帮助可视化,下面是一些图表,展示了如何在分离的头上工作与在分支上工作的不同。

我们先从master ,A,B和C上的3个提交开始。master是当前分支,所以HEAD指向master ,指向提交C.

 ABC
 *  -  *  -  * < -  master < -  HEAD

现在,如果我们提交,git将创build一个具有C作为父项的提交(因为这是当前提交,通过masterHEAD指向),并将更新master指向新的提交。 现在我们所有的提交都在masterHEAD指向通过master的新提交。

 A B C D
 *  -  *  -  *  -  * < -  master < -  HEAD

现在让我们看看B,给我们一个分离的头。

 A B C D
 *  -  *  -  *  -  * < - 主
    ^
     \  - 头

一切正常,在这里; 我们可以看看所有的文件,构build我们的程序,testing它,甚至可以创build新的提交; 但是如果我们这样做了,那么就没有分支,所以我们不能指出任何分支在那个新的提交。 唯一指出的是HEAD

 A B C D
 *  -  *  -  *  -  * < - 主
     \
      * < - 头
      Ë

如果我们以后决定再次检查一下master ,那么就没有任何东西会提到E.

 A B C D
 *  -  *  -  *  -  * < -  master < -  HEAD
     \
      *
      Ë

由于没有任何指向它,它可能很难find,git认为提交没有引用被放弃(他们发生相当常见的,如果你rebase,或压缩补丁,或做其他有趣的历史操纵;他们通常代表被遗弃的补丁你不再关心)。 经过一段时间后,git会认为它是垃圾,在下一次垃圾收集运行时被丢弃。

所以,如果你觉得你要做更多的提交,你应该使用git checkout -b branch B创build一个分支并检查出来。 现在您的提交不会丢失,因为它们将被包含在一个分支中,您可以轻松地引用,并在以后进行合并。

 A B C D
 *  -  *  -  *  -  * < - 主
    ^
     \  - 分支< -  HEAD

如果你忘了这样做,并创build一个分支提交,没有必要担心。 您可以使用git checkout -b branch创build一个引用head修订的git checkout -b branch 。 如果你已经切换回master分支,并意识到你忘了一个stream浪的提交,你可以find它使用git reflog ,它会告诉你什么提交过去几天提交HEAD的历史。 任何仍然在reflog中的东西都不会被垃圾收集,并且通常引用被保存在reflog中至less30天。

如果你只是想回到以前的提交,而不做任何改变,你可以做

 git co <previous-commit-id> 

你会在这个命令后面的一个叫“(no branch)”的分支上。

通过确认

 git br 

在玩过以前提交的代码之后,您可以切换到您所在的分支

 git co <the-branch-you-were-on> 

“(不分行)”将被自动删除。 这样你就不需要创build一个临时分支。

Git的HEAD只是一个指针,表示工作目录中的内容。 如果你想检查一个不是分支头部的提交,你只需要redirect你的头​​指向那个提交。 这是没有办法的。 你可以在这个提交中创build一个临时分支,但HEAD将被引导远离主。

这是简短的解释。 下面的详细程度将有助于理解HEAD和主人是如何不同的:

通常,事情看起来像这样:

 C ← refs/heads/master ← HEAD ↓ B ↓ A 

也就是说:“C的父亲是B,B的父亲是A.分支主人指向C,而我目前已经检出了主人的内容。 另外,当我犯了,主人应该更新。“

为了彻底理解提交图,一些假设是隐含的。 也就是说,提交只涉及他们的父母,而分支的内容是那些可以通过父链接到达的提交(并且只有那些提交)。 工作树和索引的(未修改的)内容必须与HEAD指定的提交(间接(“符号”)或直接(“分离”))相对应。

因此,如果你想检查一个旧的提交,HEAD必须更新指向所需的提交。 git-checkout做到这一点:

 C ← refs/heads/master ↓ B ← HEAD ↓ A 

现在,你已经把你的分支留在了你身后,因为你正在看一些古老的东西。 这完全没问题,因为“独立的头脑”build议冷静地告诉你(强调我的):

您可以环顾四周,进行实验性更改并提交它们,并且可以放弃您在此状态进行的任何提交, 而不会通过执行另一个结算来影响任何分支

另一方面,虽然重置你的分支也得到了HEAD的地方,它会有一个非常不同的效果!

 C ↓ B ← refs/heads/master ← HEAD ↓ A 

提交C将变成垃圾,因为你已经声明你不希望它成为主分支的一部分了。

总而言之,你所要做的就是理解git的意思是“头”,它就是所在的位置,而不是任何给定的分支。 如果你的位置与分支的位置不一样,那就别无select,只能使用分离的HEAD。

(也许你也可以看一下GitHub,gitk或者gitweb来浏览提交历史logging,如果你的HEAD出轨继续让你感到厌烦。)

这个问题有点含糊,但是如果你只想改变工作树中的文件,你可以简单地这样做:

git checkout [commit|branch] -- .

如果您愿意的话,您可以进行更改并创build一个新的提交。 有时候这很有用。

我想我理解你的问题。 这是我发现解决它。 没有GUI解决scheme,只能用命令来解决,而且很简单。

第1步:创build您想要返回的旧提交的标记。

像标签v2.0

第2步:git结帐v2.0

在这里,现在你的头指着'v2.0'提交,但是master仍然指着最后一个提交。

C:\Program Files\Git\doc\git\html\git-checkout.html这个文件可能会帮到你

或者inputgit help <checkout>