> ## Content Index
> Fetch the complete content index at: https://www.jonathancreamer.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# rebase is dead long live the squabaserge
- URL: https://www.jonathancreamer.com/rebase-is-dead-long-live-the-squabaserge/
- Published: 2025-08-21T14:42:14.000Z
- Updated: 2025-08-21T14:42:14.000Z
- Description: Git commit history is another form of documentation and it should be treated as such! It's such a useful tool as a developer to understand the history of how and why you're codebase changed. Use git rebase for a cleaner git history.
- Author: Jonathan Creamer
- Tags: git, protip, vscode, terminal

Alongside tabs vs spaces, tailwind vs vanilla css, emacs vs vim, pepsi vs coke, xbox vs playstation, the age old debate of git rebase vs git merge continues to rage on. It's still one of [Whiskey, Web, and What Not's](https://whiskey.fm/?ref=jonathancreamer.com) 🥃Hot Take questions...

Let me start by saying, git rebase is an oft misunderstood construct of git. It's complicated, hard to understand, and can be a cause for confusion. However, it has so many benefits over just merging things.

Git commit history is another form of documentation and it should be treated as such! It's such a useful tool as a developer to understand the history of how and why you're codebase changed.

## No holy wars here

Instead of getting deeper into a holy war, let's just talk about how `git rebase` when used correctly, can really be so much nicer than just `git merge` all the time.

First of all, I'm not saying that you should never **ever** merge stuff. Far from it.

If you're a user working on a feature, you'll often have a flow where you work off of your `main` branch.

%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'mainBranchOrder': '3' }} }%%
gitGraph
    commit id:"A"
    commit id:"B"
    branch my-new-feature
    checkout my-new-feature
    commit id:"C1"
    commit id:"C2"
    checkout main
    commit id:"D"
    checkout my-new-feature
    merge main
    checkout main
    merge my-new-feature id:"merge commit"
    commit id:"F"
    commit id:"G"

Here you have a developer which created a `my-new-feature` branch, and while they were working, there were other commits introduced into `main`. This means that the developer now has a choice.

![](https://storage.ghost.io/c/42/63/4263df8f-a33f-403d-aa31-ba113a54d1b7/content/images/2025/08/image.png)

rebase vs merge pressure

A lot of developers fear the rebase because of the complexity of possible git conflicts, and the idea that they're re-writing history.

And to be fair it is a total PITA when you do rebase your branch, you have multiple commits in your branch history and you do happen to have a git conflict (which can happen in a merge scenario too BTW).

What we propose here today is... 

## squabaserge

The "squabaserge" is a combination of 2 git commands.

- git rebase -i :commmitId:
- git merge

The squash part gives you as the developer the opportunity to clean up the git history of your own branch, *before* you do the rebase. This allows you to remove extraneous git commits, or too many git commits that might make resolving git conflicts tedious.

Look at the git history for your branch with `git log --oneline` pick the commit *before* you started your branch, grab it's ID, and do `git rebase -i :commit:`

This will pop open a VIM window... don't forget how to save/exit with vim `:wq`

![](https://storage.ghost.io/c/42/63/4263df8f-a33f-403d-aa31-ba113a54d1b7/content/images/2025/08/image-2.png)

You simply replace the `pick` with `squash` on all the commits you want, leaving behind just one commit with `pick`.

![](https://storage.ghost.io/c/42/63/4263df8f-a33f-403d-aa31-ba113a54d1b7/content/images/2025/08/image-5.png)

Now you can edit your commit messages since you'll only have one commit.

![](https://storage.ghost.io/c/42/63/4263df8f-a33f-403d-aa31-ba113a54d1b7/content/images/2025/08/image-6.png)

![](https://storage.ghost.io/c/42/63/4263df8f-a33f-403d-aa31-ba113a54d1b7/content/images/2025/08/image-7.png)

Or a cool VSCode #protip is you can do everything we just did in VIM above, which is even cooler if you have Git Lens installed. You can do is set your 

`EDITOR=vscode --wait` 

environment variable to open it in VSCode.

![](https://storage.ghost.io/c/42/63/4263df8f-a33f-403d-aa31-ba113a54d1b7/content/images/2025/08/image-4.png)

Once the rebase is complete, you now have your branch behind `D` , you have a nice clean git history in front of your shiny clean branch with just `C1`.

%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'mainBranchOrder': '3' }} }%%
gitGraph
    commit id: "A"
    commit id: "B"
    branch feature
    commit id: "C1"
    commit id: "C2"
    checkout main
    commit id: "D"
    %% Rebased history
    branch feature-rebased
    commit id: "C1'"
    checkout main
    merge feature-rebased tag: "after rebase"

Now when you merge your branch with `main` you'll have just the single merge commit into `main`, and won't have all those merge commits in your git history.

Many teams in the world enforce squashing when merging into `main` anyways, so by making use of the `squabaserge`, you're actually doing yourself a favor because you'll have an opportunity to clean up the git commit history of your branch prior to that squash happening. 

## Conclusion

Instead of just `git merge` all the time to get this history of `main` into your branch, especially right when your feature is ready to get put into `main`, opt for the *slightly slower*, but totally worth it flow of the `squabaserge`.

**Before**

%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'mainBranchOrder': '3' }} }%%
gitGraph
    commit id:"A"
    commit id:"B"
    branch my-new-feature
    checkout my-new-feature
    commit id:"C1"
    commit id:"C2"
    checkout main
    commit id:"D"
    checkout my-new-feature
    merge main
    checkout main
    merge my-new-feature id:"merge commit"
    commit id:"F"
    commit id:"G"

**After**

%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'mainBranchOrder': '3' }} }%%
gitGraph
    commit id: "A"
    commit id: "B"
    commit id: "D"
    %% Rebased history
    branch my-new-feature
    checkout my-new-feature
    commit id: "C1'"
    checkout main
    merge my-new-feature tag: "after rebase"