Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is git pull really git fetch + git merge?

I was practicing git in the following sandbox: https://learngitbranching.js.org/?NODEMO

I ran two sets of commands in two separate sessions. The first set of commands in order is as follows:

git clone
git checkout -b feature
git push
git fakeTeamwork main 1
git fakeTeamwork feature 1
git pull

The second set of commands in order are similar but I use git fetch + git merge at the end instead:

git clone
git checkout -b feature
git push
git fakeTeamwork main 1
git fakeTeamwork feature 1
git fetch
git merge o/feature

If git pull = git fetch + git merge, why are the two outcomes different? It seems that git pull does not update all the remote tracking branches. Is this just a flaw of the sandbox or is this actually what happens in git?

Note: The commands git clone and git fakeTeamwork are just commands built for the sandbox

Thank you!

like image 797
Jason Li Avatar asked Sep 16 '25 02:09

Jason Li


2 Answers

It seems that git pull does not update all the remote tracking branches.

This can happen, yes. It does happen when:

  • git pull runs git fetch origin master, for instance, and
  • git fetch origin master therefore only updates origin/master.

Futhermore, in Git versions predating 1.8.4, some git fetch operations do not update any remote-tracking names at all. Here the git fetch origin master has no effect on origin/master.

Besides these, we have several other special cases:

  • If git pull is configured or told to run git rebase, the second command it uses is git rebase, not git merge. The obvious substitute is thus git fetch followed by git rebase. Some specifics here are even-more Git version dependent, though: in particular, git pull implemented --fork-point mode for rebase before git rebase --fork-point existed (the actual --fork-point option first occurring in Git 1.9, but git pull doing special work since some 1.6 version—I looked up the precise version once, but these days the oldest Git in use seems to be for CentOS, which includes some Git 1.7 versions in some distributions).
  • There is one very special case: if you create an empty repository, add a remote, and run git pull, there is no existing branch yet. (You can trigger this case again later using orphan branches.) In this case instead of either merge or rebase, git pull runs a specialized git checkout.

The upstream setting of a branch matters here, depending on what arguments you pass to git pull or to the fetch and second commands. In general these mostly end up working the same way, except for the caveat you noted about some remote-tracking names sometimes not getting updated.

like image 58
torek Avatar answered Sep 18 '25 17:09

torek


Is git pull really git fetch + git merge?

In short, yes.

However, it's worth pointing out that which remote tracking branches are updated by git fetch (when invoked without any arguments) is determined by the remote.<repository>.fetch configuration variable.

If you run git config remote.origin.fetch in a real Git repo, you should see the following:

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

This is called a refspec. The * is telling Git to fetch all branches in the origin remote (the right-hand side of the :) and put them in your local repo (the left-hand side of the :). If you run git pull or git fetch without any arguments, all new and existing remote tracking branches are going to be updated thanks to this setting.

From the documentation:

When git fetch is run without specifying what branches and/or tags to fetch on the command line, e.g. git fetch origin or git fetch, remote.<repository>.fetch values are used as the refspecs—​they specify which refs to fetch and which local refs to update. The example above will fetch all branches that exist in the origin (i.e. any ref that matches the left-hand side of the value, refs/heads/*) and update the corresponding remote-tracking branches in the refs/remotes/origin/* hierarchy.

This behavior no longer applies once you start passing the branch name to git pull or git fetch, as @torek pointed out in his answer.

like image 32
Enrico Campidoglio Avatar answered Sep 18 '25 19:09

Enrico Campidoglio