Git is used by 93% of developers worldwide, yet Stack Overflow's annual survey reveals that "undoing changes" remains one of the most searched Git topics year after year. These tricky questions test the mental model you have of Git, not just your ability to memorize commands. They consistently separate developers who've clicked buttons in VS Code from those who truly understand version control.
Table of Contents
- Reset vs Revert Questions
- Reflog Recovery Questions
- Detached HEAD Questions
- Cherry-Pick Questions
- Git Bisect Questions
- Quick Reference
Reset vs Revert Questions
These questions test your understanding of Git's two primary ways to undo changes.
What is the difference between git reset and git revert?
git reset moves the branch pointer backward, rewriting history by removing commits. git revert creates a new commit that undoes changes from a previous commit without altering history. Use revert for shared branches (safe), reset for local branches only (destructive).
Think of reset as a time machine that rewrites history—the commits literally disappear from the timeline. Think of revert as an "undo" operation that acknowledges the past—it creates new commits that reverse the changes.
# You've made three commits on main that need to be undone
# The commits have already been pushed to origin
git log --oneline
# a1b2c3d Fix payment bug
# e4f5g6h Add logging
# i7j8k9l Update config
# m0n1o2p Previous good stateWrong approach: git reset --hard m0n1o2p followed by git push --force
Right approach: git revert a1b2c3d e4f5g6h i7j8k9l
When you reset on a shared branch and force-push, you're rewriting history that exists on other developers' machines. When they pull, Git gets confused because their local history no longer matches remote. This leads to duplicate commits, lost work, and angry teammates.
git revert is safe because it only adds to history. The bad commits still exist, but new commits undo their changes. Everyone's history stays consistent.
# Safe way to undo the last 3 commits
git revert HEAD~3..HEAD
# Or revert a specific commit
git revert a1b2c3d --no-edit
# Revert a merge commit (specify which parent to keep)
git revert -m 1 <merge-commit-hash>When should you use each type of git reset?
reset --soft moves the branch pointer but keeps changes staged—useful for uncommitting work you want to restructure. reset --mixed (the default) unstages changes but keeps them in your working directory. reset --hard is the nuclear option for completely discarding local experiments.
# Soft reset: uncommit but keep changes staged
git reset --soft HEAD~1
# Mixed reset: uncommit and unstage, but keep changes in working directory
git reset HEAD~1
# Hard reset: completely discard commits and changes
git reset --hard HEAD~1Reflog Recovery Questions
These questions reveal whether you know Git's safety net exists.
How do you recover deleted branches or lost commits?
Use git reflog to find the commit hash of the lost work. The reflog records every time HEAD moves, including checkouts, commits, rebases, resets, and branch deletions. Once you find the hash, create a new branch or cherry-pick specific commits.
Git almost never truly deletes anything. The reflog is your lifeline:
# You accidentally deleted a branch with important work
git branch -D feature-important
# Or you ran a hard reset and lost commits
git reset --hard HEAD~5
# See the reflog to find your lost work
git reflog
# Output shows something like:
# a1b2c3d HEAD@{0}: reset: moving to HEAD~5
# x9y8z7w HEAD@{1}: commit: Add user authentication
# p5q6r7s HEAD@{2}: commit: Fix login bug
# m0n1o2p HEAD@{3}: checkout: moving from main to feature-importantEach entry has a reference like HEAD@{n} that you can use to travel back in time:
# Recover to the state before the reset
git reset --hard HEAD@{1}
# Or create a new branch pointing to the lost commit
git checkout -b recovered-branch x9y8z7w
# Or cherry-pick specific lost commits
git cherry-pick x9y8z7w p5q6r7sThe reflog is local to your machine and entries expire after about 90 days by default. This is why it can save you from local disasters but not from commits that were never on your machine.
What is ORIG_HEAD and how does it help with recovery?
ORIG_HEAD is a reference Git sets automatically before dangerous operations like rebase or reset. Running git reset --hard ORIG_HEAD often recovers from the most recent disaster without needing to search through reflog.
# After a bad rebase
git reset --hard ORIG_HEAD
# ORIG_HEAD points to where HEAD was before the dangerous operationDetached HEAD Questions
These questions reveal whether you understand what HEAD actually is.
What is detached HEAD state and why does it matter?
Detached HEAD occurs when HEAD points directly to a commit hash instead of a branch reference. Any commits made in this state are orphaned when you switch branches—they still exist but no branch points to them. Eventually, Git's garbage collection will delete them.
Understanding this requires knowing what HEAD is. HEAD is normally a symbolic reference—it points to a branch name like refs/heads/main, and that branch points to a commit. When HEAD is "detached," it points directly to a commit hash instead of a branch.
Think of branches as named bookmarks in a book. HEAD is the page you're currently reading. Normally HEAD says "I'm reading the page that the 'main' bookmark points to." In detached HEAD state, HEAD says "I'm reading page 47" with no bookmark involved.
git checkout a1b2c3d
# You are in 'detached HEAD' state...
# You make some commits
git commit -m "Experimental feature"
git commit -m "More experiments"
# Then you checkout main
git checkout main
# Those commits are now orphaned!How do you save work done in detached HEAD state?
Create a branch before switching away. This gives your commits a named reference so they won't be orphaned.
# The fix: create a branch before switching away
git checkout a1b2c3d
git commit -m "Experimental feature"
git checkout -b save-my-experiments # Now it's safe!
git checkout mainDetached HEAD is useful for temporarily exploring old commits or testing something without affecting any branch—just remember to create a branch if you want to keep any commits you make.
Cherry-Pick Questions
These questions test practical Git workflow knowledge.
When should you use git cherry-pick?
Use cherry-pick to apply specific commits from one branch to another without merging the entire branch. It creates a new commit with a different hash—the changes are identical, but Git sees them as separate commits.
# You're on the release-2.0 branch
# A critical bugfix was committed to main
# You need ONLY that bugfix, not other main commits
git log main --oneline
# f1e2d3c Refactor user service (DON'T WANT)
# a4b5c6d Fix critical payment bug (WANT THIS)
# g7h8i9j Add new feature (DON'T WANT)
git checkout release-2.0
git cherry-pick a4b5c6dWhen to use cherry-pick:
- Applying hotfixes to multiple release branches
- Recovering specific commits from an abandoned branch
- Pulling in a single feature without merging an entire branch
When NOT to use cherry-pick:
- As a regular workflow (it duplicates commits)
- When you need many commits (consider merging instead)
- When commits have dependencies on each other
Why should you use the -x flag with cherry-pick?
The -x flag adds a reference to the original commit in the commit message, helping with traceability. This matters because cherry-pick creates a new commit with a different hash—Git might not recognize that the same fix exists on both branches during future merges.
git cherry-pick -x a4b5c6d
# Commit message automatically includes:
# (cherry picked from commit a4b5c6d)
# Cherry-pick a range of commits
git cherry-pick A^..B # Includes A through B
# Cherry-pick without committing (stage changes only)
git cherry-pick -n a4b5c6d
# Handle conflicts during cherry-pick
git cherry-pick a4b5c6d
# ... resolve conflicts ...
git add .
git cherry-pick --continueGit Bisect Questions
These questions separate Git users from Git power users.
What is git bisect and how does it find bugs?
git bisect is a binary search tool that finds the exact commit that introduced a bug. You mark a known good commit and a known bad commit, then Git checks out commits in between for you to test. Finding a bug among 200 commits takes only about 8 steps (log2 of 200).
# Users report that login is broken
# It worked in version 2.0 (commit abc123)
# It's broken in current main (commit xyz789)
# There are 200 commits between them
# Start bisect
git bisect start
# Mark current commit as bad
git bisect bad
# Mark known good commit
git bisect good abc123
# Git checks out a commit in the middle
# Bisecting: 100 revisions left to test
# Test the login functionality, then:
git bisect good # if login works
# or
git bisect bad # if login is broken
# Git narrows down further
# Bisecting: 50 revisions left to test
# Repeat until:
# a4b5c6d is the first bad commitHow do you automate git bisect with a test script?
Use git bisect run with a script that returns 0 for good commits and non-zero for bad commits. Git runs the test automatically at each step and returns the exact commit that introduced the failure.
# If you have a test script that returns 0 for good, non-zero for bad
git bisect start HEAD abc123
git bisect run npm test -- --grep "login"
# Git runs the test automatically at each step
# Returns the exact commit that introduced the failureWhen you're done:
git bisect reset # Returns to original HEADThe logarithmic efficiency is why bisect is invaluable for large repositories. Finding a bug among 1000 commits takes only about 10 steps. Note that bisect only works well when commits are reasonably atomic—if one commit contains 50 unrelated changes, bisect finds the commit but you still have to hunt for the problematic line.
Quick Reference
| Command | Purpose | Safety |
|---|---|---|
git reset --soft | Uncommit, keep staged | Local only |
git reset --mixed | Uncommit, unstage, keep changes | Local only |
git reset --hard | Discard commits and changes | Local only |
git revert | Create undo commit | Safe for shared |
git reflog | View HEAD movement history | Recovery tool |
git cherry-pick | Apply specific commit | Creates new hash |
git cherry-pick -x | Cherry-pick with traceability | Best practice |
git bisect | Binary search for bugs | Read-only search |
ORIG_HEAD | Pre-dangerous-operation state | Recovery tool |
Key mental model: Git is a content-addressed filesystem where commits are identified by SHA-1 hashes. Branches are just pointers to commits. HEAD can point to a branch (normal) or directly to a commit (detached). History can be preserved (revert) or rewritten (reset, rebase). Git almost never deletes anything immediately—reflog and ORIG_HEAD are your safety nets.
Related Articles
- Complete DevOps Engineer Interview Guide - comprehensive preparation guide for DevOps interviews
- Git Rebase vs Merge Interview Guide - When to rebase vs merge and why
- Node.js Advanced Interview Guide - Event loop, streams, and Node.js internals
- CI/CD & GitHub Actions Interview Guide - Workflows, pipelines, and deployment strategies
