Fundamentals 7 min read

Uncovering Git’s Hidden Mechanics: Index, Stash, Refs, and Merge Secrets

This article explains four often‑misunderstood Git internals—how the index, staging area, and --cached option are the same, how stash creates hidden commits, the variety of reference types beyond branches and tags, and why merge commits are not actually empty—using concrete commands and examples.

Liangxu Linux
Liangxu Linux
Liangxu Linux
Uncovering Git’s Hidden Mechanics: Index, Stash, Refs, and Merge Secrets

Index, Staging Area, and --cached are the Same

When you run git add file.txt and then git status, Git shows the file under “Changes to be committed”. The command adds the file to the object database in .git/objects and updates .git/index, which is the staging area. The three names—index, staging area, and the --cached option—refer to the same .git/index file. You can view the staged changes with git diff --cached or git diff --staged.

Stash Is a Series of Commits

Running git stash creates two commits: one for the index and one for the working‑tree changes. These commits are referenced by refs/stash. You can list them with git log stash --oneline and inspect a specific stash commit with git show <hash>. The stash commits are also recorded in the reflog.

$ git log stash --oneline
6cb983fe (refs/stash) WIP on main: c6ee55ed wip
2ff2c273 index on main: c6ee55ed wip

Not All References Are Branches or Tags

Git references include many kinds besides branches and tags, such as refs/stash, refs/notes/*, refs/pull/123/head (used for GitHub pull‑request refs), and refs/bisect/*. The stash reference is an example of a ref that is neither a branch nor a tag.

$ find .git/refs -type f
.git/refs/heads/main
.git/refs/remotes/origin/HEAD
.git/refs/remotes/origin/main
.git/refs/stash

Merge Commits Are Not Empty

A merge commit records the snapshot of the repository after the merge. In a simple merge of branches x and y, git show on the merge commit appears to have no diff because Git shows only the combined changes. Comparing the merge commit with each parent reveals the actual modifications.

$ git diff 0931e45 96a8afb --stat
 x.txt | 1 +
 1 file changed, 1 insertion(+)

$ git diff 1d8bd2d 96a8afb --stat
 y.txt | 1 +
 1 file changed, 1 insertion(+)

If the merge resolves a conflict, the diff will show the conflict resolution (e.g., replacing x and y with z).

Conclusion

The author plans to continue exploring Git internals and share further insights.

Gitindexrefsstashmerge-commitversion-control
Liangxu Linux
Written by

Liangxu Linux

Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.