Git Advanced¶
15 cards — 🟢 2 easy | 🟡 11 medium | 🔴 2 hard
🟢 Easy (2)¶
1. What do git blame and git annotate do?
Show answer
`git blame`git annotate` is functionally identical (older command, same output format).
Useful flags:
- `git blame -L 10,20 file` -- only lines 10-20
- `git blame -w` -- ignore whitespace changes
- `git blame -M` -- detect lines moved within the file
- `git blame -C` -- detect lines copied from other files
- `git blame --since=2w` -- only show changes from last 2 weeks
Git blame helps trace when and why a line was changed, essential for debugging regressions.
2. How do you clean untracked files with git clean?
Show answer
`git clean` removes untracked files from the working directory.- `git clean -n` (dry run) -- show what WOULD be deleted
- `git clean -f` -- force delete untracked files
- `git clean -fd` -- also remove untracked directories
- `git clean -fX` -- remove only ignored files
- `git clean -fx` -- remove ignored AND untracked files
Always run `-n` first to preview. Combine with `git checkout -- .` or `git restore .` to also discard modified tracked files. Useful for cleaning build artifacts or resetting to a pristine state.
🟡 Medium (11)¶
1. What is git cherry-pick and when do you use it?
Show answer
`git cherry-pickUse cases: backporting a bugfix to a release branch, pulling a specific feature commit without merging the whole branch.
For multiple commits: `git cherry-pick A..B` (exclusive of A) or `git cherry-pick A^..B` (inclusive).
If conflicts occur, resolve them, `git add`, then `git cherry-pick --continue`. Use `--abort` to cancel.
2. How does git bisect work for finding bugs?
Show answer
`git bisect` performs a binary search through commit history to find which commit introduced a bug.1. `git bisect start`
2. `git bisect bad` (current commit is broken)
3. `git bisect good
Git checks out a midpoint commit. Test it, then mark `git bisect good` or `git bisect bad`. Repeat until the culprit is found.
Automate: `git bisect run ./test.sh` -- the script should exit 0 for good, non-zero for bad.
`git bisect reset` to return to your original branch. Finds the bug in O(log n) commits.
3. Explain git stash subcommands: pop vs apply, show, list, drop.
Show answer
`git stash` saves uncommitted changes to a stack.- `git stash list` -- show all stashes (stash@{0}, stash@{1}, ...)
- `git stash show -p stash@{0}` -- show the diff of a stash
- `git stash apply` -- reapply the top stash WITHOUT removing it from the stack
- `git stash pop` -- reapply the top stash AND remove it from the stack
- `git stash drop stash@{n}` -- delete a specific stash
- `git stash clear` -- delete ALL stashes
- `git stash branch
Key difference: `pop` = `apply` + `drop`. Use `apply` when you want to apply the same stash to multiple branches.
4. How do you use git reflog to recover lost commits?
Show answer
`git reflog` shows a log of all HEAD movements (commits, checkouts, rebases, resets). Even after a `git reset --hard`, the old commits are still in reflog for ~90 days.Recovery workflow:
1. `git reflog` -- find the commit hash before the mistake
2. `git checkout
Common rescues: undo a bad rebase (`git reset --hard HEAD@{n}`), recover a deleted branch (`git branch recover-branch
`git reflog expire` controls when entries are pruned. Default: 90 days for reachable, 30 days for unreachable commits.
5. What is .gitattributes and what can you configure with it?
Show answer
`.gitattributes` controls per-path settings: line ending normalization, diff drivers, merge strategies, and Git LFS tracking.Examples:
`*.txt text eol=lf` -- force LF line endings
`*.png binary` -- treat as binary (no diff, no merge)
`*.psd filter=lfs diff=lfs merge=lfs -text` -- track with Git LFS
`*.sql diff=sql` -- use SQL-aware diff driver
`*.lock -merge` -- always take ours on merge conflicts
Place in repo root (applies recursively) or in subdirectories for path-specific rules. Unlike `.gitignore`, `.gitattributes` affects HOW files are handled, not WHETHER they are tracked.
6. Explain merge conflict markers and resolution strategies.
Show answer
When Git cannot auto-merge, it inserts conflict markers:`<<<<<<< HEAD
your changes
=======
their changes
>>>>>>> branch-name`
Resolution strategies:
1. **Manual**: Edit the file, remove markers, keep the correct code, `git add`, `git commit`
2. **Ours/theirs**: `git checkout --ours file` or `--theirs file` to pick one side entirely
3. **Merge tool**: `git mergetool` launches a visual diff tool (vimdiff, meld, kdiff3)
4. **Rerere**: `git config rerere.enabled true` -- Git remembers how you resolved a conflict and auto-applies it next time
Prevention: merge often, keep branches short-lived, communicate about shared files.
7. What is git worktree and when is it useful?
Show answer
`git worktree` lets you check out multiple branches simultaneously in separate directories, sharing a single `.git` repo.- `git worktree add ../hotfix-branch hotfix` -- create a new working tree for the hotfix branch
- `git worktree list` -- show all working trees
- `git worktree remove ../hotfix-branch` -- clean up
Use cases: reviewing a PR while working on your own branch, running tests on one branch while coding on another, comparing behavior across branches.
All worktrees share the same object database and refs, so disk usage is minimal. You cannot check out the same branch in two worktrees simultaneously.
8. How do you search through git history for specific changes?
Show answer
Several tools:- `git log --grep="pattern"` -- search commit messages
- `git log -S "string"` (pickaxe) -- find commits that added/removed a string
- `git log -G "regex"` -- like -S but with regex
- `git log --all --oneline -- path/to/file` -- history of a specific file
- `git log --diff-filter=D -- filename` -- find when a file was deleted
- `git show :
Combine with `--since`, `--until`, `--author` for targeted searches. The pickaxe (-S) is especially powerful for finding when a function or variable was introduced or removed.
9. What is the difference between git reset --soft, --mixed, and --hard?
Show answer
All three move HEAD to the target commit but differ in what they reset:- `--soft`: moves HEAD only. Staging area and working directory unchanged. Changes appear as staged.
- `--mixed` (default): moves HEAD, resets staging area. Working directory unchanged. Changes appear as unstaged.
- `--hard`: moves HEAD, resets staging area AND working directory. All changes are discarded.
Use `--soft` to squash commits (reset then recommit). Use `--mixed` to unstage. Use `--hard` to fully discard (recoverable via reflog for ~30 days).
Never `reset --hard` on shared branches without team coordination.
10. What is the difference between lightweight and annotated tags?
Show answer
Lightweight tags are just pointers to a commit: `git tag v1.0`. Annotated tags are full objects with tagger name, date, message, and optional GPG signature: `git tag -a v1.0 -m "Release 1.0"`.Annotated tags are recommended for releases because they include metadata and can be verified. Lightweight tags are useful for temporary/private markers.
`git push origin v1.0` pushes a specific tag. `git push --tags` pushes all tags. `git tag -d v1.0` deletes locally; `git push origin --delete v1.0` deletes remote.
11. What are git hooks and how do you use them for CI/CD?
Show answer
Git hooks are scripts in `.git/hooks/` that run automatically at specific points: `pre-commit`, `commit-msg`, `pre-push`, `post-merge`, etc.Common uses:
- `pre-commit`: run linters, formatters, check for secrets
- `commit-msg`: enforce conventional commit format
- `pre-push`: run tests before pushing
Hooks are NOT committed by default (they live in `.git/`). Use tools like `pre-commit` (pre-commit.com), `husky` (Node), or `lefthook` to manage shared hooks via config files committed to the repo.
Server-side hooks (`pre-receive`, `post-receive`) run on the remote and can enforce branch protection policies.
🔴 Hard (2)¶
1. How do git submodules work (add, update, sync, deinit)?
Show answer
Submodules embed one git repo inside another at a specific commit.- `git submodule add
- `git submodule update --init --recursive` -- clone and checkout submodules after a fresh clone
- `git submodule update --remote` -- pull latest from the submodule's tracked branch
- `git submodule sync` -- update submodule URLs after `.gitmodules` changes
- `git submodule deinit
Submodules pin to a specific commit. The parent repo tracks which commit each submodule should use. Alternatives: git subtree (merges history) or package managers.
2. What are common interactive rebase patterns (fixup, squash, reorder)?
Show answer
`git rebase -i HEAD~n` opens an editor with the last n commits. Each line starts with a command:- `pick` -- keep the commit as-is
- `squash` (s) -- merge into previous commit, combine messages
- `fixup` (f) -- merge into previous commit, discard this commit's message
- `reword` (r) -- change commit message
- `edit` (e) -- pause to amend the commit
- `drop` (d) -- delete the commit
Reorder by moving lines. Common workflow: make small WIP commits, then `rebase -i` to squash/fixup into clean logical commits before pushing.
Never rebase commits that have been pushed to a shared branch -- it rewrites history and forces others to force-pull.