Fetch & merge or rebase¶
A git pull
defaults to git fetch
followed by git merge origin/main
(assuming
that we are working on branch main
and the remote is called origin
). The
following example compares this fetch-merge strategy vs. a fetch-rebase strategy.
Initial state¶
Elena and Marina collaborate on a project (hosted on GitHub). Elena has already pushed
three commits (A
, B
and C
). Marina has pulled them and pushed two commits of
her own (D
and E
). Meanwhile Elena has committed F
and G
locally and has
executed a git fetch
. The state of the three repositories (on Elena’s and Marina’s
local machines as well as the one on GitHub) at this point is depicted in the three tabs
below. Note that, when visualizing Elena’s repository, we passed -R ..@{u}
[1] to
git dag
which marks the commits reachable from origin/main
but not from
main
.
Elena has to decide what to do about the diverging histories. Git provides two standard mechanisms to combine them: a merge and a rebase.
Elena merges¶
If first Elena performs a merge (git merge origin/main
) followed by a git push
and then Marina executes git pull
, the state of the three repositories would be as
depicted below. Since a fast-forward merge is not possible (due to the
diverging histories), a true merge
is performed – it creates a new “merge-commit” m
. Having such a merge-commit can be
avoided if Elena rebases her work.
Elena rebases¶
If, instead of a merge, Elena first performs a rebase (git rebase origin/main
), the
linear history of the repository would be preserved (for the current setup, this would
be the preferred approach most of the time). Note how the rebase operation recreated
Elena’s G
and F
commits (and preserved their messages) on top of Marina’s commit
E
. The original G
and F
commits are unreachable and can be found only on
Elena’s machine. Comparing the tooltips of e.g., the two F
commits we see that they
have different “committer” dates and the same author date.
The fetch-rebase strategy can be enforced using git pull --rebase
.