Have you ever put off git commit because your code "wasn't clean enough", "doesn't have tests", or "doesn't compile"?
In this workshop, we'll practice techniques for cleaning history between commit and push so that you can commit more often with less thought. I'll share some of the techniques I use to clean up a few (dozen) commits of varying quality.
We will cover:
git add --patch,--amend,--squash, and--fixup,- and
git rebase --interactivewith both--autosquashand--exec
so that you can git commit now and (over)think later!
For this workshop, please have a recent version of Git (>=2.35?) in a bash-like shell ready. If you are on Windows, Windows Terminal with git-bash or WSL should be fine. (PowerShell or CMD may overstrain your facilitator's humble faculties).
If you don't use command-line Git on a regular basis, you may want to do the first two exercises in Version Control (Git) · Missing Semester (mit.edu) before this workshop. Skimming the video and notes may also be helpful.
You may find this workshop unnecessary if you regularly use the features documented in Git - Rewriting History (git-scm.com) and are comfortable with git rebase: what can go wrong? (jvns.ca).
For convenience, helpful git aliases including git lol and git lola are provided in project.gitconfig. Do:
git config --local include.path ../project.gitconfigto add them to your local repo.
You've been tasked with creating a file containing the first few values of the Fibonacci sequence and appropriate tests. Late yesterday, you got to "mostly done" (perhaps). Today, you need to fix any remaining bugs and clean up your commit history before opening a PR.
-
Create your branch from yesterday:
git switch -c my-branch origin/main -
Inspect your work, then do a rebase to incorporate the fixes you've made:
git lol --patch origin/base..HEAD git rebase --interactive --autosquash origin/base
When prompted to edit the commit message for the
squash!, comment out any lines that shouldn't be part of your final history. -
Correct your copy-paste error by changing:
self.assertEqual(len(triples), len(self.values) - 1)
to
self.assertEqual(len(triples), len(self.values) - 2)
and
git add.Since this only affects your most recent commit (check
git lol -1 --patch), justgit commit --amendthis change. -
Run the tests by
./test_fib.pyand fix the mistakes you find. (Changeself.assertLess()toself.assertLessEqual()and correct the final line infib.txt.) -
Use
git add --patchto stage the change totest_fib.py. -
Use
git annotate HEAD -- test_fib.pyto determine which commit to fix, then dogit commit --squash <commit hash>and include an updated commit message below thesquash! ...line. -
Use
git add -p(short for--patch) to stage the change tofib.txt. -
Use
git annotate HEAD -- fib.txtto determine which commit to fix, then dogit commit --fixup <commit hash>. -
Apply your fixes by rebasing again.
-
Reorder commits: use
git rebase --interactiveto move thetest_fib.pychanges to the beginning of your history. -
Do
git rebase --interactive origin/base --exec './test_fib.py'to verify that each of the corrected commits passes all the tests.
The final branch contains all needed commits. The solution branch is fully rebased and tested.
-
Try splitting a commit into two or more commits (see Git - Rewriting History (git-scm.com) for details)
-
Try some convenience tooling such as:
Thanks to Anna and swan for inspiring this workshop and to Tool Talkers Wolf, Ryan, and Clint for their input.