我在以下沙箱中练习git: https://learngitbranching.js.org/?NODEMO
我在两个不同的会话中运行两组命令。第一组命令按顺序如下:
git clone
git checkout -b feature
git push
git fakeTeamwork main 1
git fakeTeamwork feature 1
git pull
第二组命令顺序相似,但我在末尾使用git fetch
+git merge
:
git clone
git checkout -b feature
git push
git fakeTeamwork main 1
git fakeTeamwork feature 1
git fetch
git merge o/feature
如果git pull
=git fetch
+git merge
,为什么两种结果不同?看来git pull
并没有更新所有的远程跟踪分支。这是沙盒的缺陷还是git的实际情况?
git clone
和git fakeTeamwork
只是为沙盒构建的命令
谢谢!
似乎git pull并没有更新所有的远程跟踪分支。
这个可以发生,是的。当
例如,git pull
运行git fetch origin master
,而git fetch origin master
因此只更新origin/master
。
此外,在1.8.4之前的Git版本中,一些git fetch
操作根本不更新任何远程跟踪名称。这里git fetch origin master
对origin/master
没有影响。
除此之外,我们还有其他一些特殊情况:
- 如果
git pull
被配置或被告知运行git rebase
,它使用的第二个命令是git rebase
,而不是git merge
。因此,明显的替代是git fetch
后面跟着git rebase
。这里的一些细节甚至更依赖于Git的版本,尽管:特别是git pull
在git rebase --fork-point
存在之前实现了--fork-point
模式的rebase(实际的--fork-point
选项首次出现在Git 1.9中,但git pull
从1.6版本开始做特殊的工作-我查了一次准确的版本,但这些天使用的最古老的Git似乎是CentOS,在一些发行版中包含一些Git 1.7版本)。 - 有一个非常特殊情况:如果您创建一个空存储库,添加一个远程,并运行
git pull
,则还没有现有的分支。(稍后可以使用孤立分支再次触发这种情况。)在这种情况下,git pull
运行一个专门的git checkout
,而不是合并或重新base。
分支的上游设置在这里很重要,这取决于您传递给git pull
或fetch和second命令的参数。一般来说,除了您注意到的一些远程跟踪名称有时不会更新的警告外,这些主要以相同的方式结束。
git pull
真的是git fetch
+git merge
吗?
简而言之,是的。
然而,值得指出的是,哪些远程跟踪分支由git fetch
更新(当不带任何参数调用时)是由remote.<repository>.fetch
配置变量决定的。如果你在真正的Git repo中运行git config remote.origin.fetch
,你应该看到以下内容:
+refs/heads/*:refs/remotes/origin/*
这称为refspec。*
告诉Git获取origin
远程(:
的右侧)中的所有分支,并将它们放入本地repo (:
的左侧)。如果您运行git pull
或git fetch
而不带任何参数,那么由于此设置,所有新的和现有的远程跟踪分支将被更新。
来自文档:
运行
git fetch
时,没有指定分支和/或标签在命令行获取,例如git fetch origin
或git fetch
,remote.<repository>.fetch
值被用作refspecs - they指定要获取哪些引用以及要更新哪些本地引用。的上面的例子将获取origin
中存在的所有分支(即:任何匹配值左边的ref (refs/heads/*
)并更新相应的远程跟踪分支refs/remotes/origin/*
层次结构。
一旦你开始将分支名称传递给git pull
或git fetch
,这种行为就不再适用了,正如@torek在他的回答中指出的。