Version Control with Git
Scope of this domain
Version Control with Git tests command-level understanding of Git's data model and judgement about history on shared branches: the three trees, branches as pointers, merge versus rebase, undo operations, and collaboration workflows such as trunk-based development versus GitFlow.
Core rules and concepts
- Git stores snapshots, not diffs. A commit points to a tree and to parent commits; a branch is a movable pointer to a commit; HEAD points to the current branch.
- Three trees: working directory, index (staging area), HEAD (last commit).
git diffcompares workdir to index;git diff --stagedcompares index to HEAD. reset --softmoves HEAD only;--mixedalso resets the index;--hardalso overwrites the working directory, risking data loss.revertcreates a new commit that undoes an earlier one and is safe on shared history.resetrewrites history and needs a forced push.- Rebase replays commits onto a new base, producing new SHAs. Good for local cleanup, harmful on branches others have pulled.
--force-with-leaserefuses to overwrite if the remote ref moved since your last fetch..gitignoreaffects only untracked files; already-tracked files needgit rm --cached.reflogrecords local HEAD movements and recovers commits orphaned by reset or rebase.
Worked example
A developer runs git reset --hard HEAD~2 on main after already pushing, losing two commits. Reasoning: locally, git reflog shows the pre-reset SHA and git reset --hard <sha> restores it. But because main was published, the correct remediation is to restore the commits and use git revert of the pushed commits, or re-push with --force-with-lease only if nobody has pulled. Rewriting published history breaks collaborators and CI caches.
Traps that cost marks
- Believing rebase moves commits; it copies them with new SHAs.
- Assuming cherry-pick preserves the original SHA.
- Using reset on a shared branch instead of revert.
- Forgetting that pull equals fetch plus merge or rebase depending on config.
- Deleting a branch with unmerged work without checking reflog.