/git-squash-range

Squash commits to manage size of GitHub Pages

Primary LanguageRustMIT LicenseMIT

Commit Management for GitHub Pages

When GitHub Pages is served from a dedicated branch (e.g. gh-pages), its history can be rewritten to manage repository size. One way to do this is to simply amend the most recent commit and force push.

git commit --amend
git push --force

The upside is that previous updates no longer contribute to the repository size. The downside is that a bad commit can’t be easily undone.

To have the best of both worlds, a more sophisticated approach can be used. Instead of squashing every change into a single commit, preserve the N most recent commits and only the remaining commits.

The git-squash-range script provided here does exactly this.

squash range.drawio

Algorithm

The history can be divided into two commit ranges:

  • The oldest commits to be squashed: [root, mid]

  • The newest commits to be preserved: (mid, head]

The commit IDs for the root, mid, and head commits are determined as follows:

  • root - git rev-list --max-parents=0 HEAD

  • mid - git rev-parse HEAD~$N where N is the number of commits we want to preserve

  • head - git rev-parse HEAD

The current branch also needs to be recorded:

  • branch - git branch --show-current

The algorithm is then:

  1. Squash the oldest commits

    1. Checkout root

      git checkout $root
    2. Squash merge from mid

      git merge --squash $mid
    3. Amend root with the merge result

      git commit --amend -m squashed
  2. Preserve the newest N commits

    git cherry-pick $mid..$head
  3. Move the branch to the new HEAD

    1. Move the branch

      git branch --force $branch HEAD
    2. Checkout the branch

      git checkout $branch

Development

Run the tests.

rake