Getting solid at Git rebase vs. merge

Each one is best for specific purposes, so learn when to use them efficiently, and why.

A clean, usable history that makes sense

When should I use merge?

When should I use rebase?

Quick summary: core workflow principles

Merging a branch, the smart way

Remaining identifiable thanks to a true merge

A true merge is what you automatically get when the merged branch diverged from the receiving one
We can force a true merge when there is no divergence by using the --no-ff option

Merging transparently by ensuring a fast-forward

Merging a direct descendant will fast-forward by default
By rebasing a diverged local branch before merging it, we can ensure fast-forward, so guarantee it will be transparent in the final graph.

Beware of the merge settings you might have

Rebasing an old branch

(master) $ git rebase master better-stats

Cleaning up your local history before pushing

(experiment) $ git rebase -i origin/experiment
$ git config —global alias.tidy “rebase -i @{upstream}..”
(experiment) $ git tidy
A particularly messy local history since the last sync
(experiment) $ git rebase -i origin/experiment
pick 057ad88 Locale fr-FR
pick ef61830 Opinion bien tranchée
pick 8993c57 ML dans le footer + rewording Interactive Rebasing
pick dbb7f53 Locale plus générique (fr)
pick c591fd7 Revert "Opinion bien tranchée"
pick 2863a46 MàJ .gitignore
# Rebase 34ae1ae..2863a46 onto 34ae1ae
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted. #
# Note that empty commits are commented out

Squashing and rewording

pick 057ad88 Locale fr-FR
pick dbb7f53 Locale plus générique (fr)
pick 057ad88 Locale fr-FR
fixup dbb7f53 Locale plus générique (fr)
reword 057ad88 Locale fr-FR
fixup dbb7f53 Locale plus générique (fr)

One step forward, one step back

reword 057ad88 Locale fr-FR
fixup dbb7f53 Locale plus générique (fr)
pick 8993c57 ML dans le footer + rewording Interactive Rebasing
pick 2863a46 MàJ .gitignore

Laser cutting

reword 057ad88 Locale fr-FR
fixup dbb7f53 Locale plus générique (fr)
edit 8993c57 ML dans le footer + rewording Interactive Rebasing
pick 2863a46 MàJ .gitignore

Ignition!

Interactive rebasing pausing post-commit for us to edit it, according to the “edit” verb in the script
Two perfectly unrelated changes in a single file, lumped into one commit out of sheer laziness.
Splitting a single-file lumpy commit, the I-know-git-reset-for-real way.
Two sweet, atomic, single-topic commits as a result of our care and craft…
My oh my, is that a cleaned up history or what?

The git pull and pull + push reflex trap

(feature u+3) $ git push
To /tmp/remote
! [rejected] feature -> feature (fetch first)
error: failed to push some refs to '/tmp/remote'
hint: Updates were rejected because the remote contains work
hint: that you do not have locally. This is usually caused by
hint: another repository pushing to the same ref. You may want
hint: to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help'
hint: for details.
(feature u+3) $

What does git pull do anyway?

Ill-advised merges as pulls go

As git pull merges by default, any new work I pull besides my own local work will result in a merge, which pollutes the graph.

Using rebase for pulls

Explicitly asking git pull to rebase instead of merging. Cool, but prone to being forgotten now and then.

The tricky case of a rebasing pull over a local merge

Rebase inlines merges by default, and boy does that blow hard for most cases.
Pulling with a rebase, still preserving local merges. Yup, the Holy Grail.

Conclusion

Want to learn more?

I make cool stuff and teach others to (Git, Rails, JS/CoffeeScript/Node/etc).

I make cool stuff and teach others to (Git, Rails, JS/CoffeeScript/Node/etc).