Intuition The one idea behind all of Git
A Git repository is a Directed Acyclic Graph (DAG) of commits . Each commit is an immutable snapshot that points back to its parent(s). Everything you do — branching, merging, rebasing — is just creating new commits and moving pointers . Nothing is "lost"; you only move labels around the graph.
WHY this matters: once you see commits as nodes and branches as sticky-notes pointing at nodes, every "scary" command becomes obvious.
Commit ::: an immutable snapshot of the whole tree + metadata (author, message, parent SHA(s)).
Branch ::: a movable pointer (a 41-byte file) to a commit. Creating one is O(1).
HEAD ::: a pointer to where you currently are — usually to a branch.
Working tree / staging area (index) ::: your editable files / the snapshot being prepared for the next commit.
Intuition WHY branches are cheap
A branch is literally a file in .git/refs/heads/ containing a SHA. Making a branch = writing 41 bytes. That is the whole secret to why Git encourages branching madly.
A branch is a named, movable pointer to a commit; new commits made "on" it advance the pointer forward.
HOW (commands):
git branch feature # create pointer, stay on current branch
git switch feature # move HEAD to feature (old: git checkout feature)
git switch -c feature # create + switch in one go
Intuition WHAT "current branch" means
When you commit, Git: (1) writes the snapshot, (2) sets its parent = current commit, (3) updates the branch pointer HEAD points to to the new commit. That third step is why your branch "advances".
Merging combines two branches by creating a new merge commit that has two parents , preserving both histories.
Fast-forward (FF): if the target branch is a direct ancestor , Git just slides the pointer forward — no new commit needed. WHY: there's no divergence to reconcile.
Three-way merge: branches diverged. Git finds the merge base (common ancestor) and combines base → ours and base → theirs.
Worked example Merge with conflict
git switch main
git merge feature
# CONFLICT in app.js
Why this step? main and feature both edited line 10 since their last common ancestor → falls in the CONFLICT case above.
Fix: edit the <<<<<<< ======= >>>>>>> markers, then git add app.js && git commit.
Rebasing takes your commits, finds their merge base with a target, and re-applies each as a brand-new commit on top of the target tip — producing a linear history .
Intuition WHY rebase ≠ merge
Merge records that two lines came together (extra merge commit, true history). Rebase rewrites your commits to pretend you started from the latest base (clean, linear, but new SHAs ).
Golden rule: never rebase commits you have already pushed/shared — you'd rewrite history others depend on.
HOW it works internally (derivation):
git switch feature
git rebase main
Find merge base M M M of feature and main.
Save the diffs of each feature commit C 1 , … , C n C_1,\dots,C_n C 1 , … , C n after M M M .
Move feature to main's tip.
Re-apply each diff in order, creating new commits C 1 ′ , … , C n ′ C_1',\dots,C_n' C 1 ′ , … , C n ′ .
Worked example Interactive rebase (squash 3 commits → 1)
git rebase -i HEAD~3
# mark commits 2 and 3 as 'squash'
Why this step? HEAD~3 is the base; the editor lets you reorder/squash/drop. Result is fewer, cleaner commits.
Cherry-picking re-applies the diff of a single commit onto your current branch as a new commit (new SHA).
You want one fix from another branch without merging everything. It computes parent(C) → C as a patch and applies it where you stand.
git switch main
git cherry-pick a1b2c3d
Why this step? takes the change introduced by a1b2c3d and lands it on main. If the surrounding code differs → conflict, resolve like a merge.
Stashing saves your dirty working tree + index onto a stack and reverts you to a clean HEAD, so you can switch context.
Git refuses to switch branches if changes would be overwritten. Stash = temporary commit you can pop back later.
git stash # shelve changes
git switch hotfix # now clean, can switch
...fix...
git switch feature
git stash pop # reapply + drop from stack
Why this step? pop = apply + remove from stack; use git stash apply to keep it on the stack.
Bisect performs a binary search over commit history to find the first commit that introduced a bug, using "good/bad" answers.
git bisect start
git bisect bad # current is broken
git bisect good v1.0 # this old tag worked
# Git checks out a midpoint; you test & say:
git bisect good (or) git bisect bad
# repeat ~log2(N) times
git bisect reset # back to where you started
Why this step : each answer eliminates half the commits → pinpoints the culprit in logarithmic time.
Common mistake "Merge and rebase do the same thing, so I'll rebase shared branches."
Why it feels right: both integrate main into your work and end with up-to-date code.
Why it's wrong: rebase rewrites SHAs . Teammates who based work on your old commits now have orphaned history → painful conflicts.
Fix: rebase only local, unpushed branches; use merge for shared/public branches.
Common mistake "Cherry-pick is the same as merge for one commit."
Why it feels right: both bring a change over.
Why it's wrong: cherry-pick duplicates the change as a new commit. If you later merge that branch, the same change exists twice → possible conflicts.
Fix: prefer merge/rebase for integration; use cherry-pick only for isolated hot-fixes.
git stash pop always restores everything."
Why it feels right: it usually does.
Why it's wrong: if reapplying conflicts, pop keeps the stash entry (good!) but leaves conflict markers; people then git stash drop and lose work.
Fix: resolve conflicts first; the stash auto-drops only on a clean pop.
Common mistake "Fast-forward merge creates a merge commit."
Why it feels right: "merge" sounds like it always makes a commit.
Why it's wrong: FF just moves the pointer — no new commit. Use git merge --no-ff if you want the merge commit recorded.
Recall Feynman: explain to a 12-year-old
Imagine your project history is a chain of LEGO photos. A branch is a sticky-note labeling one photo. Committing = taking a new photo and moving your sticky-note to it. Merge = gluing two chains together with a special "we joined here" photo. Rebase = peeling off your recent photos and re-taking them on top of the newest chain so it looks like one straight line. Cherry-pick = copying just one cool photo into your album. Stash = putting your half-built LEGO in a box so the table is clean. Bisect = a guessing game: "is the LEGO broken halfway? yes? then the break is in the first half" — keep halving until you find the exact bad brick.
"Big Monkeys Really Crave Sweet Bananas" → B ranch, M erge, R ebase, C herry-pick, S tash, B isect.
And for the golden rule: "Rebase Local, Merge Shared."
Recall Active recall — close the note and answer
What two things does a commit always point to? (snapshot + parent SHA)
When does a merge produce NO new commit?
One reason never to rebase a pushed branch?
How many tests does bisect need for 1024 commits?
What is a Git branch, physically? A movable pointer (small file in .git/refs/heads/) containing the SHA of a commit.
What does HEAD point to? Your current location — usually a branch (which in turn points to a commit).
When does Git do a fast-forward merge? When the target branch is a direct ancestor of the source, so it just slides the pointer forward with no merge commit.
How many parents does a (three-way) merge commit have? Two.
What is the merge base? The most recent common ancestor of the two branches being merged.
When exactly does a merge conflict occur (per region)? When both sides changed the same region differently relative to the base (
O ≠ B O\neq B O = B ,
T ≠ B T\neq B T = B ,
O ≠ T O\neq T O = T ).
What does rebase do to commit SHAs? It creates brand-new commits with new SHAs (history is rewritten).
State the golden rule of rebasing. Never rebase commits that have already been pushed/shared.
Difference between merge and rebase outcome? Merge records a merge commit (true, branched history); rebase produces a linear history of replayed commits.
What does cherry-pick apply? The diff of a single commit (parent→commit) re-applied as a new commit on the current branch.
Risk of cherry-picking then merging the same branch? The change appears twice (duplicate commits) → potential conflicts.
What does git stash do? Saves dirty working tree + index to a stack and reverts to a clean HEAD.
Difference between stash pop and stash apply? pop = apply then remove from stack; apply leaves the entry on the stack.
What algorithm does git bisect use? Binary search over commit history.
How many tests does bisect need for N commits? About ⌈log₂ N⌉.
Command to abandon a bisect session? git bisect reset.
How do you force a merge commit even when FF is possible? git merge --no-ff.
Directed Acyclic Graph — the underlying data structure of commit history
Binary Search — the engine inside git bisect
Three-way merge algorithm
Trunk-based vs GitFlow — workflows built on these operations
Conflict resolution and Diff and patch (Myers algorithm)
Immutability and content-addressable storage — why commits have SHAs
advanced by new commit on
Intuition Hinglish mein samjho
Dekho, Git ko samajhne ka sabse aasaan tareeka: socho ki tumhari poori project history ek chain of photos (commits) hai, aur har photo apne pichle photo (parent) ko point karta hai. Ek branch sirf ek sticky-note hai jo kisi ek photo pe laga hai — isliye branch banana O(1) hota hai, bas 41 bytes likhna. Jab tum commit karte ho, to naya photo banta hai aur tumhara sticky-note aage khisak jaata hai.
Merge ka matlab hai do chains ko jodna ek special "yahan mile the" photo (merge commit, do parents) ke saath. Agar koi divergence nahi hai to Git sirf pointer aage slide kar deta hai — isko fast-forward kehte hain, koi naya commit nahi banta. Rebase thoda alag hai: ye tumhare recent commits ko utha ke latest base ke upar dobara apply karta hai, history seedhi (linear) dikhne lagti hai — lekin SHA badal jaate hain. Isliye Golden Rule yaad rakho: jo commit push ho chuka hai use kabhi rebase mat karo , warna teammates ki history toot jaayegi.
Cherry-pick ka use tab karo jab kisi dusri branch ka sirf ek hi fix chahiye — wo us ek commit ka diff utha ke yahan naya commit bana deta hai. Stash tumhara aadha kaam ek box mein rakh deta hai taaki table saaf ho jaaye aur tum branch switch kar sako, baad mein stash pop se wapas le aao. Aur bisect ek guessing game hai — "good" aur "bad" commit batao, Git beech wala check karta hai, har baar aadha hissa kaat deta hai, to 1000 commits mein bhi sirf ~10 tests mein bug pakad leta hai (binary search, log 2 N \log_2 N log 2 N ). Bas yahi 6 cheezein roz ke development mein 80% kaam cover karti hain.