git fetch究竟做了什么? [英] What does git fetch really do?
问题描述
现在我想合并一个远程分支,将它命名为 origin / branch1
,并与我的本地分支 branch1
,因为我的合作伙伴在我们上次合并后在远程将一个新的提交推送到了branch1,并且自他上次提交以来我没有提交并且想要从此提交获取更新。我使用了下面的命令:
$ b $ pre $ git fetch origin branch1
压缩...
* branch branch1 - > FETCH_HEAD
$ git merge origin / branch1
已经是最新的
这不是我想要的。这样做之前我的想法是使用fetch获取我的合作伙伴添加的内容,并使远程分支 origin / branch1
得到更新。但是,已经最新意味着我无法获得本地分支中的更新1。然后,我通过
$ git检查了 origin / branch1
的sha1值ls-remote origin
,发现它在上次合并后保持旧提交的陈旧值。它告诉 git fetch origin origin branch1
不能更新 origin / branch1
。我做了另一个实验,我的合作伙伴在他的身边创建了另一个名为branch2的分支,并将分支2中的提交推送到远程原点。然后,我仍然使用
$ git fetch origin branch2
压缩...
$ git merge origin / branch2
没有分支名为origin / branch2
Compressing告诉我:第一个命令成功地在branch2中下载了一些东西,但是,第二个命令告诉我没有名为origin / branch2的分支!因此,我得出结论,既不能在本地创建 git fetch origin branchname
更新 origin / branchname
,也不能创建远程分支if它不存在。
当我用 git替换
git fetch origin branch#
后所有的 git merge
s按照我的预期工作。
然而,我经常看到
$ git fetch远程分支名称
$ git merge remote / branch-name
所以我的问题是 git fetch remote
和 git fetch remote branch-name
?并且在什么情况下我可以成功地让它按照我的愿望通过这种组合方式工作?
如果您需要知道究竟是什么 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.01 3625 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'
从github.com:FOO/BAR
*分支大师 - > 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'
基本上是对远程主机执行ssh,运行发送对象的 git-upload-pack
到 git-fetch-pack
,它接收来自另一个存储库的缺少对象。
$ b
在 man git-upload-pack
我们可以阅读:
由
$ b调用git fetch-pack
$ b
调用
> git-upload-pack
在一个可能的远程仓库中,并要求它发送这个仓库中缺少的对象,以便更新被命名的头。本地可用的提交列表通过扫描本地refs / hierarchy发现,并发送到另一端运行的git-upload-pack
。
要回答这个问题,
git fetch remote
和git fetch remote branch-name
,就是当你不指定< refspec>
参数时作为分支),它从一个或多个其他存储库以及完成其历史记录所需的对象中提取所有分支和/或标签(参考:git ls-refs
) 。默认情况下,只有被获取的对象可以访问的标签才会被下载(例如,您最终只能使用指向您感兴趣的分支的标签)。
和当你使用明确的分支和/或标签运行时,git首先确定需要获取什么,然后只获取相关的参考(分支或标签)。例如。
git fetch origin master
将仅提取master分支。Now I want to merge a remote branch, naming it
origin/branch1
, with my local branchbranch1
, as my partner pushed a new commit to branch1 on remote after our last merge, and I haven't committed since his last commit and want to get update from this commit. I used the following commands:$ git fetch origin branch1 Compressing... *branch branch1 ->FETCH_HEAD $ git merge origin/branch1 Already up-to-date
That was not what I intended. What was in my mind before doing this was using fetch to get what my partner added and made the remote branch
origin/branch1
being updated. However, the "Already up-to-date" means I failed to get the updates in my local branch1. Then I checked the sha1 value oforigin/branch1
by$ git ls-remote origin
and found that it kept the stale value of old commit after we merged last time. It tells that the
git fetch origin branch1
cannot updateorigin/branch1
. I did another experiment, where my partner created another branch named "branch2" in his side and pushed a commit in branch2 to the remote origin. Then I still used$ git fetch origin branch2 Compressing... $ git merge origin/branch2 No branch named "origin/branch2"
The "Compressing" told me that the first command downloaded something in branch2 in origin successfully, however, the second command told me that there was no branch named origin/branch2! Thus I concluded that neither could
git fetch origin branchname
updateorigin/branchname
locally, nor could it create a remote branch if it doesn't exist.After I replace
git fetch origin branch#
withgit fetch origin
, all thegit merge
s worked as I expected.However, I often see the combination of
$ git fetch remote branch-name $ git merge remote/branch-name
So my question is what is the difference between
git fetch remote
andgit fetch remote branch-name
? And in what conditions could I succeed in letting it work as my wish by this combination?解决方案If you need to know what exactly
git fetch
is doing or any othergit
command, just prefix it withGIT_TRACE=1
, so it'll give you trace output with any other commands which are invoked, e.g.$ 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'
which basically is doing ssh to the remote host, running
git-upload-pack
which send objects packed back togit-fetch-pack
which receives missing objects from another repository.In
man git-upload-pack
we can read:Invoked by
git fetch-pack
, learns what objects the other side is missing, and sends them after packing.And in
man git-fetch-pack
we can read:Invokes
git-upload-pack
on a possibly remote repository and asks it to send objects missing from this repository, to update the named heads. The list of commits available locally is found out by scanning the local refs/ hierarchy and sent togit-upload-pack
running on the other end.
To answer the question, the difference between
git fetch remote
andgit fetch remote branch-name
, is that when you don't specify<refspec>
parameter (such as branch), it fetches all branches and/or tags (refs, see:git ls-refs
) from one or more other repositories along with the objects necessary to complete their histories. By default only tags which are reachable by the objects that are fetched are downloaded (e.g. you end up only with tags that point at branches that you are interested in).And when you run with explicit branches and/or tags, git first determines what needs to be fetched, then getting only the relevant refs (branches or tags). E.g.
git fetch origin master
will fetch only the master branch.这篇关于git fetch究竟做了什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!