Freek just shared his workflow to squash all git commits into one single commit — Handy for when you’re pushing a first public release of a project. His process involves removing the .git
folder and starting off fresh again with a git init
.
Wondering if there are handier/shorter ways to achieve this I set off on a Google Search and found some answers as detailed in this StackOverflow thread. Let’s go over the techniques mentioned.
~
1. Using Orphan Branches
As per Git Documentation:
The first commit made on an orphan branch will have no parents and it will be the root of a new history totally disconnected from all the other branches and commits.
This can be useful when you want to publish the tree from a commit without exposing its full history. You might want to do this to publish an open source branch of a project whose current tree is “clean”, but whose full history contains proprietary or otherwise encumbered bits of code.
After you’ve created the orphan branch, you swap it out the with the “old” master
:
# Create a new branch, with no parent commits
git checkout --orphan squashed-master master
git commit -m "🎉 First commit"
# Overwrite the old master branch with the new one
git branch -M squashed-master master
~
2. Using git commit-tree
Creates a new commit object based on the provided tree object and emits the new commit object id on stdout.
The command below will create one commit object using git commit-tree
and then reset the HEAD
to that commit:
git reset $(git commit-tree HEAD^{tree} -m "🎉 First commit")
~
Alias it!
Since the git commit-tree
method is a git one-liner, you can alias it:
git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} -m "${1:-🎉 First commit}");};f'
From then on you can just run git squash-all
in any repo of your liking:
git squash-all
🙂
I’ve also added this alias to ./freshinstall
, a tool which I built to automatically configure macOS (Preferences, Dotfiles, Installed Software, etc)
~
Pushing your newly created branch
Since you rewrote history, you’ll need to use --force
when pushing your newly created branch.
git push --force origin master
~
Thank me with a coffee.
I don\'t do this for profit but a small one-time donation would surely put a smile on my face. Thanks!
To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.
Cool! Have you benchmarked the last method? At $customer we (ab-)use github and circleci to build git-based dashboards, so that repo has tens of thounsands of commits a day. Every few weeks, it becomes too slow to handle. So we clean the repo. (A variation of Freek’s method).
I wonder how fast the reset-method is. Have you benchmarked it?
Didn’t benchmark it, but an educated guess tells me it’s quite intensive as it’s building a list/tree containing all original commits …