假设远程仓库上有远程分支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
拉入本地br1
和origin/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
合并到当前分支上。
答案 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 fetch
会git 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 fetch
,git 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 merge
或git rebase
。同样,您当前的分支是master
,因此pull
将使用branch.master.remote
和branch.master.merge
作为默认远程和 refspec < / em> arguments。 2 这就是我们如何从原始输出中推断出它们分别是origin
和br1
。
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/br1
是git 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 fetch
或pull
。它合并的内容(或者转换为on)是 git merge
文件中遗留下来的git rebase
(有一些特殊的外壳和其他警告,我赢了#t进入这里)。
如果您当前的分支是git fetch
,但是您指示FETCH_HEAD
提取master
,则git 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}}。