git-rebase: A Play in Four Acts

While not as frowned upon as it once was1, rebasing is not a light operation and a little goes along way. A rebase allows rewriting history to provide the a reader a cleaner view of the past. The ultimate expression of this is squashed merge commits which during a merge compresses everything into a single commit and merges that instead. Putting team-workflow questions aside, rebasing has a place in a day-to-day write/edit/ review workflow.

Rebasing is a fundamental tool for working in a write/edit/review workflow. Make frequent commits to keep the workspace clean. Review the branch about once a day and reorder them into logical groups. Before making a pull request or merging, review the branch and squash together common changes, fix up the commit messages, and put the finishing touches in place. Nobody can make sense of “fix it” when reviewing commits. Helpful commit messages and tidy history helps the future person—possibly yourself—figure out what changed.

The “acts” below are one example of how a rebase can shape and form the history of a set of changes. The git-rebase interactive mode documentation explains more in depth how an interactive rebase is run.

Note

The rebase examples here are from the reflog and presented here in reverse order, i.e. the order you would see them in the interactive rebase editor.

Act 1: Reordering

Shuffle

Passing --stat to git log will show which files were changed in the commits. Add -p to print the full diff. Putting commits into related chunks and resolving conflicts at this point makes the later steps easier. The fixup command can be used for small changes at this point.

33a2bdbb10 (refs/remotes/origin/master, refs/remotes/origin/HEAD, refs/heads/master) HEAD@{82}: rebase -i (start): checkout master
4510ed8bdd HEAD@{81}: rebase -i (pick): #382: Set fks to null on delete
89e21f5c86 HEAD@{80}: rebase -i (pick): #382: Update model tests
bab381ee69 HEAD@{79}: rebase -i (pick): #382: Generation name improvements
526887e23e HEAD@{78}: rebase -i (pick): meta: don't strip required attributes here
c225d76aee HEAD@{77}: rebase -i (pick): #382: Update generation fixture
dbf3fe6bf8 HEAD@{76}: rebase -i (pick): #382: Fix name mock
7c8e50a22a HEAD@{75}: rebase -i (continue): #382: Update meta tests
155cb5b297 HEAD@{74}: rebase -i (pick): remove resource_name from cell
aeda7a71bd HEAD@{73}: rebase -i (pick): allow returning object from cell
307e473220 HEAD@{72}: rebase -i (continue): remove value_field from column
92af6bc9f3 HEAD@{71}: rebase -i (pick): cell_tests: fixes for API changes
c42122a8dc HEAD@{70}: rebase -i (continue): #382: Add generic processing
ef7c358240 HEAD@{69}: rebase -i (continue): work on related objects
68d04e4cfe HEAD@{68}: rebase -i (pick): fixture helper, update progress
49591ccd85 HEAD@{67}: rebase -i (continue): wip type 1 tests
d9573c2597 HEAD@{66}: rebase -i (pick): wip lang change
f980e50c60 HEAD@{65}: rebase -i (pick): sheet: only resolve if there is a value
dfdba1e4f1 HEAD@{64}: rebase -i (pick): #382: Flag for export only cell
d732d5f95c HEAD@{63}: rebase -i (pick): wip cleanup sheet.py
5b83d92e97 HEAD@{62}: rebase -i (pick): #382: Add Type 1 processing
ebcfc5ba57 HEAD@{61}: rebase -i (pick): #382: Add Type 1 to web tests
eb5fb9be3d HEAD@{60}: rebase -i (pick): wip additional model tests
f4b9a45262 HEAD@{59}: rebase -i (fixup): wip additional model tests
54b6cc1f82 HEAD@{58}: rebase -i (pick): wip fix some of the frontend
54b6cc1f82 HEAD@{57}: rebase -i (finish): returning to refs/heads/382_generic_processing

Act 2

Cleanup

Clean the commit objects themselves up. Shown here splitting a commit into two pieces so it can be relocated. Redundant units of work can also be merged down or dropped entirely at this point.

68d04e4cfe HEAD@{56}: rebase -i (start): checkout master
49591ccd85 HEAD@{55}: cherry-pick: fast-forward
68d04e4cfe HEAD@{54}: reset: moving to HEAD^
19a9088fb7 HEAD@{53}: commit: wip: generic additions to sheet.py
4f8c4d1fd8 HEAD@{52}: commit: add native processing tests for Type 1
818a1aa513 HEAD@{51}: rebase -i (pick): wip lang change
037b319f74 HEAD@{50}: rebase -i (pick): sheet: only resolve if there is a value
2be934cd0b HEAD@{49}: rebase -i (pick): #382: Flag for export only cell
a0c115e7b8 HEAD@{48}: rebase -i (pick): wip cleanup sheet.py
202c73a345 HEAD@{47}: rebase -i (pick): #382: Add Type 1 processing
718a613dda HEAD@{46}: rebase -i (pick): #382: Add Type 1 to web tests
5a079af88a HEAD@{45}: rebase -i (pick): wip additional model tests
828bdd1dae HEAD@{44}: rebase -i (pick): wip fix some of the frontend
828bdd1dae HEAD@{43}: rebase -i (finish): returning to refs/heads/382_generic_processing

Act 3

Structure

Finish up commit ordering here by relocate any new or updated commits and preparing for final fixup and reword commands.

19a9088fb7 HEAD@{42}: rebase -i (start): checkout master
db9f8d5848 HEAD@{41}: rebase -i (pick): wip lang change
a9b02ff779 HEAD@{40}: rebase -i (pick): sheet: only resolve if there is a value
5e7d1b1c14 HEAD@{39}: rebase -i (pick): #382: Flag for export only cell
d64524ffa6 HEAD@{38}: rebase -i (pick): wip cleanup sheet.py
ec5f55d2f7 HEAD@{37}: rebase -i (pick): #382: Add Type 1 processing
0925b74cd0 HEAD@{36}: rebase -i (pick): #382: Add Type 1 to web tests
7e78006e29 HEAD@{35}: rebase -i (pick): add native processing tests for Type 1
0e8422bcf1 HEAD@{34}: rebase -i (pick): wip additional model tests
5ac156493b HEAD@{33}: rebase -i (pick): wip fix some of the frontend
5ac156493b HEAD@{32}: rebase -i (finish): returning to refs/heads/382_generic_processing

Act 4

Squash

Squash commits down with fixup and put final commit messages into place. Using squash will keep the commit messages for the merged commits if that’s important.

bab381ee69 HEAD@{31}: rebase -i (start): checkout master
9f7a12b5f4 HEAD@{30}: rebase -i (fixup): #382: Generation name improvements
6cb93a09ed HEAD@{29}: rebase -i (reword): #382: Update generation fixture
e1c6e4ec34 HEAD@{28}: rebase -i (reword): #382: Update generation tests/fixtures
2b4c1e79fb HEAD@{27}: rebase -i (fixup): #382: Update generation tests/fixtures
f46484407b HEAD@{26}: rebase -i (reword): remove resource_name from cell
49c27838fc HEAD@{25}: rebase -i (reword): #382: Cell works with groups
63d482b9e1 HEAD@{24}: rebase -i (fixup): # This is a combination of 2 commits.
3a522231f6 HEAD@{23}: rebase -i (fixup): #382: Cell works with groups
632c42288c HEAD@{22}: rebase -i (reword): cell_tests: fixes for API changes
f6ac72af0b HEAD@{21}: rebase -i (reword): #382: Update cell tests for API changes
b81110ebf3 HEAD@{20}: rebase -i (pick): #382: Add generic processing
5626834112 HEAD@{19}: rebase -i (fixup): # This is a combination of 2 commits.
0050fdb906 HEAD@{18}: rebase -i (fixup): # This is a combination of 3 commits.
010b41439a HEAD@{17}: rebase -i (fixup): # This is a combination of 4 commits.
eb289258e2 HEAD@{16}: rebase -i (fixup): # This is a combination of 5 commits.
2c8d1001c6 HEAD@{15}: rebase -i (fixup): # This is a combination of 6 commits.
af63e0b53f HEAD@{14}: rebase -i (fixup): # This is a combination of 7 commits.
0774efac8d HEAD@{13}: rebase -i (fixup): #382: Add generic processing
b2f79ab752 HEAD@{12}: rebase -i (pick): #382: Add Type 1 processing
edf8fa9ab8 HEAD@{11}: rebase -i (pick): #382: Add Type 1 to web tests
1bb0e4cd98 HEAD@{10}: rebase -i (reword): add native processing tests for Type 1
ab7c95844a HEAD@{9}: rebase -i (reword): #382: Add new native processing tests
988cdb8aa9 HEAD@{8}: rebase -i (fixup): #382: Add new native processing tests
99a48230d0 HEAD@{7}: rebase -i (reword): wip fix some of the frontend
988e4f00dc HEAD@{6}: rebase -i (reword): #382: Partial frontend fix
988e4f00dc HEAD@{5}: rebase -i (finish): returning to refs/heads/382_generic_processing
written January 10th, 2017

January 2017

Can’t find what you’re looking for? Try hitting the home page or viewing all archives.