2

我有这个

    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 的副本,但与它没有其他关系?

4

2 回答 2

8

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

git checkout -t origin/branchname

创建一个名为branchnametrack的本地分支origin/branchname-t是 的缩写--track)。或者你可以写

git checkout -b localname -t origin/branchname

创建一个名为localnametrack的本地分支origin/branchname,因此在您的示例中:

git checkout -b mastergitb -t gitb/master

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

于 2013-09-01T04:07:36.173 回答
5

正如 git 所说的那样,“远程分支”有一个特殊的地方,这使得它们与“本地”分支非常不同。我有时认为如果 git 使用不同的名称可能对人们更有意义,尽管我实际上并没有更好的名称。所以,关于问题2:

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

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

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

当你“在一个分支上”——而不是有一个“分离的 HEAD”,正如有人指出的那样,这有点可怕——并且你做了一个新的提交,分支标签会自动移动到新的提交。也就是说, whenHEAD是 branch 的名称brangit commit(以及git merge其他各种添加提交的方法)添加新提交,其父级指向前一个分支提示,然后向前移动分支提示:

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

变成:

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

但是“远程分支”不是这样工作的。事实上,正如您所发现的那样,您甚至不能“在”远程分支上:如果您git checkout origin/mastergit 将您置于“分离的 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 将从底部git checkout origin/foo擦除(离开并都指向 commit ),并设置为 commit 的 SHA-1 哈希。它没有设置(这将使您“进入”远程分支),而是直接设置为提交哈希(“分离头”状态)。HEAD=origin/mastermasterC5HEADC1HEAD=origin/foo

然后,当你git checkout -b localfoogit 创建一个新的分支 name localfoo,将其设置为指向 commit C1,并设置HEAD=localfoo. 现在你“在一个分支上”!

注意:本地分支的“全名”bran是. 远程分支的“全名”是. 也就是说,本地分支总是在,而远程分支永远不会。通常你会忽略所有前端的东西,只参考and ,但有时它很重要,它使下面的一些文本更有意义。refs/heads/branrmt/branrefs/remotes/rmt/branrefs/heads/branorigin/bran

除了制作localfoo“跟踪” origin/foo(已经回答)之外,还有一个项目需要解释,那就是:“远程分支”究竟是如何移动的?答案:他们继续前进git fetch(或git remote update与 基本相同fetch)。当您从远程获取(或更新)时,git 会联系远程并找到其分支名称。使用这些名称,它会找到它们指向的提交。然后它找到他们的父母,以及他们父母的父母,等等。每当您没有这些提交时,它会将它们带过来并将它们填充到您的存储库中,以便您“赶上”远程。然后它将新的参考名称写入“远程分支”类别下,由.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 之后,然后您fetch从他们那里获得更新,您的 git 会移动您的“远程分支”标签以匹配。

是否以及何时移动本地分支标签以匹配自动移动的“远程分支”标签取决于您。简单的方法是使用“git merge”,而自动化的简单方法是使本地分支成为“跟踪分支”。一旦你将本地分支L标记为跟踪远程分支rmt/Rgit status它会告诉你它是否落后,git pull会知道如何调用git merge,并且git merge可以被告知自动更新(参见git-merge 文档merge.defaultToUpstream的配置部分)。

于 2013-09-01T09:38:01.390 回答