Git Branching, History Rewriting and Recovery
AI coding tools can produce a 400-line diff in under a minute. Git is how you review that diff, keep the parts you want, and undo the rest. Interviewers test this directly with questions like: You pushed a bad commit to main. What do you do? This section covers the workflow you will use every day and the recovery moves you need when something goes wrong.
1. The mental model: commits, refs and HEAD
- A commit is an immutable snapshot plus a pointer to its parent(s). Its SHA is its identity.
- A branch is a movable label pointing at one commit. Committing moves the label forward.
- HEAD is the commit you are currently on, usually via a branch.
- Rewriting history (amend, rebase, reset) never edits commits. It creates new commits and moves the labels. The old commits stay in the object database and are reachable through the reflog. By default they are kept for at least 30 days.
The practical rule: anything you committed is recoverable, but uncommitted work is not. Commit early and often, and clean up later.
2. The everyday branching workflow
Use short-lived feature branches cut from main, and merge them back within a day or two.
To keep a branch current while main moves:
Merge vs rebase
| git merge | git rebase | |
|---|---|---|
| What it does | Adds a merge commit joining the two histories | Replays your commits on top of the new base |
| History | True record, but noisy | Linear and easy to read and bisect |
| Rewrites SHAs? | No | Yes |
| Safe on shared branches? | Yes | Only on branches nobody else builds on |
never rewrite history that other people have based work on. Your own unmerged PR branch is fair game. is not.