Refactoring Git Branches with Interactive Rebase and Autosquash in Android Studio
For most developers, Git is the go-to version control system for their software projects. At PSPDFKit, we host all our projects on GitHub, and many of them inside our monorepo, which currently counts about 50 active contributors. Our teams pride themselves on a clean commit history — not only on our main branch, but also inside the working branches maintained by individuals.
One particularly useful tool for keeping a clean commit history on a working branch is Git’s --interactive
rebase option. Building on top of Git’s regular git rebase
command, interactive rebasing allows users to modify single commits of the rebased branch by applying transformations such as commit renaming, reordering of all commits, removal of unwanted commits, merging of two or more commits into one, and more.
As an Android developer who likes to stay inside my preferred IDE as much as possible, I’m happy that Android Studio offers an easy-to-use integration of interactive rebasing that serves all my needs for commit housekeeping. Let’s look at how it works!
Whoops! A Typpo.
First, we’ll take a quick look at one of the many uses of interactive rebasing. Consider writing the following method in your Android app:
fun List<String>.fuzzyMatc(filterQuery: String): List<String> { // Fuzzy stuff in here. }
Let’s commit this:
git add .
git commit -m "Add fuzzy matcher method"
git push
All great, and the tests are green too! 🙌 But, oh no! A typo slipped into the method name I just committed. Let’s fix it and create another commit:
git add .
git commit -m "Fix typo in method name"
Problem solved. But now the git log
of my branch shows one of those dreaded “fix” commits:
❯ git log --format=oneline
6c1356e (HEAD -> fuzzy-feature) Fix typo in method name
e28d2e3 Add fuzzy matcher method
Let’s (Re)Write History
To remove any signs of the embarrassing naming mistake I made, I’m going to rewrite the commits on my branch. Nothing easier than that! With Android Studio’s interactive rebase UI, I can use the fixup
operation to merge my latter commit into the former. Here’s how it works:
-
Open the Git tool window via View > Tool Windows > Git, or by using the Git button at the bottom of Android Studio.
-
Right-click the first of the two commits (mind the chronological order!), and select Interactively Rebase from Here…
-
Select the Fix typo in method name commit, and then select Squash > Fixup to merge the two commits together.
-
Click Start Rebasing to merge those commits into a single one.
Et voilà! The commit history is clean again. The result is the original commit, amended with the changes of the fixup commit:
The mindful Git user probably noticed that the demonstrated fix could have been done using
git commit --amend
as well. However, using interactive rebase, it’s possible to fix up much older commits too — rather than only the previously committed one — by simply dragging the fixup commit right after the target to fix up.
Sasquatch? Autosquash!
While not as renowned as Bigfoot, --autosquash
is a very real Git option for rebasing — one that autoconfigures the interactive rebase dialog when using specific Git commit naming conventions.
Consider the previous example: With autosquash, instead of manually marking a commit as a fixup for another commit, it’s sufficient to start the fixup commit message with !fixup
, followed by the message of the commit to fix up. For example:
git commit -m "fixup! Add fuzzy matcher method"
Here’s how our commit log would look now:
❯ git log --format=oneline bcc8e09 (HEAD -> fuzzy-feature) fixup! Add fuzzy matcher method e28d2e3 Add fuzzy matcher method
After running git rebase --interactive --autosquash
, Git will configure the rebase dialog the same way we did it manually before.
But how does this work within Android Studio? It gets even simpler. Instead of committing the fixup changes manually — either from the command line, or even from within Android Studio — all you need to do is right-click the fixup target commit inside Android Studio’s Git tool window, and then select Fixup… You can then commit the changes as suggested by Android Studio, which will automatically use the correct commit message:
After that, you continue with interactive rebasing, as explained before.
Piecing It Together
There’s one last (or rather first) step to making autosquash work within Android Studio: By default, Android Studio won’t apply the --autosquash
option when triggering an interactive rebase. To make it autosquash, you need to globally enable the --autosquash
option, using either your Git user config or the global Git config. From your terminal, run:
git config --global rebase.autosquash true
It’s safe to enable this option, since Git will only ever autoconfigure your interactive rebase if there are commits prefixed with !fixup
, !squash
, or similar commands. (Check out Git’s --autosquash
reference docs for the extensive list of commands.)
Is There More?
Glad you asked. Yes, there is! Fixups are just one of the many tools Git’s interactive rebase has to offer. Here are some more ideas of things you can actually do with interactive rebase:
-
Splitting up a commit into two or more individual commits.
-
Completely editing previously made commits while keeping everything that was committed before and after.
-
Reordering of commits on your branch.
As Martin Fowler once said: “Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” In my opinion, the same applies to Git commit histories. So, to become better programmers, let’s rewrite history together!