Git Internals
Git Commit Graph and History Shape
Understand why Git history is fundamentally a graph rather than a simple timeline, and how merge and rebase reshape that graph.
The short version
Git stores a commit graph. A linear log is just one way of reading that graph, not the only shape Git actually keeps underneath.
1. Why a graph is a better model than a list
If history is treated as only a list, it becomes hard to explain:
- why merge commits can have two parents
- why rebase produces new commit IDs
- how the same logical change sequence can be expressed with different structure
The graph model makes those behaviors natural.
2. How ordinary commits look linear
Most commits have a single parent, so a local stretch of history often looks like:
A -> B -> C -> D
That does not mean Git is fundamentally list-based. It only means this part of the graph happens to read like a line.
3. What a merge commit records
A merge commit usually has two parents. It says:
- two development lines existed
- they join at this point
So merge is not only about combining file content. It is also about preserving the historical fact that parallel work converged here.
4. Why rebase feels more linear
Rebase does not edit old commits in place. Instead it:
- takes the changes represented by a series of commits
- places them on top of a new base
- creates a new set of commit objects
That makes the graph read more linearly, but through new commit identities.
5. The real difference between merge and rebase
Both can integrate work. The difference is mainly in history expression.
merge
- preserves branching and join points
- is often more faithful to the collaboration path
- is usually safer on already-shared history
rebase
- rewrites a series of commits onto a new base
- produces a cleaner linear reading
- is best for local or not-yet-shared cleanup
6. Why commit IDs change with graph shape
A commit object stores parent information. If the parent changes, the commit object changes. If the object changes, the ID changes.
That is the internal reason rebase is a history rewrite.
7. How the graph model helps with risk judgment
Once you think in graphs, it becomes easier to judge:
- whether a merge commit is a meaningful join point
- whether a branch only contains a short local-only tail
- whether reset or force push might remove a path other people still rely on
8. Re-reading common commands through the graph
git log --graph
It does not invent the graph. It reveals parent relationships that already exist.
git merge
It often adds a node with multiple parents.
git rebase
It recreates equivalent changes on a different parent chain.
git cherry-pick
It copies the effect of a commit into a new node elsewhere in the graph.
The practical takeaway
If you care about preserving the real branching story, merge is often clearer. If you care about polishing your own unpublished series before integration, rebase is often cleaner. The graph model explains both without turning either one into magic.
Understand the difference between `main` and `origin/main` so fetch, pull, push, and branch sync become easier to reason about.
NextGit Packfiles and Object StorageLearn how Git uses packfiles, compression, and object reuse to store and transfer history efficiently instead of copying full project snapshots every time.