git fetch 到底有什么作用?

tro*_*ore 4 git merge fetch

现在我想合并一个远程分支,将它命名origin/branch1为我的本地分支branch1,因为我的合作伙伴在我们上次合并后向远程分支 1推送了一个新提交,并且自他上次提交以来我没有提交过,并希望从中获取更新犯罪。我使用了以下命令:

$ git fetch origin branch1
Compressing...
*branch branch1 ->FETCH_HEAD
$ git merge origin/branch1
Already up-to-date
Run Code Online (Sandbox Code Playgroud)

那不是我想要的。在这样做之前,我的想法是使用 fetch 来获取我的合作伙伴添加的内容并origin/branch1更新远程分支。但是,“已经是最新的”意味着我无法在本地分支 1 中获取更新。然后我检查的SHA1值origin/branch1

$ git ls-remote origin
Run Code Online (Sandbox Code Playgroud)

发现在我们上次合并后它保留了旧提交的陈旧值。它告诉git fetch origin branch1无法更新origin/branch1。我做了另一个实验,我的伙伴在他身边创建了另一个名为“branch2”的分支,并将 branch2 中的提交推送到远程源。那我还是用

$ git fetch origin branch2
Compressing...
$ git merge origin/branch2
No branch named "origin/branch2"
Run Code Online (Sandbox Code Playgroud)

“压缩”告诉我第一个命令在 origin 中成功下载了 branch2 中的东西,但是,第二个命令告诉我没有名为 origin/branch2 的分支!因此我得出结论,既不能在本地git fetch origin branchname更新origin/branchname,也不能在不存在的情况下创建远程分支。

在我用 替换git fetch origin branch#git fetch origin,所有的git merges 都按我的预期工作。

但是,我经常看到组合

$ git fetch remote branch-name
$ git merge remote/branch-name
Run Code Online (Sandbox Code Playgroud)

所以我的问题是git fetch remote和之间有什么区别git fetch remote branch-name?在什么条件下,我可以通过这种组合成功地让它如我所愿?

ken*_*orb 5

如果您需要知道究竟git fetch在做什么或任何其他git命令,只需在它前面加上前缀GIT_TRACE=1,这样它就会为您提供带有调用的任何其他命令的跟踪输出,例如

$ GIT_TRACE=1 git fetch origin master
03:08:15.704945 git.c:348               trace: built-in: git 'fetch' 'origin' 'master'
03:08:15.706183 run-command.c:347       trace: run_command: 'ssh' 'git@github.com' 'git-upload-pack '\''FOO/BAR.git'\'''
03:08:16.006394 run-command.c:347       trace: run_command: 'rev-list' '--objects' '--stdin' '--not' '--all' '--quiet'
03:08:16.013096 run-command.c:347       trace: run_command: 'rev-list' '--objects' '--stdin' '--not' '--all'
03:08:16.013625 exec_cmd.c:129          trace: exec: 'git' 'rev-list' '--objects' '--stdin' '--not' '--all'
03:08:16.016617 git.c:348               trace: built-in: git 'rev-list' '--objects' '--stdin' '--not' '--all'
From github.com:FOO/BAR
 * branch            master     -> FETCH_HEAD
03:08:16.153070 run-command.c:347       trace: run_command: 'gc' '--auto'
03:08:16.153748 exec_cmd.c:129          trace: exec: 'git' 'gc' '--auto'
03:08:16.157704 git.c:348               trace: built-in: git 'gc' '--auto'
Run Code Online (Sandbox Code Playgroud)

它基本上是对远程主机执行 ssh,运行git-upload-pack它发送打包的git-fetch-pack对象,然后从另一个存储库接收丢失的对象。

man git-upload-pack我们可以读到:

由 调用git fetch-pack,了解对方缺少哪些对象,打包后发送。

而在man git-fetch-pack我们可以看到:

git-upload-pack可能的远程存储库上调用并要求它发送此存储库中缺少的对象,以更新命名的头。本地可用的提交列表是通过扫描本地 refs/ 层次结构找到的,并发送到git-upload-pack另一端运行。


要回答这个问题,之间的区别git fetch remotegit fetch remote branch-name,就是当你不指定<refspec>参数(如分公司),它获取所有分支机构和/或标签(参见:git ls-refs)从一个或多个其他存储库连同所需物品来完成他们的历史。默认情况下,仅下载可通过获取的对象访问的标签(例如,您最终只会获得指向您感兴趣的分支的标签)。

当您使用显式分支和/或标签运行时,git 首先确定需要获取的内容,然后仅获取相关的 refs(分支或标签)。例如git fetch origin master将只获取主分支。