git_advanced 25 Q&As

Git Advanced FAQ & Answers

25 expert Git Advanced answers researched from official documentation. Every answer cites authoritative sources you can verify.

unknown

25 questions
A

Git rebase (Git 2.45+): reapplies commits from one branch onto another, creating linear history by replaying commits. Command: git rebase main (rebase current branch onto main). Process: (1) Find common ancestor. (2) Save commits from current branch. (3) Reset current branch to target. (4) Replay saved commits one by one with new SHAs. Git merge: creates merge commit, preserves both histories, non-linear graph. Key differences: Rebase creates clean linear history (better for feature branches before PR), rewrites commit SHAs (dangerous if pushed to shared branches). Merge preserves complete history (safe for shared branches like main/develop), shows when/where branches merged. Best practices (2025): Use git rebase -i main to clean up feature branch commits before merging. Always git pull --rebase for local commits on tracked branches. Never rebase commits already pushed to shared repositories. Enable git config --global pull.rebase true for cleaner history.

99% confidence
A

Interactive rebase (Git 2.44+): powerful tool to edit commit history, squash commits, reorder, edit messages. Commands: git rebase -i HEAD~3 (last 3 commits), git rebase -i main (all commits since main). Editor opens with commits and actions: pick (use commit), reword (change message), edit (amend commit), squash (combine with previous, keep both messages), fixup (like squash but discard message), drop (remove commit), exec (run shell command). Modern workflow (2025): Use git commit --fixup= for fix commits, then git rebase -i --autosquash main automatically squashes fixup commits. Git 2.44+ enables autosquash without -i flag. Example: Clean feature branch: git rebase -i main, change pick to fixup for WIP commits, squash related commits, reword final messages. Best practices: Enable git config --global rebase.autosquash true. Use before PR submission. Never rebase pushed commits on shared branches.

99% confidence
A

Git cherry-pick: applies changes from specific commit to current branch, creating new commit with same changes but different SHA. Commands: git cherry-pick (single commit), git cherry-pick (multiple), git cherry-pick main3..main1 (range, excludes main~3). Common use cases (2025): (1) Backport bug fix to release branches: git checkout release-2.0 && git cherry-pick . (2) Recover lost commits from reflog: git reflog → git cherry-pick . (3) Apply specific features without merging entire feature branch. Options: -x (append 'cherry picked from commit ' to message, recommended for tracking), -n (stage changes without committing), --continue/--abort (conflict resolution), -m 1 (select parent for merge commits). Best practices: Use git cherry-pick -x for traceability. Prefer merge/rebase for multiple related commits. Document why cherry-picked in commit message.

99% confidence
A

Git reset: moves HEAD and current branch pointer to specified commit, modifies staging area and working directory differently. (1) git reset --soft : moves HEAD only, keeps staging area and working directory unchanged. Use for: undo last commit but keep changes staged (git reset --soft HEAD~1), combine multiple commits. (2) git reset --mixed (default): moves HEAD, resets staging area, keeps working directory with modifications. Use for: unstage all changes (git reset HEAD), undo commits but preserve file changes. (3) git reset --hard : moves HEAD, resets staging area AND working directory. Destructive: permanently loses uncommitted changes. Use for: discard all local changes (git reset --hard HEAD), match remote exactly (git reset --hard origin/main). Recovery: All reset commits recoverable via git reflog for 90 days (default). Safety: Always use --soft/--mixed first. Only use --hard when certain. Best practice (2025): Avoid git reset on pushed commits (use git revert instead).

99% confidence
A

Git reset: moves branch pointer backwards, rewrites history by removing commits from branch. Commands: git reset --soft HEAD~1 (undo commit, keep staged), git reset --hard origin/main (match remote). Use for: local unpushed commits, private feature branches. Destructive: commits become unreachable but recoverable via git reflog for 90 days. Git revert: creates new commit that applies exact opposite of changes (inverse cherry-pick). Commands: git revert (revert single commit), git revert .. (revert range), git revert -m 1 (revert merge commit). Doesn't rewrite history, safe for public branches. Use for: undo pushed commits on shared branches (main/develop), maintain audit trail. Example: Fix bad commit on main: git revert abc123 creates new commit undoing abc123. Best practices (2025): Use reset only for local changes. Always use revert for shared branches. Never reset commits pushed to main/master.

99% confidence
A

Git reflog: records every HEAD movement in local repository (commits, checkouts, resets, rebases, cherry-picks). Commands: git reflog (show all HEAD movements), git reflog show branch-name (specific branch), git reflog show --all (all refs). Output: HEAD@{0} (current), HEAD@{1} (previous), etc. with commit SHA, action, and timestamp. Example output: abc123 HEAD@{0}: commit: Add feature / def456 HEAD@{1}: reset: moving to HEAD~1. Recovery scenarios (2025): (1) Undo accidental reset: git reflog → find commit before reset → git reset --hard . (2) Recover deleted branch: git reflog → find branch tip → git branch recovered-branch . (3) Recover lost commits after rebase: git reflog → git cherry-pick . (4) Find commit by action: git reflog --grep='rebase'. Expiration: 90 days for unreachable commits (gc.reflogExpire), 30 days for unreachable reflog entries (gc.reflogExpireUnreachable). Reflog is local only (not pushed to remote).

99% confidence
A

Git bisect: 'binary search through commit history to find commit that introduced bug.' Process: (1) git bisect start. (2) git bisect bad (mark current commit as bad). (3) git bisect good (mark known good commit). (4) Git checks out middle commit. (5) Test if bug present. (6) git bisect bad or git bisect good. (7) Repeat until Git identifies first bad commit. (8) git bisect reset (finish). Automated: git bisect run (script exits 0=good, 1=bad). 'Git bisect can find commit that changed any property of project, supports "old" and "new" terms in place of "good" and "bad".' Options: --no-checkout (manual testing), skip (commit can't be tested). Use for: finding regressions, identifying when bug introduced. Essential debugging tool.

99% confidence
A

Git worktree (Git 2.15+): allows multiple working directories for single repository, each checked out to different branch. Share single .git directory, avoiding multiple clones. Commands: git worktree add ../hotfix-dir hotfix (create worktree for existing branch), git worktree add -b feature-x ../feature-x-dir main (create new branch), git worktree list (show all worktrees with branches), git worktree remove ../hotfix-dir (delete worktree), git worktree prune (clean stale metadata). Use cases (2025): (1) Urgent hotfix while working on feature (no stashing needed). (2) Review PR without losing current work. (3) Parallel CI/testing in different worktrees. (4) Stacked diffs workflow (multiple dependent features). Benefits: Faster than git clone (shares objects), no stashing/switching overhead, independent working states. Limitations: Can't checkout same branch in multiple worktrees, refs in refs/bisect and refs/worktree not shared. Best practices: Use descriptive directory names, run git worktree prune monthly, commit before removing worktree.

99% confidence
A

Git submodule: repository embedded inside another repository (superproject), maintains separate history and .git directory. Use for: third-party libraries, shared code across projects, monorepo components. Commands: git submodule add path/to/lib (add submodule, creates .gitmodules), git clone --recurse-submodules (clone with submodules), git submodule update --init --recursive (initialize after cloning), git submodule update --remote (update to latest remote commit), git pull --recurse-submodules (pull superproject and submodules). Workflow challenges: Submodules stay in detached HEAD state, require explicit git submodule update after pulling superproject, updating all team members' submodules needs coordination. Modern alternatives (2025): git subtree (embeds code into superproject, simpler workflow), monorepo tools (Nx, Turborepo for JavaScript, Bazel for polyglot), package managers (npm/pnpm workspaces, Go modules). Best practices: Document submodule update workflow in README, use git config --global submodule.recurse true for automatic updates, consider package managers for simple cases.

99% confidence
A

Git hooks: scripts Git executes before/after events (commit, push, merge) to automate workflow. Stored in .git/hooks/, must be executable (chmod +x). Client-side hooks: pre-commit (lint/test before commit, exits non-zero to abort), prepare-commit-msg (edit default message), commit-msg (validate format, enforce conventional commits), post-commit (notifications), pre-push (run full test suite, prevent bad pushes), post-checkout (install dependencies), post-merge (npm install after pulling package.json changes). Server-side hooks: pre-receive (validate push before accepting), update (per-branch validation), post-receive (trigger CI/CD deployment). Modern tooling (2025): Husky v9 (Node.js, 2 kB, ~1ms execution, auto-installs hooks via npm), pre-commit framework (Python ecosystem), lefthook (fast Go-based tool). Example with Husky: npx husky init creates .husky/ directory, npx husky add .husky/pre-commit "npm test" adds hook. Combine with lint-staged to only check staged files. Best practices: Keep hooks fast (<2s for pre-commit), use lint-staged for performance, version control hooks via Husky/pre-commit, document setup in README.

99% confidence
A

Git stash advanced commands beyond basic git stash/git stash pop. Named stashes: git stash push -m "WIP: refactoring auth" (descriptive message). Partial stashing: git stash push -- src/auth.js src/utils.js (specific files only), git stash push -p (interactive, select hunks). Include untracked/ignored: git stash -u (include untracked files), git stash -a (include ignored files like build artifacts). Managing multiple stashes: git stash list (shows stash@{0}, stash@{1}, etc. with messages), git stash show stash@{1} -p (view diff of specific stash), git stash apply stash@{1} (apply without removing from list), git stash pop stash@{1} (apply and remove), git stash drop stash@{1} (delete specific stash), git stash clear (delete all stashes). Advanced workflows: git stash branch feature-from-stash stash@{0} (create branch from stash, auto-applies and drops stash). Best practices (2025): Name all stashes with -m, clean stashes monthly with git stash list, prefer git worktree for long-term parallel work, use git stash -u by default to avoid losing untracked files.

99% confidence
A

Git clean: removes untracked files from working directory. Permanently deletes files (not recoverable). ALWAYS preview first: git clean -n (dry-run, shows what would be deleted), git clean -nd (dry-run including directories). Deletion commands (require -f force flag): git clean -f (delete untracked files only), git clean -fd (delete untracked files and directories), git clean -fX (delete only ignored files from .gitignore, preserves build artifacts logic), git clean -fx (delete ALL untracked and ignored files, nuclear option). Interactive mode: git clean -i (choose what to delete interactively, safest). Common workflows (2025): Clean build artifacts: git clean -fX (removes node_modules, dist/, .cache). Fresh clone state: git clean -fdx (WARNING: removes everything not tracked). Safe exploration: git clean -fdn → review → git clean -fd. Best practices: ALWAYS run git clean -n first, add permanent ignores to .gitignore instead of cleaning repeatedly, use git stash -u instead if might need files later, configure git config --global clean.requireForce true (default safety).

99% confidence
A

Git blame: shows which commit and author last modified each line of file. Basic: git blame file.js (shows SHA, author, timestamp, line number, content). Output format: abc123 (John Doe 2025-01-15 14:23:45 -0500 42) const x = 1;. Advanced options: git blame -L 10,20 file.js (specific line range), git blame -L :functionName: file.js (blame specific function), git blame -w (ignore whitespace changes), git blame -C (detect lines copied from other files in same commit), git blame -C -C (detect copies from any commit), git blame -M (detect moved/cut-pasted lines within file), git blame abc123 file.js (blame at specific commit in history), git blame --since="3.weeks" file.js (only show changes from last 3 weeks). Effective workflow (2025): git blame file.js → find SHA → git show (full commit context) → git log -p -S"keyword" (find why keyword introduced). Modern tools: GitHub/GitLab show blame inline with syntax highlighting. Best practices: Use to understand code context (not assign blame), combine with git log for full story, ignore formatting commits with .git-blame-ignore-revs file (Git 2.23+).

99% confidence
A

Advanced git log filtering for code archeology. Author/date filters: git log --author="John" --committer="Jane" (regex supported), git log --since="2.weeks" --until="2025-01-01", git log --after="2025-01-01 09:00" --before="2025-01-15 17:00" (precise timestamps). Content filters: git log --grep="fix" --grep="bug" --all-match (multiple patterns, AND logic), git log -S"TODO" (pickaxe: commits adding/removing string), git log -G"function.*{" (regex pattern in diff), git log -L:functionName:file.js (track function history). File/path filters: git log -- path/to/file (commits affecting file), git log --follow -- file.js (track through renames). Branch comparison: git log main..feature (commits in feature not in main), git log main...feature (symmetric difference, commits in either but not both). Format options: git log --oneline --graph --decorate (visual branch history), git log --pretty=format:"%h %an %ar: %s" (custom format), git log --stat (file change stats), git log -p (full diff). Advanced: git log --merges (only merge commits), git log --no-merges --first-parent (linear history on main), git log --all --source (all branches with branch names). Combined: git log --author="John" --since="1.month" --grep="fix" --no-merges -S"API" (powerful multi-filter).

99% confidence
A

git filter-branch: deprecated tool for rewriting Git history (slow, complex, error-prone). Modern alternative: git-filter-repo (10-100x faster, safer, not built-in). Install: brew install git-filter-repo or pip install git-filter-repo. Common use cases (2025): (1) Remove sensitive data: git filter-repo --invert-paths --path secrets.env (removes file from all history). (2) Extract subdirectory: git filter-repo --path subdir/ --path-rename subdir/: (make subdir new root). (3) Change author info: git filter-repo --mailmap mailmap.txt (fix names/emails). (4) Remove large files: git filter-repo --strip-blobs-bigger-than 10M. Critical workflow: (1) REVOKE compromised credentials first (if removing secrets). (2) Fresh clone: git clone --mirror repo.git. (3) Run filter-repo on clone. (4) Force push: git push --force --all. (5) All team members must re-clone (history rewritten). BFG Repo-Cleaner: simpler alternative for removing files/passwords. Best practices (2025): Use filter-repo not filter-branch, close all PRs before rewriting, coordinate team re-clone, backup before running, verify with git log after.

99% confidence
A

Git rerere (Reuse Recorded Resolution): 'records how merge conflicts resolved, automatically reuses solutions.' Enable: git config --global rerere.enabled true && git config --global rerere.autoupdate true. autoupdate automatically stages resolved conflicts (default: false, requires manual git add). Storage: resolutions in .git/rr-cache/ directory. How it works: (1) Conflict occurs during merge/rebase. (2) You resolve conflict + commit. (3) Git records resolution (conflict markers + resolution). (4) Same conflict later → Git auto-applies recorded resolution. Enable when: rebasing >3 times/week, long-lived feature branches (>2 weeks), frequent integration with main branch. Cache expiration: unresolved conflicts pruned after 15 days (gc.rerereUnresolved), resolved after 60 days (gc.rerereResolved). Commands: git rerere status (conflicts), git rerere diff (resolutions), git rerere forget (clear). Best practice: enable globally for teams using rebase workflows, always verify auto-resolutions with git diff before committing. Essential for reducing repetitive conflict resolution.

99% confidence
A

Git history rewriting best practices (2025): Golden rule: NEVER rewrite pushed commits on shared branches (main, master, develop, release). Breaks collaborators' repos. Safe scenarios: (1) Private feature branches before merging. (2) Local unpushed commits. (3) Team-coordinated rewrites with all members re-cloning. Pre-rewrite safety: git branch backup-feature (create backup branch), git reflog (verify recoverable for 90 days). Rewriting tools: git rebase -i main (clean up feature branch commits), git commit --amend (fix last commit message/files), git reset --soft HEAD~3 (undo commits, keep changes staged). Safe force-pushing: Use git push --force-with-lease (Git 2.30+: add --force-if-includes for extra safety). Checks if remote changed since last fetch, prevents overwriting teammates' work. Fails if remote updated by others. Alternative: git push --force is dangerous (blindly overwrites). Team coordination: Announce before force-pushing shared branches, document reason in PR/Slack, ensure all members fetch before/after, prefer git revert for public commits (preserves history, no force-push needed). Verification: git log --oneline --graph after rewriting, git push --dry-run --force-with-lease before pushing.

99% confidence
A

Git patches: text files containing diffs, used for sharing changes without Git remote access. Create patches: git diff > unstaged.patch (uncommitted changes), git diff --cached > staged.patch (staged changes), git format-patch -1 HEAD (last commit as 0001-.patch with metadata), git format-patch -3 HEAD (last 3 commits, creates 3 files), git format-patch main..feature (all commits in feature since main), git format-patch --stdout main > feature.patch (single file for all commits). Apply patches: git apply changes.patch (apply diff without committing, like git diff output), git apply --check changes.patch (dry-run test), git apply --3way changes.patch (three-way merge if conflicts), git am 0001-.patch (apply format-patch files, preserves commits/author/date), git am --signoff *.patch (add Signed-off-by line). Use cases (2025): Linux kernel mailing list workflow, contributing to projects without push access, sharing changes via forums/email, archiving experimental changes. Difference: git format-patch includes full commit metadata (author, date, message, committer), git am recreates original commits exactly. Best practices: Prefer PRs/MRs for team collaboration, use patches for open-source mailing lists, test with --check before applying.

99% confidence
A

Git tags mark specific points in history for releases/versions. Lightweight tag: simple pointer to commit (like immovable branch). Create: git tag v1.0.0. Stores: commit SHA only (41 bytes). Use for: temporary markers, local bookmarks, private milestones. Annotated tag: full Git object with metadata. Create: git tag -a v1.0.0 -m "Release 1.0.0" or git tag -a v2.0.0 -m "Backport release". Stores: tagger name/email, tag date, message, commit SHA, GPG/SSH signature (if signed). View: git show v1.0.0 displays tag metadata + commit. Signing (2025 security best practice): git tag -s v1.0.0 -m "Signed release" (GPG signature), git tag -s v1.0.0 -m "SSH signed" --sign-with-ssh (Git 2.34+, SSH key). Verify: git tag -v v1.0.0. Operations: git tag -l "v1.*" (list pattern), git push origin v1.0.0 (push single tag), git push origin --tags (push all tags), git tag -d v1.0.0 (delete local), git push origin --delete v1.0.0 (delete remote). Best practices: Use annotated tags for all releases (public record with metadata), sign release tags for security/authenticity, follow semver (v1.2.3), use lightweight only for temporary local markers.

99% confidence
A

git gc (garbage collection): optimizes repository by packing loose objects, removing unreachable objects, cleaning caches. Operations: (1) Packs loose objects into compressed packfiles (saves disk space, faster operations). (2) Removes objects unreachable from any ref after grace period (default 14 days for objects, 90 days for reflog commits). (3) Packs refs into packed-refs file. (4) Cleans rerere cache and worktree metadata. (5) Prunes old reflog entries (90 days for reachable, 30 days for unreachable). Commands: git gc (standard cleanup, runs in ~seconds for small repos), git gc --aggressive (thorough repack, slow, rarely needed), git gc --prune=now (immediate pruning, use after filter-repo), git gc --auto (runs only if needed based on heuristics). Automatic triggering (Git 2.30+): Git auto-runs gc when: >6700 loose objects exist, >50 packfiles exist, or after operations like fetch/rebase. Modern alternative (Git 2.30+): git maintenance start (schedules background tasks: hourly commit-graph/prefetch, daily incremental-repack/loose-objects, weekly gc). Best practices (2025): Let automatic gc handle routine maintenance, run git gc after major history rewrites (filter-repo), use git maintenance for repos >1GB, avoid --aggressive (minimal benefit, high cost).

99% confidence
A

Git bundle: single file containing Git objects and refs for offline transfer. Create full: git bundle create repo.bundle --all (entire repo with all branches/tags). Create specific: git bundle create feature.bundle main (single branch). Incremental: git bundle create updates.bundle main10..main (last 10 commits, requires main10 exists in destination). Verify: git bundle verify repo.bundle (checks integrity and prerequisites). Clone: git clone repo.bundle new-repo (creates repository from bundle). Fetch: git fetch /path/to/repo.bundle refs/heads/main:refs/heads/main (imports branch). Track incremental: git tag -f last-bundle main (mark last bundled commit), then git bundle create next.bundle last-bundle..main. Use cases: air-gapped deployments (no network access), secure environments (financial/lab systems), offline transfer (USB/email), CI/CD artifacts. Bundle is read-only (cannot push to it). Best practice: verify before use, tag bundle points, err on overlap side (safe).

99% confidence
A

Advanced git config for productivity (2025). Conflict resolution: git config --global rerere.enabled true (reuse recorded resolutions, essential for frequent rebasing), git config --global merge.conflictstyle zdiff3 (Git 2.35+, best conflict markers with common ancestor). Branch management: git config --global fetch.prune true (auto-delete gone remote branches), git config --global pull.rebase true (rebase not merge on pull, cleaner history), git config --global push.default current (push current branch to same name), git config --global push.autoSetupRemote true (Git 2.37+, auto-create remote branch). Rebase workflow: git config --global rebase.autosquash true (auto-handle fixup!/squash! commits), git config --global rebase.updateRefs true (Git 2.38+, auto-update dependent branches). Security: git config --global commit.gpgsign true (sign all commits), git config --global gpg.format ssh (use SSH keys for signing, Git 2.34+), git config --global user.signingkey ~/.ssh/id_ed25519.pub. Performance: git config --global core.fsmonitor true (Git 2.37+, faster git status on large repos), git config --global feature.manyFiles true (optimize for repos with many files). UX improvements: git config --global core.excludesfile ~/.gitignore_global (global .gitignore), git config --global help.autocorrect 10 (auto-run misspelled commands after 1s), git config --global alias.st "status -sb" (shortcuts). Credential management: git config --global credential.helper osxkeychain (macOS) or git config --global credential.helper 'cache --timeout=3600' (Linux, 1 hour cache).

99% confidence
A

Common Git mistakes and recovery (2025). (1) Committed to wrong branch: git reset --soft HEAD~1 (uncommit, keep changes staged), git switch correct-branch, git commit (or git cherry-pick from wrong branch). (2) Wrong commit message: git commit --amend -m "Correct message" (last commit only, unpushed). (3) Forgot to add file: git add forgotten.js && git commit --amend --no-edit (adds to last commit). (4) Deleted branch: git reflog → find tip (e.g., abc123) → git branch recovered abc123. (5) Accidental git reset --hard: git reflog → find commit before reset → git reset --hard abc123 (reflog stores 90 days). (6) Pushed wrong commit to main: git revert (safe, creates inverse commit) OR coordinate with team: git reset --hard && git push --force-with-lease (dangerous). (7) Lost commits after rebase: git reflog → git cherry-pick . (8) Detached HEAD after checkout : git switch main or git checkout -b new-branch (save work). (9) Merge conflict panic: git merge --abort or git rebase --abort (return to pre-merge state). (10) Committed secrets (.env file): git filter-repo --invert-paths --path .env (rewrites history, requires force-push and team re-clone). Key tool: git reflog is Git's time machine (recovers almost anything within 90 days).

99% confidence
A

Sparse-checkout (Git 2.25+): check out only subset of files from repository, skip rest. Setup: git clone --no-checkout && cd repo && git sparse-checkout init --cone && git sparse-checkout set src/backend tests (cone mode, directory-based, faster). Cone mode (recommended): Uses directories only, O(M+N) performance vs O(N*M) for pattern mode. Add paths: git sparse-checkout add docs. Disable: git sparse-checkout disable. Use cases: Monorepos (only checkout services/api/ from 50+ services), large repos (skip node_modules/, build artifacts). Performance: 10x faster git status with cone mode + sparse-index (git config --global index.sparse true, Git 2.35+). Shallow clone: clone with limited history depth. Create: git clone --depth 1 (only latest commit, fastest for CI/CD). Deepen: git fetch --depth 10 (fetch 10 commits back), git fetch --unshallow (convert to full clone). Limitations: Can't clone from shallow clone, some operations fail (bisect). Partial clone (Git 2.22+): git clone --filter=blob:none (fetch blobs lazily, download only when needed). Combines well with sparse-checkout. Best practices (2025): CI: --depth 1 (fastest), Development: full clone or --filter=blob:none, Monorepos: sparse-checkout cone mode + sparse-index, Huge repos (>1GB): scalar clone (Git 2.38+, combines partial clone + sparse-checkout + maintenance).

99% confidence
A

git maintenance (Git 2.30+): 'scheduled optimization tasks for large repos.' Enable: git maintenance start (runs hourly: commit-graph/prefetch, daily: loose-objects/incremental-repack, weekly: pack-refs). incremental-repack consolidates small pack-files without full repack (repos with thousands of packs dropped to dozens, 200GB→30-50GB). commit-graph accelerates log/blame/traversal operations. multi-pack-index prevents performance degradation from many packfiles. Large repo optimization: (1) scalar clone (Git 2.38+, combines partial clone + sparse-checkout + maintenance). (2) Partial clone: git clone --filter=blob:none (download blobs lazily). (3) Sparse checkout: git sparse-checkout set (checkout only needed directories). Best practice: git maintenance start for repos >1GB, scalar clone for monorepos, incremental-repack avoids expensive gc.

99% confidence