如何正确检出远程存储库中的分支

时间:2013-09-01 03:57:06

标签: git

我有这个

    abc@abc-ubuntu:~/project1/wh-app-ios$ git branch -a -v -v
    * master                   1d35af1 [origin/master: ahead 2] Adding 123 to hello
      remotes/gitb/gh-pages    e3dad9d boom
      remotes/gitb/integration 1d3fcd5 Adding 55_Glossary chapter
      remotes/gitb/master      86d1d30 Merge remote-tracking branch 'origin/master'
      remotes/gitb/pt_BR       dc9d991 Revisions at 03, 07, 08, 09, 10, 11 and 50
      remotes/origin/HEAD      -> origin/master
      remotes/origin/master    1ae426b Update README.md

我做

    abc@abc-ubuntu:~/project1/wh-app-ios$ git checkout gitb/master
    Note: checking out 'gitb/master'.

    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 86d1d30... Merge remote-tracking branch 'origin/master'

然后查看上面的警告信息

    abc@abc-ubuntu:~/project1/wh-app-ios$ git checkout -b mastergitb
    Switched to a new branch 'mastergitb'

现在我在

    abc@abc-ubuntu:~/project1/wh-app-ios$ git branch -a -v -v
      master                   1d35af1 [origin/master: ahead 2] Adding 123 to hello
    * mastergitb               86d1d30 Merge remote-tracking branch 'origin/master'
      remotes/gitb/gh-pages    e3dad9d boom
      remotes/gitb/integration 1d3fcd5 Adding 55_Glossary chapter
      remotes/gitb/master      86d1d30 Merge remote-tracking branch 'origin/master'
      remotes/gitb/pt_BR       dc9d991 Revisions at 03, 07, 08, 09, 10, 11 and 50
      remotes/origin/HEAD      -> origin/master
      remotes/origin/master    1ae426b Update README.md
    abc@abc-ubuntu:~/project1/wh-app-ios$ 

问题:

  1. 但很明显,mastergitb不跟踪gitb / master。那是为什么?

  2. 我是否只创建了一个名为mastergitb的本地分支,它只是gitb / master的副本,但与之没有其他关系?

2 个答案:

答案 0 :(得分:7)

我不确定为什么消息没有引用这个,但你可以写

git checkout -t origin/branchname

创建一个名为branchname的本地分支,用于跟踪origin/branchname-t--track的缩写)。或者你可以写

git checkout -b localname -t origin/branchname

创建一个名为localname的跟踪origin/branchname的本地分支,所以在您的示例中:

git checkout -b mastergitb -t gitb/master

是的,创建非跟踪分支正是您所做的。您可以通过删除分支并遵循这些说明,或通过运行git branch --set-upstream mastergitb gitb/master来设置现有分支的上游来修复它。

答案 1 :(得分:4)

关于“远程分支”有一个奇怪的事情,就像git称之为“远程分支”,这使得它们与“本地”分支非常不同。我有时认为如果git使用不同的名称对人们更有意义,尽管我实际上没有更好的名字。所以,关于问题2:

  

我是否只创建了一个名为mastergitb的本地分支,它只是gitb/master的副本,但与之没有其他关系?

是的,但短语“副本”有点误导。相反,假设您创建了一个本地分支,以与远程协议相同的提交结束。

关于git branches要记住的是每个分支名称只是提交标签。使本地分支名称特别特殊(且有用)的原因在于它是移动标签,并且它自动移动 。 (与“标签”比较,“标签”也是特定提交的标签,但标签不会自动移动,人们通常希望它们保持不变。如果您移动标签,则必须警告其他人与您的仓库共享或复制标记。)

当你在“分支上”时 - 反对拥有一个“分离的HEAD”,正如有人指出的那样,有点可怕 - 并且你进行了新的提交,分支标签会自动移动到新的提交。也就是说,当HEAD是分支brangit commit(和git merge以及其他各种其他添加提交的方式)的名称时,添加新提交及其父级指向前一个分支尖端,然后向前移动分支尖端:

C5 -- C6 -- C7   <-- HEAD=bran

变为:

C5 -- C6 -- C7 -- C8   <-- HEAD=bran

但是“远程分支”不能像这样工作。实际上,你甚至无法“在”远程分支上,正如你所发现的那样:如果你git checkout origin/master,git会让你进入那种“分离的HEAD”状态。

另一个有趣的事情是,“远程分支”可以并且确实移动。当添加提交时,它们不会移动,因为你永远不会“开启”它们。你把它们检查出来,你的脑袋就会被断头关闭。 :-)然后,您可以使用git checkout -b创建一个本地分支,就像您一样。此本地分支设置为指向HEAD名称的提交,这与“远程分支名称”指向的提交相同。它不是任何东西的副本,因为它只是一个指向提交的箭头

在图表形式中,它可能看起来有点像这样(假设您在本地master上“跟踪”origin/master):

       C2        <-- origin/xyz
      /
C0--C1           <-- origin/foo
      \
       C3--C4    <-- origin/bar
         \
          C5     <-- origin/master, HEAD=master

如果你git checkout origin/foo,git会从底部删除HEAD=origin/mastermaster都指向提交C5),并设置{ {1}}提交HEAD的SHA-1哈希值。它没有设置C1(这会让你“在远程分支上”),而是直接设置为提交哈希(“分离头”状态)。

然后,当您HEAD=origin/foo时,git会创建一个新的分支名称git checkout -b localfoo,将其设置为指向提交localfoo,并设置C1。现在你“在一个分支上”!

注意:本地分支HEAD=localfoo的“全名”是bran。远程分支refs/heads/bran的“全名”为rmt/bran。也就是说,本地分支始终在refs/remotes/rmt/bran,而远程从不在。{1}}。通常情况下,您将所有前端内容留下,只需引用refs/heads/bran,但有时它很重要,并且它使下面的某些内容更有意义。

除了让origin/bran“跟踪”localfoo(已经回答)之外,还有一个要解释的项目,那就是:“远程分支”如何移动?答案是:他们继续origin/foo(或git fetch,与git remote update基本相同)。当您从远程获取(或更新)时,git会联系远程并找到其分支名称。使用这些名称,它会找到它们指向的提交。然后它找到了他们的父母,以及他们父母的父母,等等。每当你没有这些提交时,它会把它们带到你的仓库并将它们塞进你的仓库,这样你就能“赶上”遥控器。然后它将新的引用名称写在“远程分支”类别下,由fetch文件控制。

如果您查看.git/config,您会看到类似的内容:

.git/config

[remote "origin"] fetch = +refs/heads/*:refs/remotes/origin/* url = ssh://some.where.out.there/some/path/to/repo.git 行是获取“远程分支”的关键。它表示,对于匹配fetch的所有 本地分支的所有内容 - 将refs/heads/*替换为refs/heads/(保留其余的分支名称) )然后更新那些引用(强制,因为refs/remotes/origin/符号)。因此,在某人控制远程URL更新该repo后,然后从他们+获取更新后,您的git会移动您的“远程分支”标签以匹配。

是否以及何时移动本地分支标签以匹配自动移动的“远程分支”标签取决于您。简单的方法是使用“git merge”,自动化的简便方法是使本地分支成为“跟踪分支”。一旦您将本地分支 L 标记为跟踪远程分支 rmt / R fetch将告诉您它是否落后,git status将知道如何调用git pull,可以告诉git merge自动更新(请参阅git-merge documentation的配置部分中的git merge)。