Squash all Git commits with git squash-all

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

~

Did this help you out? Like what you see?
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!

BuymeaCoffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Published by Bramus!

Bramus is a frontend web developer from Belgium, working as a Chrome Developer Relations Engineer at Google. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Unless noted otherwise, the contents of this post are licensed under the Creative Commons Attribution 4.0 License and code samples are licensed under the MIT License

Join the Conversation

2 Comments

  1. 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?

    1. 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 …

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.