简体   繁体   English

Git在新克隆的仓库上分离了头部

[英]Git detached head on newly cloned repo

I just cloned a repo and tried to checkout a branch. 我只是克隆了一个仓库,并试图签出一个分支。 The branch is checked out in detached head mode! 分支以分离头模式检出! I don't understand why it should do that. 我不明白为什么要这么做。 I just cloned the repository. 我刚刚克隆了存储库。

$ git checkout PATCH_branch
Note: checking out 'PATCH_branch'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

git checkout -b <new-branch-name>

HEAD is now at 896c259... xxxxxxxxxxxxxxxxxxxxxxxxxxx

I figured perhaps I can create a local branch and make it track the remote. 我想也许我可以创建一个本地分支并使其跟踪远程服务器。 So I did: 所以我做了:

$ git checkout -b PATCH_branch origin/PATCH_branch
fatal: Cannot update paths and switch to branch 'PATCH_branch' at the same time.
Did you intend to checkout 'origin/PATCH_branch' which can not be resolved as commit?

Could someone please explain what the last bit means? 有人可以解释一下最后的意思吗? Or why I can't checkout a branch without being detached? 还是为什么我不能在不分离的情况下签出分支? I know under certain circumstances I might end up with a detached HEAD, but this isn't one of them. 我知道在某些情况下,我可能会遇到一个分离的HEAD,但这不是其中之一。

There is no origin/PATCH_branch . 没有origin/PATCH_branch Instead, there is a tag that is very poorly named, and in your clone, you have checked out that tag, resulting in the detached HEAD. 相反,有一个标签的名称很差,并且在您的克隆中,您已签出该标签,从而导致HEAD分离。

Why this happened 为什么会这样

If you consult the gitrevisions documentation , you will see a sequenced list of possibilities for resolving a symbolic reference name: 如果您查阅gitrevisions文档 ,您将看到解析符号引用名称的可能性的顺序列表:

<refname> , eg master , heads/master , refs/heads/master <refname> ,例如masterheads / masterrefs / heads / master

A symbolic ref name. 符号引用名称。 Eg master typically means the commit object referenced by refs/heads/master . 例如master通常是指refs / heads / master引用的提交对象。 If you happen to have both heads/master and tags/master , you can explicitly say heads/master to tell Git which one you mean. 如果您碰巧同时拥有heads / mastertags / master ,则可以明确地说出heads / master来告诉Git您是什么意思。 When ambiguous, a <refname> is disambiguated by taking the first match in the following rules : 当模棱两可时,通过遵循以下规则中的第一个匹配项来消除<refname>的歧义:

  1. If $GIT_DIR/<refname> exists, that is what you mean (this is usually useful only for HEAD, FETCH_HEAD, ORIG_HEAD, MERGE_HEAD and CHERRY_PICK_HEAD ); 如果$ GIT_DIR / <refname>存在,这就是您的意思(通常仅对HEAD,FETCH_HEAD,ORIG_HEAD,MERGE_HEADCHERRY_PICK_HEAD有用 );

  2. otherwise, refs/<refname> if it exists; 否则, refs / <refname>(如果存在);

  3. otherwise, refs/tags/<refname> if it exists ; 否则, refs / tags / <refname>(如果存在)

In this particular case, the name PATCH_branch is not in fact ambiguous, but the rules (especially the parts I put in bold text) still apply: if there is a tag named PATCH_branch , and neither rule #1 nor rule #2 are able to resolve the name to a commit hash but the tag can, Git can check out the tag, so we don't need to go on to look at rules 4, 5, and 6; 在这种特殊情况下,名称PATCH_branch实际上并不是模棱两可的,但是规则(尤其是我用粗体显示的部分)仍然适用:如果有一个名为PATCH_branch的标记,则规则#1和规则#2都无法执行将名称解析为提交哈希,但是标签可以,Git可以签出标签,因此我们无需继续查看规则4、5和6; but here they are anyway: 但无论如何在这里:

  1. otherwise, refs/heads/<refname> if it exists; 否则, refs / heads / <refname>(如果存在);

  2. otherwise, refs/remotes/<refname> if it exists; 否则, 引用/远程/ <refname>(如果存在);

  3. otherwise, refs/remotes/<refname>/HEAD if it exists. 否则, 引用/远程/ <refname> / HEAD(如果存在)。

Of these six rules, only one—specifically rule 4—will not give you a "detached HEAD" checkout. 在这六个规则中,只有一个(特别是规则4) 不会给您“分离的HEAD”结帐。 Since you did get a detached HEAD, clearly rule 4 did not apply. 由于您确实获得了独立的HEAD,因此显然规则4不适用。

Special rules for git checkout git checkout特殊规则

Now, git checkout has its own additional "rule 4.5", where it will create refs/heads/ refname in some situations. 现在, git checkout有自己的附加“规则4.5”,在某些情况下它将在其中创建 refs/heads/ refname That extra git checkout rule is the rule you were expecting to experience here, I believe. 我相信,额外的git checkout规则就是您希望在这里经历的规则。

Specifically, git checkout will, even before trying rules 1, 2, and 3 , try rule 4. If this fails, git checkout will then see if it can create a local branch based on the existence of exactly one matching remote-tracking branch. 具体来说,即使在尝试规则1、2和3之前git checkout仍将尝试规则4。如果失败,则git checkout将根据是否存在一个完全匹配的远程跟踪分支来查看是否可以创建本地分支。 In either of these two cases, rule 4 then applies and git checkout does not give you a "detached HEAD". 在这两种情况中的任何一种情况下,规则4均适用,并且git checkout 不会为您提供“分离的HEAD”。 Otherwise git checkout goes back and starts over at rule 1. 否则git checkout返回并从规则1重新开始。

Clones initially have only remote-tracking branches and tags 克隆最初仅具有远程跟踪分支和标签

You mentioned that this is a new clone, and in new clones, there is one (and only one) remote and by default, you get all of its branches as remote-tracking branches. 您提到这是一个新克隆,在新克隆中,有一个(只有一个)远程,默认情况下,您将其所有分支作为远程跟踪分支。 If the remote is named origin (as it usually is), these remote-tracking branches live in the refs/remotes/origin/ part of your repository's name-space. 如果将远程站点命名为origin (通常如此),则这些远程跟踪分支将位于存储库名称空间的refs/remotes/origin/部分中。 You also, by default, get all of the remote's tags, which live in your refs/tags/ name-space. 默认情况下,您还可以获取遥控器的所有标签,这些标签都位于refs/tags/名称空间中。

The last step of git clone is git checkout git clone的最后一步是git checkout

When you run: 运行时:

$ git clone <url>

or: 要么:

$ git clone <url> <destination>

Git will connect to the given URL, verify that there is a Git repository there, ask that remote for a list of all branches and tags, and then create a clone repository for you in the given destination directory (or use the last part of the URL to make a default destination name). Git将连接到给定的URL,验证那里有一个Git存储库,要求该远程服务器提供所有分支和标签的列表,然后在给定的目标目录中为您创建一个克隆存储库(或使用该存储库的最后一部分)用作默认目标名称的URL)。 In that repository, Git will add a remote named origin (or whatever name you specify with -o ). 在该存储库中,Git将添加一个远程命名的origin (或您使用-o指定的任何名称)。 It will copy all of their tags to your tags, and copy their branches to your refs/remotes/origin/ remote-tracking branches (if you specify a different -o , modify these names as appropriate). 它将所有它们的标签复制到您的标签,并将它们的分支复制到refs/remotes/origin/ remote-tracking分支(如果您指定其他-o ,请相应地修改这些名称)。 The resulting repository has no local branches at all . 生成的存储库根本没有本地分支

However, at this point, git clone invokes git checkout , to check out some branch—the one you told it to ( git clone -b ) or, by default, the one your Git got from the remote, usually master . 但是,在这一点上, git clone调用git checkout ,以检出某些分支,即您告诉它的分支( git clone -b ),或者默认情况下,是您的Git从远程(通常是master获得的分支。 Of course, you don't have a local master branch, and this is where what I called "rule 4.5" comes in: git checkout looks to see if there is an origin/master , and of course there is, so your Git makes a new local branch named master that tracks remote-tracking branch origin/master . 当然,你不必在本地master分支,这就是我所说的“第4.5条”进来: git checkout查看是否有一个origin/master ,当然有,所以你的Git品牌一个名为master的新本地分支,该分支可跟踪远程跟踪分支的origin/master 1 This is, in fact, how you get your master branch! 1实际上,这就是您获得master分支的方式!

When you ran git checkout PATCH_branch you no doubt expected Git to follow this same pattern: there should be an origin/PATCH_branch , and your Git should create a new (regular, ordinary, local) branch named PATCH_branch based on origin/PATCH_branch (which is really refs/remotes/origin/PATCH_branch ). 当你运行git checkout PATCH_branch毫无疑问你预期的Git遵循同样的模式:应该有一个origin/PATCH_branch ,和你的Git应该创建一个新的(普通,平凡,本地)分支命名PATCH_branch基于origin/PATCH_branch (这是确实refs/remotes/origin/PATCH_branch )。

But instead, what you have is a tag, refs/tags/PATCH_branch . 但是,您拥有的只是一个标签refs/tags/PATCH_branch So the special "create local branch from remote-tracking branch" rule does not apply, and the "early application of rule 4" does not apply either, and we're left with rules 1 and 2 (which do not apply) and then rule 3, and that got you the "detached HEAD" checkout. 因此,特殊的“从远程跟踪分支创建本地分支”规则不适用,“规则4的早期应用”也不适用,我们剩下规则1和2(不适用),然后规则3,这使您获得了“分离头”结帐。

You can create a local branch, but be careful! 可以创建本地分支,但要小心!

Look back over the six rules. 回顾这六个规则。 Suppose you have both refs/heads/PATCH_branch and refs/tags/PATCH_branch . 假设您同时拥有refs/heads/PATCH_branch refs/tags/PATCH_branch Note that rule 3 normally applies before rule 4: most Git commands will treat PATCH_branch as the tag . 请注意,规则3通常规则4 之前适用: 大多数 Git命令会将PATCH_branch视为tag

Because git checkout is special, and applies rule 4 first (instead of after rule 3), you will be able to check out the local branch. 因为git checkout很特殊,并且首先应用规则4(而不是在规则3之后),所以您可以签出本地分支。 But other Git commands will behave in ways you won't expect, as they will apply rule 3 first. 但是其他Git命令将以您意想不到的方式运行,因为它们将首先应用规则3。

The tag is poorly named 标签名称不正确

Tag names should probably not contain the word "branch". 标签名称可能不应包含“ branch”一词。 Whether you can or should fix this is an administrative question more than a technical one. 您是否可以解决此问题,不仅仅是技术性的管理问题。 Find out who created the tag and why, and see if you can get everyone on your project to agree that this is a bad name and thus to delete it. 找出谁创建了标签以及为什么创建标签,然后查看您是否可以使项目中的每个人都同意这是一个不好的名字,因此将其删除。


1 The names here are admittedly terribly confusing. 1这里的名字令人困惑。 The local branch master is not a "(remote-)tracking branch", but it is "tracking" another branch. 本地分支master不是“(远程)跟踪分支”,而是“跟踪”另一个分支。 The remote-tracking branch origin/master is something your Git stores locally; 远程跟踪分支机构的 origin/master是您的Git在本地存储的; it's just automatically updated from whatever your Git sees on origin , whenever your Git talks with their Git. 它只是自动从任何你Git把上更新的origin ,每当他们的Git你的Git会谈。 So your branch—your master —is "tracking" a remote-tracking branch, origin/master . 所以,你的分支的master -is“跟踪”远程跟踪分支, origin/master All that really means is that your master has origin/master set as its upstream , which is a newer, somewhat better term. 真正的意思是,您的mastermaster origin/master设置为其上游 ,这是一个更新的,更好的术语。 Older Git documentation (pre-version-1.8 or so) does not define upstream quite this carefully, though. 不过,较早的Git文档(1.8版之前的版本)并未对此上游进行仔细定义。

Typically, when you git clone a repository, it will only contain a single branch (usually master , but in can be different depending on what HEAD refers to in the origin repository). 通常,当您git clone一个存储库时,它只会包含一个分支(通常是master ,但是根据HEAD在原始存储库中所指的不同而不同)。 It will also have remote references for the branches the origin repository has (these will be named like refs/remotes/origin/branchname ). 它还将对原始存储库所具有的分支具有远程引用(这些名称将像refs/remotes/origin/branchname一样命名)。 If you then do git checkout branchname , it will check out the commit found in refs/remotes/origin/branchname , but since that is not a branch (which would be named refs/heads/branchname ), you get a detached HEAD - you're no longer looking at a branch. 如果你然后做git checkout branchname ,它会检查在发现提交refs/remotes/origin/branchname ,但由于这不是一个分支(这将被命名为refs/heads/branchname ),你会得到一个分离的HEAD -你不再看分支。

To resolve that, you can follow the advice given in the message that git showed you git checkout -b <branchname> , essentially creating a new branch at the commit you have checked out, or run the command you attempted in your second listing. 要解决此问题,您可以按照git向您显示git checkout -b <branchname>的消息中给出的建议,本质上是在您检出的提交处创建一个新分支,或者运行您在第二个清单中尝试的命令。 The caveat with the second command is that you need to get back on a branch first (eg git checkout master ) before that command will succeed. 使用第二个命令的警告是,您需要先回到分支(例如git checkout master ),然后该命令才能成功。 If you had run git checkout -b <branchname> origin/<branchname> first, it would have been successful. 如果首先运行git checkout -b <branchname> origin/<branchname> ,则该操作将成功。 That will also set up the new branch to "track" the origin branch, so you can do git push , git pull , etc. with it. 这还将设置新分支以“跟踪”原始分支,因此您可以对其进行git pushgit pull等。

you are using checkout instead of clone to get the repository (tho you could simply be skipping the cloning part for your question). 您正在使用checkout而不是clone来获取存储库(因此,您可以直接跳过问题的克隆部分)。

It would seem that your repo doesn't hold any remote repository to check out to. 您的存储库似乎没有任何要签出的远程存储库。 What's the output of git remote -v ? git remote -v的输出是什么?

It should probably the same remote repository called origin, once for fetching and once for pushing. 它可能应该是称为origin的同一远程存储库,一次用于获取,一次用于推送。 If you don't have any, you should git remote add <remoteRepo> 如果没有,则应该git remote add <remoteRepo>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM