git pull真的是git fetch + git merge吗?

h43kikqp  于 2023-11-15  发布在  Git
关注(0)|答案(3)|浏览(205)

我在下面的沙箱中练习git:https://learngitbranching.js.org/?NODEMO
我在两个单独的会话中运行了两组命令。第一组命令的顺序如下:

  1. git clone
  2. git checkout -b feature
  3. git push
  4. git fakeTeamwork main 1
  5. git fakeTeamwork feature 1
  6. git pull

字符串
第二组命令的顺序类似,但我在最后使用git fetch + git merge

  1. git clone
  2. git checkout -b feature
  3. git push
  4. git fakeTeamwork main 1
  5. git fakeTeamwork feature 1
  6. git fetch
  7. git merge o/feature


如果git pull = git fetch + git merge,为什么两个结果不同?似乎git pull没有更新所有的远程跟踪分支。这只是沙箱的缺陷,还是这实际上是在git中发生的?
注意:命令git clonegit fakeTeamwork只是为沙箱构建的命令
谢谢你,谢谢你

v1uwarro

v1uwarro1#

似乎git pull并没有更新所有的远程跟踪分支。
这可能会发生,是的。它确实会发生在:

  • 例如,git pull运行git fetch origin master
  • 因此,git fetch origin master仅更新origin/master

但是,在1.8.4之前的Git版本中,一些git fetch操作根本不会更新任何远程跟踪名称。这里的git fetch origin masterorigin/master没有影响。
除此之外,我们还有其他几种特殊情况:

  • 如果git pull被配置或被告知运行git rebase,它使用的第二个命令是git rebase,而不是git merge。因此,明显的替代是git fetch后跟git rebase。这里的一些细节甚至更多地依赖于Git版本:特别是,在git rebase --fork-point出现之前,git pull就实现了--fork-point模式来进行变基(实际的--fork-point选项最早出现在Git 1.9中,但git pull在1.6版本中做了特殊的工作-我查过一次精确的版本,但现在使用的最早的Git似乎是CentOS,在一些发行版中包括一些Git 1.7版本)。
  • 有一种非常特殊的情况:如果您创建了一个空仓库,添加了一个remote,然后运行git pull,那么还没有现有的分支。(您可以在以后使用孤立分支再次触发这种情况。)在这种情况下,git pull运行的不是merge或rebase,而是一个专门的git checkout

分支的 upstream 设置在这里很重要,这取决于你传递给git pull或fetch和second命令的参数。一般来说,除了你注意到的一些远程跟踪名称有时不会更新的警告之外,这些命令的工作方式基本相同。

展开查看全部
uqdfh47h

uqdfh47h2#

git pull真的是git fetch + git merge吗?
简而言之,是的。
然而,值得指出的是,git fetch(在没有任何参数的情况下调用时)更新的 * 哪些 * 远程跟踪分支是由remote.<repository>.fetch配置变量决定的。
如果你在真实的Git仓库中运行git config remote.origin.fetch,你应该看到以下内容:

  1. +refs/heads/*:refs/remotes/origin/*

字符串
这被称为 refspec*告诉Git获取origin远程中的所有分支(:的右侧),并将它们放入本地存储库中(:的左侧)。如果不带任何参数运行git pullgit fetch,所有新的和现有的远程跟踪分支都将通过此设置进行更新。
从文档中:
当运行git fetch而没有在命令行上指定要获取的分支和/或标记时,例如git fetch origingit fetchremote.<repository>.fetch值用作引用规范-它们指定要获取的引用和要更新的本地引用。(即任何与值refs/heads/*的左侧匹配的ref),并更新refs/remotes/origin/*层次结构中相应的远程跟踪分支。
一旦开始将分支名称传递给git pullgit fetch,这种行为就不再适用,正如@torek在his answer中指出的那样。

mnowg1ta

mnowg1ta3#

你可以使用环境变量GIT_TRACE=1来查看git的大致功能。例如,在我的git 2.42中:

  1. $ GIT_TRACE=1 git pull
  2. # ... shortened ....
  3. trace: run_command: git fetch --update-head-ok
  4. trace: run_command: git merge FETCH_HEAD

字符串
当然,除了这些命令之外,git还做其他事情(例如,根据本地状态做出决策,发布错误)。注意:您可能会看到其他run_command:跟踪,它们是fetchmerge的一部分。

相关问题