While working on a branch locally, it can become necessary to make minor
changes to older commits.
For example, consider the need to fix a typo in commit B in the following git
history.
|
One way to do this is use of an Interactive rebase to edit
commit B.
$ git checkout feature
$ git rebase -i main
pick aaaaaa Add functionality
-pick bbbbbb Bind configuration
+edit bbbbbb Bind configuration
pick cccccc Create handlers
Edit the commit
|
1. Auto-squashing
An improvement upon this is use of the
--autosquash
flag for git rebase
.
Combined with git commit --fixup
,
it enables queuing up fixes to older commits.
# On cccccc (HEAD, feature)
$ vim config.py
$ git add config.py
$ git commit --fixup ":/Bind config"
💡 Tip
|
|
This creates a new commit with the message fixup! Bind configuration
.
|
Queue up any number of such fixup
commits and run an interactive
rebase with the --autosquash
flag.
The instruction list will place these commits in their right places, ready to
combine with their targets.
|
Save and quit, and the old commit is all fixed up.
This improves the process but it necessitates recalling the log message of the target commit. This can be more streamlined.
2. Using Tig
Tig is a command-line UI for Git.
It augments the regular usage of git
, and has become my primary method of
committing code.
2.1. Navigating Tig’s main view
Tig’s main view displays a list of commits for the current branch. Try it out:
Run tig
, navigate to a commit with j/k, and open it with
Enter.
Inspect the commit. Move around with j/k, or Ctrl-D/Ctrl-U for page down and up. Close the commit with q and similarly inspect the other commits.
Open the status view by pressing s. Look around using the same keys as before. Quit with Q.
2.2. Partially staging changes with Tig
A productivity win of Tig right out the box is an easier to use method
of partially staging changes (versus git add --patch
).
To try it out, make changes in a repository and open the Tig status
view by running tig status
or by running tig
and pressing s.
In the status view, navigate to a file (j/k) in the
Changes not staged for commit section and open it (Enter).
Inside the file, navigate to a chunk (j/k) and perform one of the following:
-
Stage this entire chunk (u)
-
Stage a single line in the chunk (1)
-
Increase (]) or decrease ([) diff context
-
Split the chunk (\) and go to step 3
-
Close the file (q)
Repeat for other files with uncommitted changes. Similarly unstage changes from files in the Changes to be committed section if necessary.
When ready, commit the staged changes from within Tig
(C in status view) or quit (Q) and run git commit
.
3. Auto-squashing with Tig
Tig is configurable via a ~/.config/tig/config
file.
Among other things, it supports introducing new key bindings that execute
arbitrary git
commands.
Create a ~/.config/tig/config
file if it doesn’t already exist and add
the following to it.
bind main = !git commit --fixup=%(commit) bind main <Ctrl-R> !git rebase --autosquash -i %(commit)
Alternatively, add the following to ~/.gitconfig
instead. This will have the
same effect as the changes suggested above.
[tig "bind"]
main = = !git commit --fixup=%(commit)
main = <ctrl-r> !git rebase --autosquash -i %(commit)
This introduces the following key bindings to the main
view:
-
= will create a new
fixup
commit for the focused commit -
Ctrl-R will being an interactive rebase with auto-squashing enabled on top of the focused commit
To try it out, make changes in a repository and open tig
.
Stage changes in the status view (partially if necessary)
and switch back to the main view (q).
In the main view, navigate to the commit to be fixed (j/k) and
create a new fixup
commit by pressing =.
Queue up as many such fixes as needed.
When it’s time to apply the fixup
commits, navigate to a commit before the
oldest commit being fixed, and press Ctrl-R to start the interactive
rebase.
Adjust the rebase instruction list if necessary, save, and quit.
4. Conclusion
By providing convenient methods of partial staging with auto squashing, Tig streamlines the process of fixing up older commits. It’s a valuable addition to the toolbox for anyone who uses Git.
Edit(2020-04-30): Add instructions for configuring via
~/.gitconfig
.