Status: RFC · Early Implementation
squash-tree is a Git extension that preserves, visualizes, and reverses squash commits by maintaining an explicit logical squash graph alongside Git’s native commit DAG.
Git intentionally discards history during squash operations.
squash-tree makes that history explicit, inspectable, and reversible — without modifying Git itself.
Git squash workflows (merge --squash, interactive rebase, GitHub squash merges) permanently collapse commit history.
Once a squash is created:
- The original commit structure is lost
- There is no way to inspect how a commit was composed
- Reverting or “unsquashing” is impossible without external context
- Auditability and debuggability suffer
This is not a bug in Git — it is a design choice.
squash-tree does not try to change Git’s behavior.
Instead, it records squash relationships explicitly using Git-native mechanisms.
Git maintains a commit DAG that represents code history.
squash-tree introduces a parallel logical graph that represents composition history:
- Git DAG → what code exists
- Squash Tree → how that code was composed
This separation allows squash history to be:
- preserved
- inspected
- traversed
- reversed
without rewriting Git internals.
- Git remains the source of truth for code
- Squash relationships are explicit, never inferred
- All metadata is opt-in and Git-native
- No heuristics, no magic
- Safety over convenience
squash-tree uses two existing Git mechanisms:
-
Git notes (with a dedicated namespace)
Used to attach structured squash metadata to commits. -
Hidden Git refs
Used to preserve original commits and prevent garbage collection.
Together, these allow the construction of a recursive squash tree where:
- a squash commit is a logical parent
- its original commits are logical children
- children may themselves be squash commits
- Defines a formal Squash Tree specification
- Stores squash relationships explicitly
- Visualizes squash trees
- Enables safe, non-destructive unsquash operations
- Works across clones and platforms
- Reconstruct historical squashes without prior metadata
- Modify Git’s internal object model
- Automatically rewrite published history
- Infer squash structure from diffs or reflogs
If metadata was not recorded at squash time, it cannot be recovered later.
This repository is in early RFC / design-first stage.
Current focus:
- locking the data model
- documenting invariants
- building a minimal, correct foundation
Features will be implemented incrementally once the design is stable.
cmd/
squash-tree/ # CLI entrypoint
docs/
design.md # Architecture & rationale
spec.md # Formal Squash Tree specification
The intended CLI shape (subject to change):
git squash-tree inspect <commit>
git squash-tree tree <commit>
git squash-tree unsquash <commit>No commands are considered stable yet.
This project is design-driven.
Before proposing features or code changes:
- read
docs/design.md - read
docs/spec.md
Guiding rule:
Correctness and explicitness are more important than convenience.
Spec changes require discussion.
Git chose simplicity and performance over historical preservation.
squash-tree exists to restore visibility and control — without fighting Git.