git pull命令输出消息意味着进入哪个分支

时间:2015-02-05 06:17:11

标签: git git-branch git-pull git-remote

假设远程仓库上有远程分支br1签出,本地仓库上有master分支。

  • 命令1:如果我做了" git pull origin br1:br1"它将远程br1拉入本地br1,并显示: 9188a5d..97d4825 br1 -> br1 9188a5d..97d4825 br1 -> origin/br1

  • 命令2:如果我只选择" git pull",它会将远程br1拉入本地master,但它只会显示以下: 9188a5d..97d4825 br1 -> origin/br1

我希望它也会显示类似" br1 -> master"的内容。为什么没有表现出来?

" br1 -> br1"意味着将远程br1拉入本地br1

那是什么" br1 -> origin/br1"意思?

更新:在VonC的帮助下,我发现了以下内容:

  • git pull更新所有跟踪分支。 br1 -> origin/br1表示遥控器上的br1被拉入本地跟踪分支origin/br1

  • git pull origin br1:br1将远程br1拉入本地br1origin/br1。然后,之后的消息意味着相同的更改集也被拉入当前签出的分支(消息为Updating ...,它不显示br1 -> master): $ git pull origin br1:br1 beb48a4..b344dd1 br1 -> br1 beb48a4..b344dd1 br1 -> origin/br1 Updating cca5a9b..b344dd1 Fast-forward file2 | 0 file3 | 0 4 files changed, 0 insertions(+), 0 deletions(-)

  • 以前我认为git pull会拉入本地主人。事实并非如此。这是git pull origin br1:br1做到的。

更新2 :通过torek的解释,具体问题是命令git pull origin br1:br1在一系列其他操作之后将远程br1拉入FETCH_HEAD随后将FETCH_HEAD合并到当前分支上。

2 个答案:

答案 0 :(得分:5)

警告:很久。 TL; DR版本:您正在查看git fetch输出,而git fetch根本不会影响您的master,它是您git merge的{​​{1}}部分}}会影响您的git pull。但是,您的master正在更新远程跟踪分支git fetch,在一种情况下更新甚至创建本地分支origin/br1

br1是一个便利脚本

永远记住,git pull只是一个便利脚本,可以为您运行另外两个git命令:首先,git pull将您的参数传递给git pull。完成后,git fetchgit pull(或者,如果需要git merge),但原始问题中的所有引用操作都是在git rebase内完成的。 ("更新"部分中的一部分来自git fetch,我稍后会介绍。)

如果未向git merge提供远程参数,git pull脚本将从当前分支的配置中提取一个。{1}}脚本。在这种情况下,它提取的那个显然是pull。因此,如果您在未指定origin的情况下运行git pull,则实际上您正在运行origin

如果您没有向git pull origin提供 refspec 参数,git pull脚本会从当前分支的配置中提取一个非常简单的参数 - 在这种情况下,无论你从pull看到什么,显然是git config --get branch.master.merge。所以这意味着如果你运行br1,你实际上正在运行git pull origin 1

同样,所有这些都被传递到git pull origin br1,因此,无论您运行git fetchgit pull还是git pull origin,所有这些都只是最终调用:

git pull origin br1

(您也可以手动执行,并且您将看到上述内容)。

我们稍后会到git fetch origin br1

关于可能的误解的背景

让我们再次简要介绍一下您的设置声明:

  

假设远程仓库上有远程分支git fetch origin br1:br1签出,本地仓库上有br1分支。

遥控器上当前已检出的分支(如果有) master无关。第一个(或第一个)事情fetch的作用是连接到远程并询问它是否包含所有引用及其相应SHA-1的列表(您可以通过运行查看fetch可以看到的内容git fetch)。该列表中包含远程的git ls-remote ,这样您就可以指示HEAD使用它了,但如果您不这样做,那么您的fetch fetch只是忽略它(远程' HEAD主要仅用于控制初始git clone上的默认初始分支。)

local repo 中的当前分支非常重要,原因有两个:

  • 如果您没有向git pull提供额外的参数,它会根据您当前的分支找到它们;和
  • fetch成功后,git pull运行使用您当前分支的git mergegit rebase

同样,您当前的分支是master,因此pull将使用branch.master.remotebranch.master.merge作为默认远程 refspec < / em> arguments。 2 这就是我们如何从原始输出中推断出它们分别是originbr1

git fetch

返回git fetch,它的作用是与远程git服务器进行一些比较,以找出哪些引用(主要是分支和标记)可用以及它们对应的SHA-1值是什么。一旦有了这些信息,它就会查看你要求它带来哪些参考资料。如果您列出了br1之类的特定参考,那么它将引入一个参考。

当然,除了每个引用之外,它还必须带来任何新对象(提交本身及其关联的树和文件,以及任何父提交及其所需的树和文件),以便您获得所有从那个特定点向后的历史。无论你有什么历史,当然,它都可以跳过。 3

作为VonC already noted,git 1.8.4及更高版本中git在git fetch remote refspec上的行为发生了变化。过去的情况是,如果您运行git fetch remote refspec,您的refspec 会覆盖该遥控器的git配置条目中的规则,但现在只需从中选择。默认情况下,名为origin的远程的规则集为+refs/heads/*:refs/remotes/origin/*,因此您的br1 refspec会从此规则集中选择一个项目。


如果你只使用三个参数运行git fetch,请暂停一下,看看会发生什么:

$ git fetch origin

在这里,您要指示您的本地git连接到遥控器,找出它有什么,并带来所有分支。它的方式(和原因)如上所述:它连接,获取列表,然后查询git config --get-all remote.origin.fetch的输出。 4 这是&#34的列表; refspecs&#34;,每git config --get-all行一个。

由于remote.origin.fetch的标准行(单行)为+refs/heads/*:refs/remotes/origin/*,因此您的本地git将采用与refs/heads/*匹配的每个引用名称。也就是说,它将占用origin上的所有分支,因为分支只是&#34;名称以refs/heads/&#34;开头的引用。 对这些分支做什么取决于此refspec的右侧:它将refs/heads/替换为refs/remotes/origin/

结果是&#34;远程跟踪分支&#34;。如果遥控器有分支master,则您的本地git会将其转换为origin/master。如果遥控器有br1,则您的本地git会将其转换为origin/br1。对于遥控器上的每个分支,您将获得一个(本地)远程跟踪分支,其名称以origin/开头。 5


回到我们git fetch origin br1的情况,我们现在可以看到会发生什么:我们的本地git带来了br1,结果证明它是一个分支,因此它的全名是refs/heads/br1 。因此,它与标准remote.origin.fetch行匹配,refs/heads/br1被翻译为refs/remotes/origin/br1,这会导致git打印出origin/br1

9188a5d..97d4825  br1        -> origin/br1

左侧的名称br1是遥控器上引用的简称,右侧的名称origin/br1git fetch已更新的引用的短名称

过去你会看到类似的东西 - 你仍然可以看到它:

* branch            name       -> FETCH_HEAD

这表明git fetch在遥控器上找到了一个名为name的分支(即refs/heads/name形式的引用)并将其转移到您的本地仓库并将其放入{ {1}}。什么是FETCH_HEAD?它是一个特殊的文件,几乎只存在于FETCH_HEAD脚本中。 (它的工作原理很像参考,但它有一个特殊的格式,可能包含多个SHA-1。)


现在我们(最后)准备好解决git pull案件。在此,您要告知当地br1:br1提交引用git fetch。通常会调用遥控器,发现br1确实是br1,并带来参考和任何需要的对象 - 但这一次,除了咨询refs/heads/br1行之外,它将新的SHA-1写入您指定的

在这种情况下,您指定的remote.origin.fetch没有资格:不是br1,不是refs/heads/br1,只有refs/remotes/origin/br1。在这种情况下,git看到它是遥控器上的br1引用,意味着它是一个分支;所以git也会在你的最后添加refs/heads/,并创建或更新你自己的refs/heads/

换句话说,这会创建或更新本地分支refs/heads/br1

此外,git仍然会应用仍为br1的{​​{1}}行,因此它仍然会更新远程跟踪分支remote.origin.fetch(全名+refs/heads/*:refs/remotes/origin/*)。 这就是你从Command 1获得输出的原因。

origin/br1

refs/remotes/origin/br1怎么样?好吧,git merge的其余部分重新出现:执行FETCH_HEAD步骤后,git pull脚本运行git fetchpull 。它合并的内容(或者转换为on)是 git merge文件中遗留下来的git rebase (有一些特殊的外壳和其他警告,我赢了#t进入这里)。

如果您当前的分支是git fetch,但是您指示FETCH_HEAD提取mastergit pull步骤origin br1最新git merge更确切地说,合并可让您及时更新master br1完成后的origin/br1副本。可能就在您git fetch完成后,其他人在您的遥控器上更新了git fetch {/ 1}}。

合并是&#34;快进&#34;如果可能合并,但我再次在这里不再详细介绍。我只是注意到它是可能的,所以它已经完成了;这是更新中的git push行。

在任何情况下,合并都会引入当前分支(br1)自当前分支和目标提交的合并基础以来的更改(Fast-forward离开的原始SHA-1在master文件中,它也是git fetch的新SHA-1,在一种情况下,是新的或更新的本地分支FETCH_HEAD的新SHA-1。 / p>

在1.8之前的git版本中,origin/br1远程跟踪分支未更新。尽管如此,所有内容仍然可以在br1文件中运行,如果有的话,甚至更多比新gits更令人困惑,我们可以说你现在已经更新了使用origin/br1而不必非常严格和挑剔#{1;} FETCH_HEAD,因为它在您运行origin/br1&#34;时已经在遥控器上。

加号是什么?

眼尖的读者会注意到br1中的git fetch。此+符号表示&#34;强制更新&#34;。通常,在更新分支参考时 - 任何以+refs/heads/*:refs/remotes/origin/*开头的参考 - git都会允许更新,除非它是&#34;快进&#34;标签更新。在refspec中设置force标志允许进行特定更新。在命令行上使用+也允许更新以及所有其他参考更新。换句话说,加号只是refs/heads/的更具针对性(单个refspec)版本。


1 这是夸大其辞:有时它使用三个参数--force

2 对于远程位始终为true,但 refspec 位可能为空,--force脚本确定哪个在git fetch完成后,refspec将在稍后申请。

3 默认情况下,pull操作还会引入任何与其带来的提交ID匹配的标记名称引用。如果您自己运行git fetch,则可以更改fetch处理这些问题的方式,但如果您让git fetch运行fetch,您将获得此默认行为。请注意,它是您做出这些决定的本地git:远程git只是向您的本地git显示所有内容,然后您的git决定是否将标记添加到您的存储库。

4 技术上git pull只调用执行此操作的C代码,而不是实际运行git fetch。在任何情况下,如果git fetch有多个配置条目,git config --get-all确实适用于所有这些条目。它的方式虽然有点复杂,但我会在这里跳过血淋淋的细节。

5 远程跟踪分支实际上只是名称以remote.origin.fetch开头的引用,就像本地分支是名称以git fetch origin开头的引用一样。这在git中很常见:你的标签是名称以refs/remotes/开头的引用。 refs/heads/脚本使用单个特殊引用refs/tags。 Git&#34;注意&#34;存储在git stash下,您可以创建自己的引用:只需选择一个不同的起始字符串,并希望将来没有其他人为新的git功能选择相同的字符串。 : - )

答案 1 :(得分:1)

包含origin/xxxx的任何行表示git pull git fetch git fetch + git merge}的git config branch.b1.merge部分已更新remote tracking branch
git 1.8.4 (before it only updated FETCH_HEAD)以来就是如此。

  

如果我只做一个&#34; git pull&#34;,它会将远程br1拉入本地主人

这取决于git pull,它指示git pull b1:b1 的git合并部分进行合并。
通过执行b1,您将覆盖该配置并指示合并在本地master分支中进行。

另请参阅git branch -avvv的结果,以了解哪个本地分支正在跟踪哪个远程分支。

  

我期待它也会显示类似&#34; br1 - &gt;的内容。主&#34 ;.为什么它没有显示出来?

可能97d4825已经在{{1}}。