4.5.8 · D1Software Engineering

Foundations — Git operations — branch, merge, rebase, cherry-pick, stash, bisect

2,707 words12 min readBack to topic

Before you can read branch, merge, rebase, cherry-pick, stash, bisect, you need the small pile of ideas those words are built on. This page defines every symbol and word the parent note leans on — from absolute zero. Read top to bottom; each block uses only things defined above it. (The word "commit" appears in the summary above, but you are not expected to know it yet — Section 3 builds it precisely once "snapshot" and "SHA" exist.)


1. A "snapshot" — the thing Git actually stores

The picture: imagine your project folder is a table full of LEGO. A snapshot is a full photo of the table. Take a photo, glue one brick, take another photo — you now have two complete photos, not "one photo + one brick".

Why Git needs it: if every point in history is a complete picture, you can jump to any past moment instantly and completely, without "undoing" steps one by one.

Figure 1 — Three complete photos of the LEGO table. The one changed brick is shown in red, but each photo still stores the whole table, not just the change.


2. The hash / SHA — a fingerprint

Git needs a way to name each thing it stores uniquely. It cannot use "photo #1, #2" (two people would clash). Instead it computes a fingerprint of the contents.

Why this tool and not a counter? A content-based fingerprint gives you two superpowers for free:

  • Uniqueness without coordination — no central authority hands out numbers.
  • Tamper-evidence — if any byte changes, the name changes, so history can't be silently edited.

This idea has a name in the vault: see Immutability and content-addressable storage — "content-addressable" literally means the address is computed from the content.


Now that "snapshot" and "SHA" exist, we can finally define the word from the intro.

The picture: each photo has a little card stapled to its back listing who took it, when, a caption, and an arrow pointing to the previous photo. Follow the arrows backwards and you walk the entire history.

How many parents can a commit have?

  • Zero parents — the very first commit in the project (nothing came before it).
  • One parent — an ordinary commit.
  • Two parents — a merge commit joining two lines of work (Section 7).
  • Three or more parents — a rare "octopus" merge joining several branches at once. Git allows any number of parents; two is just the common case.

4. The DAG — the shape of all these arrows together

Snapshots + backward arrows form a specific mathematical shape.

Breaking the name apart:

  • Graph ::: dots joined by lines. Here dots = commits.
  • Directed ::: each line is an arrow (has a from-end and a to-end). Here it always points to the parent.
  • Acyclic ::: "a-" = not, "cyclic" = looping. No commit can be its own ancestor — which makes sense, a snapshot can't come before itself.

Figure 2 — Five commits A–E joined by parent arrows (child → parent). A has no parent (first commit); E has two parents shown in red, making it a merge commit.

Why Git needs the DAG: every operation in the parent note is "walk this graph and place a new node". Merge finds where two paths meet; rebase copies a path onto another spot; bisect searches along a path. The DAG is the board the whole game is played on.


5. Branch — a movable name-tag on a node

The picture: a sticky-note labelled main stuck onto one photo in the chain.

How a branch "moves": when you commit while on a branch, Git makes the new commit's parent = the commit the branch currently points to, then slides the name-tag onto the new commit. The tag walks forward one photo at a time.


6. HEAD — "you are here" (and the detached case)

The picture: a red arrow labelled HEAD stuck onto whichever sticky-note (branch) you're currently working from.

Why Git needs it: when you commit, Git must know which name-tag to advance. HEAD answers that: it points at your current branch, and that branch's tag moves.

Figure 3 — Left: normal HEAD points at the branch feature, which points at a commit. Right: detached HEAD points straight at a commit with no branch attached.


7. Merge base & merge commit — where two paths meet

Once you have branches, two lines of work can grow apart. To rejoin them we need one more idea.

The picture: trace both branches backward along their parent arrows; the first commit they both hit is the merge base — the fork in the road.

Why the merge base matters: to combine two edited files fairly, Git needs to know what they both started from. That common starting point is the merge base — it's the "before" picture the Three-way merge algorithm compares against (see D-page on merging for the full three-way logic). The vault topic Conflict resolution picks up when the two sides changed the same spot differently.


8. Diff / patch — the "difference" between two snapshots

Git stores whole snapshots, but to show or move a change it computes a diff.

The picture: two photos side by side with only the changed bricks circled — the circles are the diff.

Why Git needs it: rebase and cherry-pick work by taking the diff parent(C) → C (what one commit changed) and replaying it somewhere new. The precise algorithm for computing the smallest such diff is Diff and patch (Myers algorithm).


9. Logarithm — why bisect is fast

The parent's bisect section uses . Here is that symbol from zero.

Why this tool for bisect? Bisect uses Binary Search: each "good/bad" test throws away half the suspect commits. The count of halvings needed to shrink candidates down to the single guilty one is exactly . So commits need only about tests, not .

Figure 4 — Each bisect test cuts the suspect set in half: 16 → 8 → 4 → 2 → 1. Reaching the single culprit (red) took 4 tests, which is log₂(16).


10. Working tree, index (staging area), stack

Three last words the parent note uses for stash and committing.

Why "dirty": if your working tree has edits that aren't committed yet, Git calls it dirty. Stash exists to make a dirty tree clean by shelving those edits on the stack.


The prerequisite map

Node names below are spelled out in full plain words (no abbreviations) so the diagram reads on its own; each corresponds to the same-named section above.

Snapshot whole project frozen

SHA fingerprint of the bytes

Immutable no silent edits

Commit snapshot plus metadata

Parent pointers link history

DAG commits and arrows

Branch movable name tag

HEAD you are here or detached

Merge base common ancestor

Merge combine two lines

Diff change recipe

Rebase and cherry pick replay diffs

Logarithm halving count

Bisect binary search

Git operations topic

Related deeper dives and context: Trunk-based vs GitFlow shows how teams choose to branch, and the Hinglish walkthrough is here → 4.5.08 Git operations — branch, merge, rebase, cherry-pick, stash, bisect (Hinglish). This foundations page feeds directly into the parent topic.


Equipment checklist

Cover the right side and answer out loud before moving to the operations page.

What is a snapshot in Git?
A complete frozen photo of all your files at one moment — not the changes.
What is a SHA, and for a commit what exactly is hashed?
A 40-char content fingerprint; for a commit it hashes the whole commit object — tree pointer, parent SHA(s), author, committer, timestamp and message — so any change to any of those gives a new SHA.
Why can't you truly "edit" an old commit?
Its name is built from all its bytes, so any change makes a brand-new commit with a new SHA — the old one is immutable.
How many parents can a commit have?
Zero (first commit), one (ordinary), two (normal merge), or three-plus (octopus merge) — Git allows any number.
Which way does a commit's parent pointer face, and why?
Backwards (child → parent), because the past is frozen and safe to point at; forward pointers would force editing old commits.
Spell out D-A-G.
Directed (arrows have a direction), Acyclic (no loops back to yourself), Graph (nodes joined by lines).
What exactly is a branch?
A tiny file — a name-tag pointing at one commit's SHA. Making one costs ~41 bytes.
What are the two things HEAD can point at?
Normally a branch (which points at a commit); or, when detached, directly at a commit SHA with no branch attached.
Why is a detached HEAD risky?
New commits there have no name-tag pointing at them, so they're easy to lose once you switch away — make a branch to keep them.
What is the merge base of two branches?
Their most recent common ancestor — the last commit both shared before splitting.
What is a diff/patch?
The recipe of +/- line edits turning one snapshot into another; a reusable saved one is a patch.
In , what is , and what does the whole thing count?
= the number of suspect commits; = the number of halvings to shrink them to 1, which is why bisect needs about tests.
Working tree vs index vs stack?
Working tree = live editable files; index = staged snapshot being prepared; stack = last-in-first-out pile used by stash.
Recall Self-test: is the naming really content-based?

If two commits wrap byte-for-byte identical trees but have different commit messages, will their SHAs match? ::: No — a commit's SHA hashes the whole object including the message, so different messages give different SHAs even with identical files.