Version Control
Branching, history, and the commands worth understanding before you run them.
Questions
Easy / Med / Hard
Your accuracy
Git is the tool every software engineer touches daily and the one most people learn only as far as they must.
Branching strategies. Trunk-based development keeps everyone committing to one branch, many times a day, behind feature flags where needed. Integration pain stays small because it happens constantly. Feature branching isolates work until it is finished, which feels safer and produces exactly the large, painful merges the isolation was meant to avoid. GitFlow adds release and hotfix branches on top; it suits versioned software you ship on a schedule and is heavy for continuous delivery.
Merge versus rebase. A merge commit preserves what actually happened, including the fact that two lines of work existed in parallel. Rebase replays your commits on top of the target branch, producing a linear history that reads as though you worked sequentially. Rebase makes history easier to read and rewrites commit hashes, which is why the rule is: rebase your own unpushed work, never rebase what others have pulled.
The one that bites. Force-pushing a shared branch rewrites history other people have based work on. If you must, --force-with-lease refuses when someone else has pushed since you last fetched, which turns silent data loss into an error.
Commands worth knowing properly. git bisect binary-searches history for the commit that introduced a bug — roughly seven checkouts for a hundred commits. git cherry-pick copies one commit onto another branch. git reflog records where HEAD has been, and is how you recover work you thought a bad reset destroyed.
Squashing collapses a messy branch into one commit at merge time. It keeps the main history readable and discards the detail of how you got there, which is usually the right trade for a feature branch and the wrong one for a long-lived refactor.