Git rebase & co.

Table of Contents

1 context: code review/development iteration

1.1 the process: (1) submit, (2) review, (3) goto 1

1.2 iteration history

1.2.1 squash intermediate commits because they don’t matter

1.2.2 adjust commits and commit logs according to review

2 keeping the history linear

2.1 what ‘git merge’ and ‘git pull’ (and ‘git push’ sometimes) do

2.1.1 creates a “merge commit”

see the awesome Git for Computer Scientists

Sorry, your browser does not support SVG.

2.1.2 show example of linear and non-linear history

2.2 why should i care?

2.2.1 helps understand code evolution

2.2.2 helps bisection (‘git bisect’)

2.2.3 possibly helps continuous integration

2.3 visualizing the history

  • using gitk (which is part of Git)
  • using Magit (in Emacs)
  • using a Web interface (GitLab, cgit, etc.)

2.4 pull/merge requests

2.4.1 by default, they introduce merge commits!

2.5 note: sometimes you do need parallel dev branches, that’s fine!

3 rebasing

3.1 the Git commit graph

Do not miss Git for Computer Scientists!

Sorry, your browser does not support SVG.

3.2 rebasing your changes before pushing

For example, assuming you are working on the ‘master’ branch and have a bunch of local commits ready to be pushed, you would run these commands:

$ git pull --rebase  # fetch remote changes, and rebase on top of them
$ git push

Sometimes ‘git pull –rebase’ will result in conflicts that need to be resolved. Assuming ‘foo.cpp’ has a conflict, you would edit it to fix those conflicts (look for “>>>”), and then:

$ git add foo.cpp
$ git rebase --continue

3.3 make ‘git pull’ rebase by default

git config branch.master.rebase true

From now on ‘git pull’ will always rebase. \o/

3.4 tell GitLab to rebase when you accept merge requests

gitlab-merge-request-rebase.png

4 rebase, “history rewriting”

4.1 Caveat: don’t rebase a published branch!

4.2 tools

  1. Magit (Emacs)

    magit.png

  2. Fugitive (Vim)
  3. command-line: ‘git rebase -i’ etc.

4.3 amending the last commit of a branch

git add foo                     # stage changes
git commit --amend              # amend the last commit on the branch

4.4 rebasing a branch on top of another one

This will simplify the reviewers life by make sure the changes apply on the latest ‘master’, for example.

git checkout master
git pull           # update my copy of 'master'
git checkout my-feature-branch
git rebase master  # rebase 'my-feature-branch' on 'master'

4.5 squashing, dropping, reordering, rewriting commits

All with ‘git rebase -i’ (or similar in your favorite UI). Glossary:

  • squashing two or more commits: turning them into a single commit
  • dropping: get rid of commits you don’t like, after all
  • reodering: you can change the order of commits in the history
  • rewriting: change the commit log and/or what the commit does

4.6 pro tip: autosquash (thanks bgoglin!)

  • Write “squash! the summary line” in your commit log and then ‘git rebase n–autosquash’ will automatically flag it as candidate for squashing with the commit that has “the summary line”. See git-rebase(1). Also works with “fixup!” (difference is that the fixup commit log is discarded.)
  • git config branch.THE-BRANCH.autoSquash true
  • Actually, ‘git commit –fixup ID’ creates the right summary line!

Created: 2018-01-23 ar. 13:25

Validate