Sometimes, when working in a feature branch, you’ll find yourself wishing you could segment your work without having to create and maintain multiple feature branches. Thankfully, Git has a nifty way of handling this use case via empty commits. Example:
git commit --allow-empty --no-verify --message "----- End of API Work -----"
The above can broken down as follows:
-
--allow-empty: Makes empty commit creation possible. -
--no-verify: Bypasses Git Hooks since empty commits will most likely trip up your lint checks. -
--message: Specifies the commit subject. The five dashes (-) on each side of the message makes for a nice — and clear — visual que when reviewing your feature branch commit history.
When creating an empty commit, you’ll only have the commit message (subject) which, as shown above, is: "----- End of API Work -----". If you were to grab the SHA of this commit and use git show to view it, you’d see output similar to the following:
git show f49f086fbc36
# commit f49f086fbc364c99c5a1d31530f213e1ab59371f (HEAD -> demo)
# Author: Brooke Kuhlmann <[email protected]>
# Date: Sat Oct 11 14:40:18 2025 -0600
#
# ----- End of API Work -----
Typical uses of empty commits are:
-
Trigging your Continuous Integration (CI) builds (although you’re better off using
git commit --amend --no-editwith no file changes to update the SHA of your last commit to trigger a new build because this doesn’t create a commit you need to delete later). -
Recording a commit message for work you are planning to do. Later, you’d amend and/or rebase the commit with an actual implementation. Using an empty commit, like this, ends up being a form of pre-planning. In truth, you’re better off making atomic commits and then rebasing to reorganize your commits so they make chronological sense.
-
Segmenting your work so you can focus on the macro and micro aspects of your architecture all within a single feature branch.
Out of all of the above scenarios, only the last (segmentation) is where empty commits are most useful. Here’s a visual example of what this would look in terms of Git commit messages:
Added authorization endpoint Added models endpoint Added devices endpoint Added API documenation ----- End of API Work ----- Added registration page Added login page Added user resources Added model resources Added device resources Added site navigation ----- End of UI Work -----
As you can see, there are two segments of work: API and UI. The first empty commit denotes where we completed the API work and the second empty commit denotes where we completed the UI work. This is extremely powerful when you want to work on a complex piece of architecture while ensuring all of the pieces fit together. This allows you to constantly fix issues and improve the implementation while using Git Rebase to maintain a clean and reviewable commit history.
Once you are satisfied with your work and the build is green, you can then create a feature branch of your API work and push it up for review. This allows you to continue working on the UI work or start another segment of related work. If any changes need to be made based on feedback to your work during the code review, you can easily rebase all changes without missing a beat. Once your changes are accepted, all you have to do is rebase your original feature branch upon the main branch, delete the "----- End of API Work -----" empty commit, and you’re back to working on your UI work (or pushing it up for review next if ready).
You won’t always need this workflow but when dealing with teams that are slower than you, this can be a life saver so you can continue working, unencumbered, while letting Git Rebase keep your feature branch work up-to-date and clean.
As powerful as empty commits can be, there are a few guidelines to adhere to:
-
Use as an aid to organize your work before publicly sharing with others.
-
Use Git Lint to ensure empty commits fail your CI builds so you always remember clean them up before rebasing onto your
mainbranch. -
Avoid applying empty commits to your
mainbranch. Empty commits have no value on yourmainbranch and are only meant for temporary use in your feature branch.
Now you know how to use empty commits in your work. Even better, they will help you organize your thoughts and resulting output. Enjoy!