Search code examples
gitgithubversion-control

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!


Solution

  • 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.