Lesson 30 of 30
The capstone: a real tangled branch — 15 WIP commits, a wrong-branch merge, and a leaked secret — fixed with the exact tools this track spent 29 lessons building.
20 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
This topic is about judgment and practical tradeoffs more than a single right answer — a mock interview is the better way to test yourself on it.
Be interviewed on this →Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
This is the lesson that doesn't teach a new command. It's the scenario every previous lesson in this track was preparing you for: you inherit a branch that's a genuine mess, and you have to actually untangle it, not just know the definitions of the tools involved.
Here's the situation. feature/pricing-engine has been open for two weeks. It has:
wip, fix, actually fix, debug logging, remove debug logging, repeated four more times.main in the wrong direction two commits back — someone ran git merge feature/pricing-engine while on main locally, then pushed main, so main now contains half-finished pricing logic it was never supposed to have.Three different problems, three different tools from this track — and the order you fix them in matters.
First, clean up the noise, locally, before touching anything shared. Fifteen WIP commits become a handful of real ones with an interactive rebase:
git checkout feature/pricing-engine
git rebase -i HEAD~15
pick a1b2c3d wip
squash e4f5g6h fix
squash h7i8j9k actually fix
squash k0l1m2n debug logging
squash n3o4p5q remove debug logging
pick r6s7t8u add tiered pricing calc
squash u9v0w1x wip pricing edge cases
...
Squash the noise into commits that describe what actually changed. This is a local rewrite so far — nothing shared is broken yet.
Second, undo the wrong-direction merge on main — with the reflog, since it's already pushed. git revert of a merge commit is the clean forward-fix (it doesn't rewrite history other people may have already pulled), but if you need to confirm exactly what main looked like before the merge landed:
git reflog main
a71e0bb main@{0}: merge feature/pricing-engine: Merge made by the 'ort' strategy.
9f2a1c4 main@{1}: commit: chore: bump deps
main@{1} is main's exact position before the bad merge. Since this is already pushed and possibly pulled by others, the safe fix is git revert -m 1 a71e0bb — a new commit that undoes the merge's changes — not a hard reset that would force everyone to reconcile diverged history. The reflog's job here isn't to fix it directly, it's to prove precisely what needs undoing.
Third — and this is the one people get wrong — the secret needs two separate actions, not one. Removing it from the current file with git rm --cached config/secrets.env (paired with adding it to .gitignore) only stops it from being tracked going forward; the key is still readable in every commit before that removal, by anyone who runs git log -p or clones the repo. Actually erasing it from history means rewriting every commit after the one that introduced it — git filter-repo (the modern, maintained tool for this; git filter-branch is the deprecated built-in equivalent) rewrites the whole affected range, changing every commit hash from that point forward.
git filter-repo --path config/secrets.env --invert-paths
This is a genuine history rewrite — same blast radius as any force-push scenario: every collaborator's existing clone now has a diverged, incompatible history and needs to re-clone or hard-reset to the new one.
git rm --cached alone is a trap people mistake for "fixed." It stops future tracking but leaves the secret fully readable in git log -p and every existing clone — the most common actual mistake in a leaked-secret incident is stopping at this step.Interactive rebase for cleanup, the reflog as a safety net and source of truth, remotes and force-push mechanics for coordinating a rewrite, .gitignore and tracked-file hygiene for the leak itself — none of these tools exist in isolation. A messy real branch is where they all get used together, which is exactly why this is the last lesson in the track.