Kaushik's Blog

Absorbing and Autosquashing

Those better versed in git-fu may know already, but TIL about git absorb and git rebase --autosquash.

Have you ever made a commit, done other work, found an issue in that first commit, and made a cleanup commit? Have you then used fixup in an interactive rebase?

An interactive rebase may look something like this:

pick 6fd784a # Update logic in helper function gen_actions_of_type
pick 47f1569 # Add type annotations
pick 0aec529 # Remove debug print
pick 07c4790 # Fix typo in helper function (SHOULD FIXUP)

This can get annoying. Sometimes, I know I should fixup a commit, but I don't know which parent commit it goes into. This especially happens when I commit small things with the message typo or to fixup.

Enter git absorb

git absorb associates staged cleanups with the commits they belong to.

The usage is simple:

Example:

$ git add .
$ git absorb
Nov 11 16:20:26.804 INFO committed, header: +1,-1, commit: cbb7a7fa5c5e2d035c57f32ed5805463a497ffdc
$ git log --oneline -n 5
cbb7a7f (HEAD -> feat/ongoing-dev-work) fixup! Update logic in helper function gen_actions_of_type
0aec529 Remove debug print
47f1569 Add type annotations
6fd784a Update logic in helper function gen_actions_of_type

Enter --autosquash

The really nice thing about commits that start with fixup! is that git rebase can natively handle them!

A regular interactive rebase would look like this. I'd have to move cbb7a7f where it belongs, under the first commit, and change pick to fixup.

pick 6fd784a # Update logic in helper function gen_actions_of_type
pick 47f1569 # Add type annotations
pick 0aec529 # Remove debug print
pick cbb7a7f # fixup! Update logic in helper function gen_actions_of_type

Or I can let git rebase --autosquash handle it for me. The git-rebase-todo looks like this:

pick 6fd784a # Update logic in helper function gen_actions_of_type
fixup cbb7a7f # fixup! Update logic in helper function gen_actions_of_type
pick 47f1569 # Add type annotations
pick 0aec529 # Remove debug print

It magically reorders fixup commits to put them right after the commits they reference. It also changes the action from pick to fixup so that they are coalesced.

The one-two punch of git absorb and git rebase --autosquash slots nicely into my existing workflow for making small units of work that work.


  1. I like staging changes with VS Code's Source Control interface. It allows for granular control over the changes I want in any particular commit.

#git