Beyond Code & Karma · Version Control

Git — The Akashic Repository

How git really works — internals, the DAG, and the philosophy of version control through Chitragupta's cosmic ledger.

Interactive Deep Dive

Git doesn't track diffs.
It stores snapshots.

Git internals surprise most developers: git is not a change tracker. It is a content-addressable object store. Every file version you ever commit exists as an immutable object, addressed by the SHA-1 hash of its contents. The working directory is just a view — the real repository lives in .git/objects/.

The core truth: Git reconstructs diffs on demand by comparing snapshots. A git diff is computed, never stored. Every commit is a complete picture of your entire project at that exact moment.
blob
Raw file contents — no name, no path. The SHA is derived from the bytes alone. Two identical files across any repo share the same blob SHA.
tree
A directory snapshot — a list of blob refs (files) and subtree refs (subdirs). Created at commit time, not at staging.
commit
Wraps a tree ref + parent commit refs + author metadata. Points to the full snapshot. The SHA changes if anything in the tree or parents changes.
tag
A named pointer to a specific commit — with an optional annotation and GPG signature. Lightweight tags are just refs; annotated tags are objects.

Inside .git/ — the object store

Everything Git knows lives in .git/. Delete it and Git is gone — your working files remain, but all history, branches, and refs are lost. Understanding this directory is understanding Git.

Object Contains Created by
blobRaw file contents (no name/path)git add
treeDirectory listing — blob refs + subtree refsgit commit
commitTree ref + parent refs + author + messagegit commit
tagCommit ref + annotation + optional signaturegit tag -a
blob — git cat-file -p
# Every file version is stored as a blob — raw content, nothing more
git cat-file -p a1b2c3d
# Output: the exact bytes of the file at that version
# The SHA is derived from the content itself — Chitragupta's seal
tree — git cat-file -p HEAD^{tree}
# A tree is a directory snapshot — blob refs + subtree refs
git cat-file -p HEAD^{tree}
# 100644 blob a1b2c3d  README.md
# 040000 tree e4f5a6b  src
# Every directory level is its own tree object
commit — git cat-file -p HEAD
# A commit wraps a tree snapshot + metadata
git cat-file -p HEAD
# tree   e4f5a6b7c8d9e0f1
# parent a1b2c3d4e5f6a7b8   ← points to previous karma
# author Deveshwar Jaiswal
# committer Deveshwar Jaiswal
#
# feat: add authentication
# Each commit is a complete snapshot — never a diff
Every commit is a snapshot, not a diff. Git reconstructs diffs on demand by comparing two snapshots. This is why git checkout is instant regardless of history length.
.git/ anatomy
  • objects/ — the content-addressable store (all blobs, trees, commits, tags)
  • refs/heads/ — one file per branch, containing a SHA
  • refs/remotes/ — remote-tracking refs (snapshots of remote branches)
  • HEAD — current branch or detached SHA
  • index — the staging area (binary file)
  • config — repo-level configuration
  • logs/ — reflog: every HEAD movement for 90 days

The DAG — commits as a directed acyclic graph

Every commit points to its parent(s). This forms a Directed Acyclic Graph — the data structure underlying every Git operation. Branches, merges, rebases, and cherry-picks are all just ways of reading, writing, or rearranging nodes in this graph.

HEAD, branches, and detached state
# HEAD is just a text file
cat .git/HEAD
# ref: refs/heads/main   ← attached (normal state)

# A branch is also just a text file — 41 bytes
cat .git/refs/heads/main
# a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0

# Detached HEAD — contains a SHA directly
cat .git/HEAD
# a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0   ← wandering soul
HEAD
A text file containing either a branch name (attached) or a SHA (detached). It always answers: "where are you right now?"
Branch ref
A file in refs/heads/ containing a single SHA. When you commit, the current branch file is updated to the new SHA. That's it.
Remote-tracking ref
A local snapshot of a remote branch at the time of last fetch. origin/main lives in refs/remotes/origin/main.
Detached HEAD — HEAD contains a SHA instead of a branch name. You're present in a specific moment but not on any named path. Commits made here are reachable only from HEAD; leave without creating a branch and they become orphans. The reflog preserves them for 90 days.

The operations — commit to worktree

git commit

Creates an immutable commit object — blob + tree + commit — addressed by SHA. The current branch pointer advances. The SHA is content-derived: same tree + same parent + same message = same SHA, always.

git commit
# Each commit is a karma — permanently sealed by Chitragupta
git add src/auth.ts
git commit -m "feat: add JWT validation"
# [main a1b2c3d] feat: add JWT validation
# SHA is deterministic — same tree + same parent + same message = same SHA

Use: whenever a logical unit of work is complete. Commit early, commit often — history is cheap and rebasing lets you clean it up before sharing.

Avoid: committing broken states to shared branches. On private branches, commit freely and squash/rebase before merging.

git branch

Creates a 41-byte text file — nearly free. A branch is a movable pointer to a commit, nothing more. Deleting a branch deletes only the pointer; the commits remain until garbage collection.

git branch
# A branch is a dharmic path — a parallel reality that costs nothing
git checkout -b feature/auth  # 41 bytes — that's the entire cost
git branch -v
# * feature/auth  a1b2c3d  feat: add JWT validation
#   main          a1b2c3d  feat: add JWT validation

Use: always — one branch per feature, fix, or experiment. Branch names are free.

Avoid: long-lived branches that diverge significantly from main. The longer a branch lives, the harder the eventual merge becomes.

git merge — fast-forward

When main hasn't advanced since the branch was created, Git simply moves the main pointer forward — no merge commit, no new node in the DAG.

fast-forward merge
# Fast-forward — paths that never diverged rejoin cleanly
git checkout main
git merge feature/auth
# Updating a1b2c3d..b2c3d4e
# Fast-forward — no merge commit, no karma clash

Use: the default for short-lived branches that haven't diverged. Produces a clean linear history.

Avoid using --no-ff unless: you explicitly want a merge commit to mark the integration point (useful in release workflows).

git merge — 3-way

When both branches have diverged, Git finds their common ancestor (the merge base) and creates a new commit with two parents. The merge commit preserves full history.

3-way merge
# 3-way merge — two dharmas converge, a new moment is born
git merge feature/auth
# Merge made by the 'ort' strategy.
# The merge commit has two parents — it carries both histories
git log --graph --oneline
# *   m7n8o9p Merge branch 'feature/auth'
# |\
# | * b2c3d4e feat: add JWT validation
# * | c3d4e5f fix: hotfix
# |/
# * a1b2c3d  init

Use: integrating long-lived branches (e.g. release branches) where the divergence history is meaningful.

Avoid: for everyday feature branches where you want a clean linear history — rebase first, then fast-forward merge.

git rebase

Replays your commits on top of a new base. Each commit gets a new SHA — same diff, new parent, new fingerprint. History becomes linear. This is Maya: the perceived history changes, the underlying actions do not.

git rebase
# Maya — the perceived history rewrites, the actions are unchanged
git rebase main
# First, rewinding head to replay your work on top of it...
# Applying: feat: add JWT validation
# New SHA — same diff, new parent, new fingerprint
# The old commit is abandoned (no refs). Reflog preserves it.

Use: to keep feature branches up to date with main, and to produce a clean linear history before merging.

Never rebase: commits that have been pushed to a shared remote. It rewrites SHAs — anyone who based work on the old SHAs will face conflicts.

git cherry-pick

Copies a single commit's diff to the current branch. Creates a new commit with a new SHA — same changes, new moment in the ledger.

git cherry-pick
# Selective karma — one action carried to another path
git cherry-pick a1b2c3d
# [main b2c3d4e] feat: fix critical bug
# Same diff, new SHA — a new moment with the same intention
# The source branch is untouched

Use: to apply a specific bug fix from one branch to another without merging all of that branch's history.

Avoid: cherry-picking the same commit repeatedly across branches — it creates duplicate changes with different SHAs, which causes confusion during eventual merges.

git reset — three modes

Moves HEAD (and the current branch pointer) to a target commit. The three modes control what happens to the index (staging area) and working tree.

reset --soft
# --soft: turn back the clock, keep your preparations
git reset --soft HEAD~1
# HEAD moves back. Changes stay staged. Ready to recommit.
reset --mixed (default)
# --mixed (default): return to before you staged
git reset HEAD~1
# HEAD moves back. Index cleared. Working tree unchanged.
# Your edits remain — just unstaged.
reset --hard
# --hard: pralaya — the dissolution
git reset --hard HEAD~1
# HEAD moves back. Index cleared. Working tree wiped.
# The commits still live in reflog for 90 days — nothing is truly lost.

--soft: undo the last commit, keep changes staged. Good for combining multiple commits into one.

--mixed: undo the last commit, unstage changes. Good for re-staging selectively.

--hard: discard everything back to a known good state. The reflog preserves all commits for 90 days — you can recover.

Never reset public commits (pushed to shared remote). Use git revert instead — it creates a new commit that undoes the change, preserving history.

git stash

Saves the current dirty state (staged + unstaged changes) to a stack and restores the working tree to the last commit. The Samskara of Git — latent impressions stored below the surface.

git stash
# Samskara — latent impressions stored below the surface
git stash push -m "WIP: auth refactor"
# Working tree is clean. The impressions wait.
git stash pop
# The samskara surfaces — changes restored to working tree

Use: when interrupted mid-task and needing to switch context quickly.

Prefer a branch for anything longer than a few minutes — stash entries are easy to forget and don't show up in git log.

git worktree

Multiple working directories, one repository. All worktrees share the same .git/objects/ — the same Chitragupta keeping all ledgers. The Lokas (realms) of your codebase, coexisting simultaneously.

git worktree
# Multiple lokas — realms of the same codebase, existing simultaneously
git worktree add ../hotfix-dir hotfix/critical
# ../hotfix-dir is now checked out to hotfix/critical branch
# Both dirs share .git/objects — same Chitragupta keeps both ledgers
git worktree list
# /path/to/repo       a1b2c3d [main]
# /path/to/hotfix-dir b2c3d4e [hotfix/critical]

Use: when you need to work on a hotfix while keeping a long-running feature branch's working directory intact. Also excellent for running tests on multiple branches simultaneously.

Avoid: checking out the same branch in two worktrees simultaneously — Git prevents this as it would cause index conflicts.

See the DAG move

Step through 8 scenarios — commit flow, branching, merge, rebase, cherry-pick, reset, detached HEAD, and worktrees — and watch the commit graph update in real time.

Open Full Visualizer →

Chitragupta & the Akashic Repository

Hindu Mythology Parallel

Every commit you make is an act recorded by Chitragupta — Yama's scribe who keeps the cosmic ledger of every soul's actions with perfect accuracy, never erasing, never forgetting. Git's object store is the Akashic Record of your codebase: immutable, content-addressed, eternal. Even git reset --hard cannot truly destroy — it only moves the pointer. The commits still exist until garbage collection (the great dissolution, Pralaya) sweeps them away. The git reflog is your personal akashic record — every past HEAD position preserved for 90 days.

And every commit is a karma — an action with consequences that propagate through the DAG. Branches are dharmic paths. Merges are karma resolutions. Rebase is Maya — the history looks different, but the underlying actions are unchanged.

Git concept Deity / Concept Why
Commit log / SHA Chitragupta Yama's scribe — records every action with perfect, immutable accuracy
git init / first commit Brahma The first act of creation — the repository before any commit
git stash / stored refs Vishnu The preserver — holds what exists between active cycles
git reset --hard Shiva The transformer — clears the working state to begin again
Remote / origin Brahman The universal source — local repos are avatars of the remote
Worktree Loka (realm) Multiple concurrent realms of the same codebase
Merge conflict Karma clash Two dharmic paths with contradictory consequences — requires conscious resolution
git reflog Akashic Records Nothing is ever truly lost — every past HEAD position is recoverable
Rebase Maya The perceived history changes; the underlying actions do not
Detached HEAD Wandering soul Present in a moment outside any named path — commits here are lost without a branch

Git Trivia

Linus Torvalds wrote the first working version of Git in 10 days (April 2005), after BitKeeper revoked free access for Linux kernel development.
Git stores objects by content hash — two identical files anywhere in any repo share the exact same SHA object. No duplication, ever.
A Git branch is just a 41-byte text file containing a SHA. Creating a branch is nearly free — git branch writes ~41 bytes to disk.
git rebase rewrites commit SHAs because the parent pointer changes — same diff, different history, different hash. That's why you never rebase public commits.
git reflog retains every HEAD position for 90 days by default. You can recover from almost any reset --hard or detached HEAD incident.
"Git" is British slang for "unpleasant person." Linus named it after himself — his words: "I'm an egotistical bastard, and I name all my projects after myself."