签出一个旧的提交和维护主分支上的头?
目前切换到另一个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作为父项的提交(因为这是当前提交,通过master
从HEAD
指向),并将更新master
指向新的提交。 现在我们所有的提交都在master
, HEAD
指向通过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>