git 检查旧提交并维护主分支上的头部?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5658302/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Checking out an old commit and maintaining the head on the master branch?
提问by devoured elysium
Currently for switching to another git commit (on the same branch...actually, on the master branch!), I'm executing the command
目前为了切换到另一个 git commit(在同一个分支上......实际上,在主分支上!),我正在执行命令
git checkout ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a
Now, every time I do this git tells me that I'm now with a detached head. How do I go to an older commit and still maintain the head on the same branch?
现在,每次我做这个 git 都会告诉我,我现在的头已经脱离了。如何转到较旧的提交并仍然在同一分支上保持头部?
回答by Nick Canzoneri
Most of the time when I do this I checkout to a temp branch:
大多数情况下,当我这样做时,我会结帐到临时分支:
git checkout -b temp-branch-name ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a
Then after I'm done i just delete the branch
然后在我完成后我只是删除了分支
回答by Brian Campbell
It depends on what you want to do when you checkout that commit. If all you're doing is checking it out so you can build or test that revision, then there's nothing wrong with working with a detached head. Just remember to check out an actual branch before you make any commits (git checkout master
, for example), so that you don't create commits that are not included in any branch.
这取决于您在检出该提交时想要做什么。如果您所做的只是检查它以便您可以构建或测试该修订版,那么使用分离头就没有问题。请记住在进行任何提交之前检查实际分支(git checkout master
例如),这样您就不会创建未包含在任何分支中的提交。
If, however, you want to make more commits starting from that point, you should create a branch. If you make commits that are not referenced by a branch, they can easily get lost, and will eventually be cleaned up by git's garbage collector, as nothing refers to them. You can create a new branch by running:
但是,如果您想从该点开始进行更多提交,则应该创建一个分支。如果你提交的提交没有被分支引用,它们很容易丢失,最终会被 git 的垃圾收集器清理,因为没有任何内容引用它们。您可以通过运行来创建一个新分支:
git checkout -b newbranch ea3d5ed
To help visualize, here's are some diagrams demonstrating how working on a detached head differs from working on a branch.
为了帮助形象化,这里有一些图表展示了在分离头上工作与在分支上工作有何不同。
Let's start out with 3 commits on master
, A, B, and C. master
is the current branch, so HEAD
points to master
, which points to commit C.
让我们从 3 次提交开始master
,A、B 和 C。master
是当前分支,所以HEAD
指向master
,它指向提交 C。
A B C *--*--* <-- master <-- HEAD
Now if we commit, git will create a commit that has C as a parent (because that's the current commit, pointed to from HEAD
via master
), and will update master
to point to that new commit. All of our commits are now in master
, and HEAD
points to the new commit through master
.
现在,如果我们提交,git 将创建一个以 C 作为父项的提交(因为这是当前提交,从HEAD
via指向master
),并将更新master
以指向该新提交。我们所有的提交现在都在master
,并通过HEAD
指向新的提交master
。
A B C D *--*--*--* <-- master <-- HEAD
Now let's check out B, giving us a detached HEAD
.
现在让我们看看 B,给我们一个分离的HEAD
.
A B C D *--*--*--* <-- master ^ \-- HEAD
Everything works fine here; we can look at all of the files, build our program, test it, etc. We can even create new commits; but if we do so, there's no branch that we're on, so we can't point any branch at that new commit. The only thing pointing at it is HEAD
:
这里一切正常;我们可以查看所有文件,构建我们的程序,测试它等等。我们甚至可以创建新的提交;但是如果我们这样做,就没有我们所在的分支,所以我们不能在那个新提交上指向任何分支。唯一指向它的是HEAD
:
A B C D *--*--*--* <-- master \ * <-- HEAD E
If we later decide to check out master
again, there will be nothing referring to E.
如果我们稍后决定master
再次结帐,则不会有任何与 E 相关的内容。
A B C D *--*--*--* <-- master <-- HEAD \ * E
Since there's nothing referring to it, it can be hard to find, and git considers commits with no references to be abandoned (they happen quite commonly if you rebase, or squash patches in, or do other fun history manipulation; they usually represent abandoned patches that you no longer care about). After a certain amount of time, git will consider it garbage, to be discarded the next time garbage collection runs.
由于没有任何引用它,因此可能很难找到,并且 git 认为没有引用的提交将被放弃(如果您变基、压缩补丁或进行其他有趣的历史操作,它们通常会发生;它们通常代表被放弃的补丁你不再关心)。一定时间后,git 会认为它是垃圾,在下次垃圾收集运行时将其丢弃。
So, instead of checking out a bare revision and getting a detached head, if you feel like you are going to make more commits, you should use git checkout -b branch B
to create a branch and check it out. Now your commits won't be lost, as they will be included in a branch, that you can easily refer to, and merge later on.
因此,与其检查一个裸修订版并获得一个独立的头部,如果您觉得要进行更多提交,您应该使用git checkout -b branch B
来创建一个分支并检查它。现在您的提交不会丢失,因为它们将包含在一个分支中,您可以轻松引用该分支并稍后合并。
A B C D *--*--*--* <-- master ^ \-- branch <-- HEAD
If you forget to do this, and create commits off a branch, there's no need to worry. You can create a branch referring to the head revision with git checkout -b branch
. If you have already switched back to the master
branch, and realize that you forgot a stray commit, you can find it using git reflog
, which will show you a history of what commits HEAD
has pointed to over the last few days. Anything that's still in the reflog will not be garbage collected, and generally references are kept in the reflog for at least 30 days.
如果您忘记执行此操作并从分支创建提交,则无需担心。您可以使用git checkout -b branch
. 如果您已经切换回master
分支,并意识到您忘记了一个流浪提交,您可以使用 找到它git reflog
,这将显示HEAD
过去几天提交指向的历史记录。仍然在 reflog 中的任何内容都不会被垃圾收集,并且通常引用会在 reflog 中保留至少 30 天。
回答by Zack Xu
If you simply want to return to an earlier commit to play with it without making any changes, you can do
如果您只是想返回到较早的提交来使用它而不进行任何更改,您可以这样做
git co <previous-commit-id>
you'll will be on a branch called "(no branch)" after this command.
执行此命令后,您将位于名为“(无分支)”的分支上。
Confirm this by
确认这一点
git br
After you've played with this previously committed code, you can switch to the branch you were on by
在你玩过这个之前提交的代码之后,你可以切换到你所在的分支
git co <the-branch-you-were-on>
The "(no branch)" will be deleted automatically. This way you don't need to create a temporary branch.
“(无分支)”将被自动删除。这样您就不需要创建临时分支。
回答by Josh Lee
Git's HEAD is simply a pointer that says what's in the working directory. If you want to check out a commit which is not the head of a branch, you simply have to redirect your HEAD to point at that commit. There's no way around it. You can create a temporary branch at that commit, but HEAD will be directed away from master nonetheless.
Git 的 HEAD 只是一个指示工作目录中内容的指针。如果你想检查一个不是分支头的提交,你只需要重定向你的 HEAD 指向那个提交。没有办法解决。您可以在该提交时创建一个临时分支,但 HEAD 将远离 master。
That's the short explanation. The verbosity below will hopefully aid in understanding how HEAD and master are different:
这就是简短的解释。下面的详细信息有望有助于理解 HEAD 和 master 的不同之处:
Normally, things look like this:
通常情况下,事情是这样的:
C ← refs/heads/master ← HEAD
↓
B
↓
A
Which is to say: “The parent of C is B, and the parent of B is A. The branch master is pointing to C, and I currently have checked out the contents of master. In addition, when I commit, master shall be updated.”
也就是说:“C的父节点是B,B的父节点是A,分支master指向C,我目前已经查看到master的内容。另外,当我提交时,master会被更新。”
Some assumptions are implicit in this which are necessary for a thorough understanding of the commit graph. Namely, commits refer only to their parents, and the contents of a branch are those commits (and only those commits) which can be reached by following the parent links. The (unmodified) contents of the working tree and the index must correspond to the commit named by HEAD, either indirectly (“symbolic”) or directly (“detached”).
其中隐含了一些假设,这些假设对于彻底理解提交图是必要的。即,提交仅指其父级,而分支的内容是通过父级链接可以访问的那些提交(并且仅那些提交)。工作树和索引的(未修改的)内容必须与 HEAD 命名的提交相对应,间接(“符号”)或直接(“分离”)。
Thus, if you want to check out an old commit, the HEAD must be updated to point to the desired commit. git-checkout
does just that:
因此,如果您想检出旧提交,则必须更新 HEAD 以指向所需的提交。git-checkout
就是这样:
C ← refs/heads/master
↓
B ← HEAD
↓
A
Now, you've left your branch behind you, since you're looking at something old. That's perfectly OK, as the “detached head” advice tell you calmly (emphasis mine):
现在,你已经把你的分支抛在了身后,因为你正在看一些旧的东西。这完全没问题,正如“超然头脑”的建议冷静地告诉你(强调我的):
You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branchesby performing another checkout.
您可以环顾四周,进行实验性更改并提交它们,并且您可以通过执行另一次检出来放弃您在此状态下所做的任何提交,而不会影响任何分支。
On the other hand, while resetting your branch also gets HEAD where it needs to be, it would have a very different effect!
另一方面,虽然重置您的分支也会将 HEAD 放在它需要的位置,但它会产生非常不同的效果!
C
↓
B ← refs/heads/master ← HEAD
↓
A
The commit C will become garbage, since you have declared that you do not wish for it to be part of the master branch anymore.
提交 C 将成为垃圾,因为您已经声明您不希望它再成为 master 分支的一部分。
In short, all you have to do is understand what git means by “HEAD” — it's where youare, not where any given branch is. And if where youare is not the same as where a branch is, there is no choice but to use a detached HEAD.
简而言之,您所要做的就是了解 git 的“HEAD”是什么意思——它是您所在的位置,而不是任何给定分支所在的位置。如果您所在的位置与分支所在的位置不同,则别无选择,只能使用分离的 HEAD。
(Perhaps also look into GitHub, gitk, or gitweb to browse the commit history, if derailing your HEAD continues to irk you.)
(也许还可以查看 GitHub、gitk 或 gitweb 以浏览提交历史记录,如果让您的 HEAD 脱轨继续让您感到厌烦。)
回答by Lari Hotari
The question is a bit vague, but if you want to just change files in your working tree, you can simply do this:
这个问题有点含糊,但如果您只想更改工作树中的文件,您可以简单地执行以下操作:
git checkout [commit|branch] -- .
git checkout [commit|branch] -- .
You can then stage the changes and create a new commit if you wish. This is pretty useful sometimes.
然后,您可以暂存更改并根据需要创建新的提交。这有时非常有用。
回答by Lion Lai
I think I understand your questions. Here is what I found to solve it. and there is no GUI solution of it, you can only use command to solve it, and it's really simple.
我想我明白你的问题。这是我找到的解决方法。并且没有GUI的解决方案,只能用命令来解决,而且很简单。
step 1: creat a tag of the old commit which you want to go back.
第 1 步:创建要返回的旧提交的标签。
like tag v2.0
喜欢标签 v2.0
step 2: git checkout v2.0
第 2 步:git checkout v2.0
here it is, now your HEAD is pointing at 'v2.0' commit, but master is still pointing at last commit.
在这里,现在您的 HEAD 指向“v2.0”提交,但 master 仍然指向最后一次提交。
C:\Program Files\Git\doc\git\html\git-checkout.html
this document may help you
C:\Program Files\Git\doc\git\html\git-checkout.html
这份文件可能对你有帮助
or type git help < checkout >
或者输入 git help < checkout >