Git Advanced Commands Quick Reference Guide

Production-ready guide covering git advanced commands quick reference guide with implementation patterns, code examples, and anti-patterns for enterprise engineering teams.

This reference collects the git commands and configuration patterns that surface when everyday workflows hit their limits. It matters when git push is rejected after a rewrite, when a commit must be amended after it’s been shared, when history must be searched across every branch, or when a repository state must be rescued after a mistaken reset. Every entry below is a real, ship‑built git subcommand, flag, or config key – nothing invented, nothing attributed to a commercial product. Use it as a lookup table for the moments where the porcelain layer stops helping and the plumbing layer begins.

Inspecting History

Searching commits across all branches

git log --graph --oneline --all --decorate displays the full branch graph, every head, and short subject lines. Pair --grep=<pattern> with --all-match or --invert-grep to filter by commit message content. For line‑level searches, git log -S<term> finds commits that added or removed the given text string, regardless of when it was introduced.

Blaming specific lines

git blame -L 42,42 path/to/file.py annotates line 42 with the last commit and author that modified it. The -L range accepts start,end, start,+lines, or +start,+lines. Note that git blame respects the git blame.ignoreRevsFile config if a .git-blame-ignore-revs file exists; it does not skip lines that are part of a merge commit’s first parent by default.

Recovering with the reflog

git reflog show --all lists every ref update across all repositories on the machine, including dropped commits, branch creations, and checkouts. Each entry has an @{n} syntax: git checkout @{1} returns you to the previous HEAD, irrespective of branch. The reflog expires after the period set by gc.reflogExpire (default 30 days) and gc.reflogExpireUnreachable (default 90 days for unreachable objects). After expiration, git fsck --unreachable can still locate dangling objects, but they are no longer reachable via git reflog.

Rewriting Commits (High‑Risk Zone)

Amending the most recent commit

git commit --amend --no-edit replaces the tip commit with the current staged changes, preserving the original commit message. If no changes are staged, the command opens the editor (or uses commit.gpgsign/ commit.template settings) without altering the message. To change the message without touching the snapshot, use git commit --amend alone, which invokes the editor.

Interactive rebase

git rebase -i HEAD~5 opens the sequence editor with the last five commits. Each line follows the format action <commit>, where actions are pick, reword, edit, squash, or fixup. squash merges the commit message as well as the changes; fixup discards the message and keeps only the changes. Sharp edge: reordering or dropping commits in an interactive rebase rewrites every subsequent commit hash. If any of the rewritten commits have been pushed to a shared remote, the history diverges and git push will be rejected unless --force-with-lease is used.

Resetting the tip of a branch

git reset --soft HEAD~1 moves the current branch pointer backward one commit while keeping all changes from that commit staged. git reset --mixed HEAD~1 (the default) unstages the changes but leaves them in the working directory. git reset --hard HEAD~1 discards both the commit and all its changes—this action is irreversible without git reflog or object recovery. A common confusion: --soft leaves changes staged, --mixed leaves them unstaged but present, and --hard wipes them entirely. Always verify with git status before and after.

Deprecated git filter‑branch and the modern alternative

git filter-branch --tree-filter 'rm -f path/to/file' HEAD~1..HEAD removes a file from every commit in the range. This command is deprecated in Git 2.33+ because of performance issues and edge cases with environment variables. The recommended replacement is git filter-repo, a standalone Python script installed via pip install git-filter-repo. It offers --blob-callback, --msg-callback, and --path-rename flags with comparable functionality but a different CLI surface. If you must stay within built‑in git, be aware that filter‑branch rewrites every commit’s SHA, updates every branch tip, and can produce duplicate commits if the same tree appears under multiple parents.

Recovering Lost Work

Using git fsck to find dangling objects

git fsck --unreachable --dangling --lost scans the object database for commits, trees, and blobs not reachable from any ref. Output lines begin with unreachable blob <hash>, unreachable tree <hash>, or unreachable commit <hash>. To recover a specific commit, git checkout <hash> creates a detached HEAD at that commit, from which you can git cherry-pick or git merge the work into a current branch.

Resurrecting an expired reflog entry

If the reflog entry you need has expired, you can still locate the object by its hash if you have it. Otherwise, git fsck --unreachable will list it. Once identified, git checkout -b <new-branch> <hash> creates a recoverable branch at that point. Production tip: many teams enable gc.pruneExpire to a longer window (e.g., 180 days) in environments where history‑rewriting operations are frequent, reducing the window in which reflog‑based recovery is possible.

Recovering from a force‑pushed shared branch

When a teammate runs git push --force on a branch you’ve both been working on, your local reflog still contains the old tip. git fetch origin followed by git log origin/<branch>..HEAD shows commits you have locally that the remote no longer does. git rebase origin/<branch> or git merge origin/<branch> can then re‑integrate those commits into your current work. If the remote branch was force‑pushed with a new history, git reflog on your local copy will show the old ref as refs/remotes/origin/<branch>@{1}; you can reset your local branch to that point with git reset --hard refs/remotes/origin/<branch>@{1}.

Managing Branches & Worktrees

Parallel worktrees without cloning twice

git worktree add -b feature/login ../worktrees/feature-login main creates a new worktree tied to the same repository, checked out at main with a new feature/login branch. Each worktree has its own .git file pointing at the shared GIT_DIR. Sharp edge: worktrees share the same index. Running git checkout in one worktree can affect the index visible in another, leading to unexpected staging states. Always git status in the specific worktree you’re operating in.

Pruning stale remote‑tracking branches

git fetch --prune updates all remote‑tracking refs and removes any that no longer exist on the remote. Without --prune, stale refs accumulate and git branch -r shows branches that have been deleted on the server. To also prune unreachable local objects after fetching, pair with git remote prune origin or configure remote.<name>.prune in .gitconfig.

Setting the default remote branch

git remote set-head origin -a makes the local master (or main) track origin/master. Without this, git pull may complain about ambiguous refnames. An alternative, per‑branch approach: git branch --set-upstream-to=origin/main main establishes the tracking connection for a single branch.

git cherry‑pick across divergent histories

git cherry-pick <commit-hash> applies the change introduced by the named commit onto the current branch, creating a new commit with a different SHA. If the commit’s changes conflict with the current state, git pauses and marks conflicts in the usual <<<<<<< / ======= / >>>>>>> format. Resolve the conflicts, git add the resolved files, then git cherry-pick --continue to proceed. git cherry-pick --abort cancels the operation and resets HEAD to the state before the cherry‑pick began.

Configuration & Environment Tweaks

Core .gitconfig keys used in advanced workflows

Environment variables that affect git behavior

Sharp Edges & Production Failure Modes

git push --force vs --force-with-lease

git push --force unconditionally overwrites the remote ref, discarding any commits the remote has that your local history does not know about. git push --force-with-lease (available since Git 1.8.2) only updates the remote if the remote ref is still at the hash you expect (i.e., it “leases” the ref and refuses to overwrite if someone else has pushed in the meantime). Production rule: always prefer --force-with-lease. The only case where --force is safe is when you own the branch exclusively and have confirmed no one else has fetched or pushed to it.

Detached HEAD state pitfalls

Checking out a commit hash, tag, or remote‑tracking ref directly (git checkout v1.2.3 or git checkout <hash>) puts you in a detached HEAD state. Any commits you make here are not on any branch and will be lost if you switch branches or checkout another ref without git branch -c first. To make work permanent, git checkout -b <new-branch> immediately after the detached checkout, or git stash the changes and then create the branch.

git gc and git repack side‑effects

git gc (garbage collection) runs automatically on push or fetch if the repository has accumulated many loose objects. It packs objects, removes unreachable ones, and can temporarily increase disk I/O. git gc --prune=now forces immediate pruning of objects older than the configured expiry. git repack -a -d aggressively packs all objects into a single pack, deleting loose objects. Caution: on very large repositories, git repack can take hours and may not respect the transfer.fetchPrune or gc.pruneExpire settings, potentially removing objects that reflog‑based recovery depends on. Always verify with git fsck after aggressive repacking.

git submodule update gotchas

git submodule update --init --recursive clones each submodule’s recorded commit. If a submodule’s remote URL has changed or the recorded commit no longer exists on the remote, the command fails with fatal: repository '...' does not exist. The error message does not indicate whether the issue is a URL mismatch or a missing commit. To diagnose, git submodule status shows + (initialized), - (not initialized), or * (new). git submodule sync updates the .gitmodules file’s URLs from the config, and git submodule update --init then fetches the correct commit.

git blame performance on histories with many merges

git blame on a file with a long history and numerous merge commits can be slow, because it must walk the full ancestry graph to determine the “last modifying” commit. The --first-parent flag limits the walk to the first parent of each merge, which speeds up the operation but may miss changes that were introduced on a merged side‑branch. If you need blame accuracy across merge branches, be prepared for longer latency; for quick inspection, git log -p --follow <file> often provides a faster, if less precise, view.

git worktree race conditions with concurrent checkouts

When two worktrees share the same repository and one runs git checkout <branch> while the other is in the middle of git add/git commit, the index can become inconsistent. The worktree performing the checkout may report “paths changed on disk” or refuse the checkout until the index is refreshed with git reset. Mitigate by ensuring only one worktree modifies the index at a time, or by using git stash before switching branches across worktrees.

git rebase onto vs. interactive rebase

git rebase --onto <newbase> <upstream> <branch> re‑bases the range <upstream>..<branch> onto <newbase> in a single step, without opening an editor. This is useful for linearizing feature branches: git rebase --onto main feature-branch main reapplies every commit on feature-branch that is not already reachable from main. Sharp edge: if <upstream> is an ancestor of <branch>, the command may silently do nothing or produce an empty rebased history. Always verify the result with git log --oneline after the operation.

git stash with untracked files

git stash by default only stashes tracked files. git stash --include-untracked (or the short form git stash -u) includes untracked files in the stash. git stash --all also stashes ignored files (respecting .gitignore). Production tip: if your workflow depends on untracked assets (e.g., generated documentation, build artifacts), always use git stash -u to avoid losing them when you later git stash pop on a different branch.

*This guide is intentionally terse and command‑focused. It does not replace the git man pages or the official documentation, but it surfaces the exact flags, error messages, and configuration patterns you’ll encounter when the standard workflow breaks down.*

This page was rewritten on 14 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.