How best to squash old commits How best to squash old commits git git

How best to squash old commits


In order to do a git squash follow those steps:

// X is the number of commits you wish to squashgit rebase -i HEAD~X

Once you squash your commits - choose the s for squash = it will combine all the commits into a single commit.

enter image description here


You also have the --root flag in case you need it

try: git rebase -i --root

--root

Rebase all commits reachable from <branch>, instead of limiting them withan <upstream>.This allows you to rebase the root commit(s) on a branch.  When used with --onto, it will skip changes already contained in `<newbase>`   (instead of `<upstream>`) whereas without --onto it will operate on every change. When used together with both --onto and --preserve-merges, all root commits will be rewritten to have `<newbase>` as parent instead.`


I know that this is already an ancient question but I needed a solution for this.

Long story short, my local git repo (on NFS, no upstream) works as a back up to certain files and I wanted it to have a maximum of 50 commits. Since there are many files and the backups are taken rather often, I needed something that automatically squashes the history, so I created a script that both backs the files up and squashes the history.

#!/bin/bash# Max number of commits preservedMAX_COMMITS=50# First commit (HEAD~<number>) to be squashedFIRST_SQUASH=$(echo "${MAX_COMMITS}-1"|bc)# Number of commits until squashSQUASH_LIMIT=60# Date and time for commit messageDATE=$(date +'%F %R')# Number of current commitsCURRENT_COMMITS=$(git log --oneline|wc -l)if [ "${CURRENT_COMMITS}" -gt "${SQUASH_LIMIT}" ]; then    # Checkout a new branch 'temp' with the first commit to be squashed    git checkout -b temp HEAD~${FIRST_SQUASH}    # Reset (soft) to the very first commit in history    git reset $(git rev-list --max-parents=0 --abbrev-commit HEAD)    # Add and commit (--amend) all the files    git add -A    git commit --amend -m "Automatic squash on ${DATE}"    # Cherry pick all the non-squashed commits from 'master'    git cherry-pick master~${FIRST_SQUASH}..master    # Delete the 'master' branch and rename the 'temp' to 'master'    git branch -D master    git branch -m masterfi

So, what the script basically does is (I removed the back up part):

  1. If there are more than 60 commits, it squashes all the commits from 50 to 60+ into a one commit.
  2. It creates and checks out a new branch based on the commit
  3. Cherry picks the remaining commits from the master (#1 to #49) to the branch
  4. Removes the master branch
  5. Renames the new branch to master.


The age of the commits doesn't matter, squashing commits is squashing commits.

If rebasing isn't preferable for you, or there are literally thousands of commits that you want to squash and can't be bothered with it, you could just reset softly to the first commit hash and re-commit everything:

$ git reset aabbff $ git commit -m "This commit now contains everything from the tip until aabbff"

You would then only have one commit, the same as rebase -> squash.