Handling committed secrets (rotate first, then rewrite), Git hooks in teams, getting an old version of a file without losing work, tracking others' changes correctly, a complicated multi-file conflict, tags and releases, a teammate breaking the build, detached HEAD, feature toggles vs branches, and sharing work without merging.
Published September 25, 2026
Several widely shared answers to these questions are wrong in ways that cause real damage: rewriting history before rotating a leaked secret, a git log command that shows the opposite of what's claimed, "feature toggles with branches". Give the correct version, and briefly say why.
Short answer: In this order:
.gitignore.git filter-repo or the BFG Repo-Cleaner (git filter-branch is deprecated), then force-push, coordinate with the team to re-clone, and ask the hosting provider to purge cached views.Common trap: starting with "rewrite history and force-push". History rewriting doesn't un-leak a secret. Rotation is the actual fix.
Short answer: Hooks are scripts that Git runs at points in its workflow:
pre-commit (format, lint, scan for secrets), commit-msg (enforce message conventions), pre-push (run fast tests).pre-receive, update (reject pushes that break policy).They catch problems before they reach review or CI.
Key points to cover:
.git/hooks, and aren't shared automatically. Distribute them with tools such as pre-commit (the framework), Husky, or core.hooksPath pointing to a versioned folder.--no-verify), so enforce the important rules in CI, and in server-side branch protection too.Short answer: View or extract the old version, without touching your working copy:
git show <commit>:src/main/java/com/shop/Pricing.java > /tmp/Pricing.old.java # a copy to compare
git diff <commit> -- src/main/java/com/shop/Pricing.java # what changed since then
git restore --source=<commit> --worktree -- Pricing.java # replace the file… only after committing/stashing your work
git worktree add ../shop-old <commit> # a separate checkout of the whole old tree
Key points to cover:
git stash, then check out the old file, then git stash pop (the common answer) usually leads to conflicts or confusion. Extracting the file to a separate path is simpler.Short answer: Fetch first, then compare your branch with the remote:
git fetch --all --prune
git log --oneline HEAD..origin/main # commits on the remote that you don't have yet
git log --oneline origin/main..HEAD # your commits that the remote doesn't have
git diff HEAD...origin/main # changes on main since your branch diverged
git log --since="1 week" --author="Asha" -- src/payments/ # who changed what, where
Common trap: git log --branches --not --remotes shows your local commits that haven't been pushed, which is the opposite of "changes made by others".
Key points to cover:
Short answer (a model story): "Two teams refactored the pricing module in parallel. One renamed classes and moved packages, while the other changed the discount logic, which produced conflicts in 14 files. I first merged the structural rename on its own, so Git could track the moves, then re-applied the logic change. Where I was unsure, I used a three-way merge tool with zdiff3, resolved it with both authors on a call, and ran the full test suite plus contract tests before merging. Afterwards we agreed to do cross-cutting refactors in small, quickly merged PRs."
Key points to cover:
Short answer: Tags mark release points. Use annotated tags for releases: they record the tagger, date and message, and can be signed. Lightweight tags are just pointers.
git tag -a v2.3.0 -m "Release 2.3.0" <commit> # annotated (add -s to GPG-sign)
git push origin v2.3.0 # push one tag (or: git push --follow-tags)
git tag -d v2.3.0-rc1 && git push origin :refs/tags/v2.3.0-rc1 # delete locally and remotely
Key points to cover:
git push --tags pushes every local tag, including experimental ones. Push specific tags, or use --follow-tags.Short answer:
git revert the offending commit on main (never force-push main).git bisect, if it isn't clear which commit did it.Short answer: HEAD normally points to a branch, which points to a commit. In a detached HEAD state, HEAD points directly to a commit. It happens when you check out a commit hash, a tag or a remote-tracking ref (git checkout v2.3.0, git checkout origin/main), and during rebases and bisects. You can look around and commit, but new commits belong to no branch, and become unreachable once you switch away. They're recoverable from the reflog for a while.
git switch -c hotfix/v2.3.1 # keep work done in detached HEAD by creating a branch here
Short answer: Feature toggles (flags) exist precisely so you don't need long-lived feature branches. You merge incomplete features into main continuously, hidden behind a runtime flag, and release them by switching the flag on, which is independent of deploying. Git's role is trunk-based development: small, frequent merges. The flag system (configuration, or a feature-flag service) controls exposure: per environment, per user or by percentage.
if (featureFlags.isEnabled("new-checkout", user)) {
return newCheckout.place(cart);
}
return legacyCheckout.place(cart);
Common trap: "create a branch for the feature and merge it when it's ready". That's the long-lived-branch workflow feature toggles are designed to replace.
Key points to cover:
Short answer: Push the branch, and have them check it out:
git push -u origin feature/export-v2
# teammate:
git fetch origin
git switch feature/export-v2 # creates a local tracking branch
Other options:
git format-patch / git am, or git bundle, for offline or air-gapped sharing.Key points to cover:
pull --rebase and avoid force-pushing shared branches.Q: What's the difference between git revert and git reset?
A: revert adds a new commit that undoes an old one, which is safe on shared branches. reset moves the branch pointer back, rewriting history, so use it only for unpublished commits.
Q: What's the difference between a merge commit and a fast-forward? A: If the target branch hasn't moved since you branched, Git just moves its pointer forward (a fast-forward), with no new commit. Otherwise it creates a merge commit with two parents.
Q: How do you sign commits, and why?
A: With GPG, SSH or S/MIME keys (git config commit.gpgsign true). Signatures prove the commits came from you. Platforms can require verified signatures on protected branches.
Q: What is a monorepo, and which Git features help at scale?
A: A monorepo holds many projects in one repository. At scale, it relies on partial clone (--filter=blob:none), sparse checkout, git maintenance, the commit-graph, and CODEOWNERS, plus build tools that only rebuild what changed.