Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions blog/_posts/2026-02-04-squash-tree-solution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
layout: post
title: "Squash-tree: Preserve and Inspect Squash History Without Fighting Git"
headline: "Squash-tree: Preserve and Inspect Squash History Without Fighting Git"
modified: 2026-02-04 12:00:00 +0100
description: "A Git extension that preserves references to original commits so you can inspect the squash tree and cherry-pick to recover when squashing goes wrong."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description: "A Git extension that preserves references to original commits so you can inspect the squash tree and cherry-pick to recover when squashing goes wrong."
description: "Preserves the history of the original commits after git squash. Inspect the squash tree and cherry-pick whenever and whatever you want."

tags: [git, squash-tree, version-control, collaboration]
featured_post: false
toc: true
image: post.jpg
author:
name: Yasir Guzmán
github: jasirguzman123
linkedin: yasir-guzman
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's add this image

Image

---

Git squash workflows are widely used to keep main clean. Merge squash, interactive rebase, GitHub squash merge. But once you squash, the original commit structure is gone. You lose the ability to inspect how a commit was composed, recover individual changes, or audit what went into a release. **squash-tree** is a Git extension that preserves squash history alongside Git's native DAG so you can inspect it and recover when you need to.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Git squash workflows are widely used to keep main clean. Merge squash, interactive rebase, GitHub squash merge. But once you squash, the original commit structure is gone. You lose the ability to inspect how a commit was composed, recover individual changes, or audit what went into a release. **squash-tree** is a Git extension that preserves squash history alongside Git's native DAG so you can inspect it and recover when you need to.
The git [squash](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History#_squashing) command is a very powerful and useful tool. It’s widely used to keep branches clean. But once you squash, the original commits are gone. You lose the ability to inspect how a squashed commit has been composed. You are no longer able to cherry-pick the original commits or audit what happened during the rebase. You lose the history.
Although it is possible to recover the original state of the branch before the squash using “reflog”, after some time, it becomes very challenging, if possible at all, as “reflog” is quite messy, and it’s hard to find something in it.
To improve the situation around squash's original commits, we created [squash-tree](https://github.com/widefix/squash-tree). It’s a Git extension that preserves squash history alongside Git’s native history, so you can inspect it and recover original commits when you need to. If you are a big fan of commit squashing and faced the need for the recovery of the original commits, that might be very helpful for you.
This post is an overview of this tool on installation, usage, and main scenarios.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jasirguzman123 I recommend this - https://app.grammarly.com/ - to check grammar and text quality.


## The Problem

Git squash workflows permanently collapse history. Whether you use `merge --squash`, interactive rebase, or a platform squash merge, the result is the same: the original commits vanish from the DAG. After a squash:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

explain what is DAG or add a reference


- The original commit structure is lost
- You cannot inspect how a commit was composed
- Reverting or "unsquashing" is impossible without external context
- Auditability and debuggability suffer

This isn't a bug in Git. It's a design choice. Git favors simplicity and performance over preserving every detail of how history was composed. For many teams, that tradeoff hurts: you squash to keep history tidy, but when something goes wrong (a bad merge, a dropped fix, a need to trace what actually shipped) you have nowhere to look. Squash-tree doesn't try to change Git's behavior. It records squash relationships explicitly so that history stays visible and recoverable.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This isn't a bug in Git. It's a design choice. Git favors simplicity and performance over preserving every detail of how history was composed. For many teams, that tradeoff hurts: you squash to keep history tidy, but when something goes wrong (a bad merge, a dropped fix, a need to trace what actually shipped) you have nowhere to look. Squash-tree doesn't try to change Git's behavior. It records squash relationships explicitly so that history stays visible and recoverable.
This isn't a bug in Git. It's a design choice. Git favors simplicity and performance over preserving every detail of how history was composed. For many teams, that tradeoff hurts: you squash to keep history tidy, but when something goes wrong (a bad merge, a dropped fix, a need to trace what actually shipped), you have nowhere to look. Squash-tree doesn't try to change Git's behavior. It complements it by recording the relationship of squashed commits so that history stays visible and recoverable.

This paragraph is good, but it's not related to the problem. It's more like a solution.

To expand the problem, a demo of commands lead to the problem would look much better.


## The Solution

Squash-tree keeps a *logical squash graph* alongside Git's DAG. You can see how a commit was composed, who contributed what, and cherry-pick the originals if you need to recover. It uses Git notes and hidden refs to record squash relationships explicitly, without changing how Git works.

### Install

```bash
curl -sSL https://raw.githubusercontent.com/widefix/squash-tree/refs/heads/main/scripts/install.sh | bash
```

The script installs the binary, adds it to your PATH (if needed), and configures the Git alias. Run `source ~/.zshrc` or `source ~/.bashrc` (or open a new terminal), then in a repository:

```bash
git squash-tree init # this repo only
git squash-tree init --global # all repos
```

Run `git squash-tree init` and it installs hooks that record metadata whenever you squash locally. Say you have a feature branch with three commits. Let's use `rebase -i` to squash them. In the editor you'll see:

```
pick abc1234 Add login form
squash def5678 Add validation
squash ghi9012 Add tests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, it also works with fixup. So let's add an example and mention that somewhere.

```

Keep `pick` on the first commit and change the rest to `squash`, save and close. With hooks installed, the metadata is recorded automatically. Then run `git squash-tree HEAD` and you'll see:

```
xyz7890 [SQUASH] Add login feature (squashed)
├── abc1234 [LEAF] Add login form
├── def5678 [LEAF] Add validation
└── ghi9012 [LEAF] Add tests
```

`[SQUASH]` means a commit formed by squashing others. `[LEAF]` means an original commit. From here you can cherry-pick any of them to recover. Metadata has to be recorded at squash time. If it wasn't, the structure can't be reconstructed later.
Copy link
Member

@ka8725 ka8725 Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Metadata has to be recorded at squash time. If it wasn't, the structure can't be reconstructed later.

Please elaborate on this - what do you mean by that: which metadata and how can go wrong.


For full setup, CLI options, and edge cases, see the [squash-tree repository](https://github.com/widefix/squash-tree) and its README.

## Conclusion

Git prioritizes simplicity; squash-tree restores **visibility and control** over squash history without fighting Git. The project is in an early RFC / design-first stage, with focus on locking the data model and building a minimal, correct foundation. You can follow the project and contribute feedback on [GitHub](https://github.com/widefix/squash-tree).