$ cat docs/git-commands-reference.md
updated Today · 35-45 min read · published
Git Commands Reference Introduction
This page is the Git commands encyclopedia — porcelain day-to-day tools and the plumbing underneath. Use it alongside How to Master Git and the Git Roadmap .
ℹ info
Porcelain commands are what humans type. Plumbing commands manipulate objects and refs directly — prefer porcelain unless you are debugging or scripting internals.
Porcelain vs Plumbing
Git splits the UI into high-level porcelain and low-level plumbing. Scripts that parse porcelain output break when formats change — prefer plumbing or --porcelain machine modes.
Kind Examples Audience Porcelain add, commit, status, log, switch, merge, rebase, push Humans & agents day-to-day Plumbing hash-object, cat-file, update-index, write-tree, commit-tree, update-ref Internals, recovery scripts Machine porcelain status --porcelain=v1, log --pretty=format: CI parsers, tools
porcelain-machine.sh wrap Bash
Copy 1 # Stable for scripts 2 git status --porcelain=v1 -uall 3 git diff --name-status --diff-filter=ACMR 4 git log -1 --pretty=format:'%H %an %s' 5 6 # Plumbing peek at an object 7 git rev-parse HEAD 8 git cat-file -t HEAD 9 git cat-file -p HEAD | head
config
Read and write configuration at system, global, local, and worktree scopes. See Git Config for deep dive.
Command Purpose git config --global user.name Set identity (required) git config --list --show-origin Show all keys with file source git config --global -e Edit ~/.gitconfig git config --unset key Remove a key git config --get-regexp alias List aliases
Copy 1 git config --global user.name "Jane Doe" 2 git config --global user.email "jane@example.com" 3 git config --global init.defaultBranch main 4 git config --global core.editor "code --wait" 5 git config --global pull.rebase true 6 git config --global fetch.prune true 7 git config --list --show-origin | head -40
init / clone
Create new repositories or copy existing ones. Prefer clone when a remote already exists.
Command Purpose git init -b main New repo with main branch git clone url dir Copy remote into dir git clone --depth 1 Shallow clone (CI) git clone --filter=blob:none Partial clone (blobs on demand) git clone --recurse-submodules Include submodules git clone --bare Bare remote-style repo
Copy 1 git init -b main 2 git clone git@github.com:org/app.git 3 git clone --depth 1 --branch main https://github.com/org/app.git app-ci 4 git clone --filter=blob:none --sparse git@github.com:org/monorepo.git
status / add / commit
Move changes from working tree → index → history. Always inspect status before commit.
Command Purpose git status -sb Short branch + file status git add path Stage file or directory git add -p Interactive hunk staging git add -u Stage tracked modifications/deletes git commit -m "msg" Create commit from index git commit --amend --no-edit Amend last (local only) git commit --fixup HEAD~1 Fixup for autosquash git rm / git mv Remove / rename tracked paths
status-add-commit.sh wrap Bash
Copy 1 git status -sb 2 git add src/app.ts 3 git add -p README.md 4 git commit -m "feat(auth): add session refresh" 5 git commit --amend --no-edit # only if not pushed 6 git restore --staged src/app.ts # unstage
⚠ warning
Never amend commits that have already been pushed to a shared branch unless the team explicitly allows force-with-lease on that branch.
log / diff / show
Inspect history and changes. diff compares trees; show displays one object.
Command Purpose git log --oneline --graph --all Visual history git log -S'symbol' Pickaxe: commits changing string git log -p -1 Patch for latest commit git diff Unstaged vs index git diff --staged Index vs HEAD git diff main...HEAD Triple-dot: changes on branch git show HEAD:path File content at revision
Copy 1 git log --oneline --graph --decorate -20 2 git log --author='Jane' --since='2 weeks ago' --pretty=format:'%h %ad %s' --date=short 3 git log -S'createHash' --oneline -- src/ 4 git diff main...HEAD --stat 5 git diff --staged 6 git show abc123 --stat 7 git show HEAD:package.json | head
branch / switch / checkout
Prefer git switch for branches and git restore for files. checkout still works but overloads two jobs.
Command Purpose git branch -vv List local with upstream git switch -c feature/x Create and switch git switch main Switch branch git switch - Previous branch git branch -d feature/x Delete merged branch git branch -D feature/x Force delete git checkout abc123 -- file Legacy: restore file from rev
Copy 1 git branch -vv 2 git switch -c feature/login 3 git switch main 4 git branch --merged main 5 git branch -d feature/login 6 git push origin --delete feature/login
merge / rebase
Integrate histories. Merge preserves topology; rebase replays commits for linear history. See Merge and Rebasing .
Command Purpose git merge feature Merge into current branch git merge --no-ff feature Always create merge commit git merge --abort Abort conflicted merge git rebase main Replay onto main git rebase -i HEAD~5 Interactive rewrite git rebase --onto Advanced transplant git rebase --abort / --continue Conflict control
Copy 1 git switch main 2 git merge --no-ff feature/login -m "merge: feature/login" 3 git switch feature/payments 4 git fetch origin 5 git rebase origin/main 6 # conflict? fix files, then: 7 git add -A && git rebase --continue
reset / restore / revert
Three different undo tools. Reset moves branch tip; restore fixes files; revert adds an inverse commit.
Command Purpose git reset --soft HEAD~1 Undo commit, keep staged git reset HEAD~1 Mixed: undo commit, unstage git reset --hard HEAD~1 Destroy WD+index to tip git restore file Discard WD changes git restore --staged file Unstage git restore --source=HEAD~1 file Checkout file from rev git revert abc123 New commit undoing abc123 git revert -m 1 mergeHash Revert a merge
Copy 1 # Local unpublished: soft reset and recommit 2 git reset --soft HEAD~1 3 git commit -m "feat: better message" 4 5 # Discard one file's uncommitted edits 6 git restore src/buggy.ts 7 8 # Public bugfix: revert 9 git revert abc123 --no-edit 10 git revert -m 1 def456 # merge commit
✕ danger
git reset --hard discards uncommitted work permanently (unless recoverable via stash/reflog edges). Prefer restore for single files.
stash
Temporarily shelf dirty work. Prefer named stashes; consider worktrees for longer context switches.
Command Purpose git stash push -m "wip" Save WD+index git stash push -u -m "wip" Include untracked git stash list Show stack git stash show -p stash@{0} Show patch git stash pop Apply and drop git stash apply Apply keep entry git stash drop Delete entry
Copy 1 git stash push -u -m "wip: login form" 2 git switch main 3 # hotfix... 4 git switch - 5 git stash pop 6 git stash list
remote / fetch / pull / push
Synchronize with remotes. Fetch downloads; pull = fetch + integrate; push publishes.
Command Purpose git remote -v List remotes git fetch --all --prune Update remote-tracking git pull --rebase Fetch + rebase git push -u origin HEAD Push and set upstream git push --force-with-lease Safer force push git push origin :branch Delete remote branch
Copy 1 git remote -v 2 git fetch origin --prune 3 git status -sb 4 git pull --rebase origin main 5 git push -u origin HEAD 6 # Feature branch rewrite after rebase: 7 git push --force-with-lease origin feature/login
✕ danger
Never git push --force to main /master . Use --force-with-lease only on your feature branches when required.
tag
Mark releases. Prefer annotated (or signed) tags for versions.
Command Purpose git tag -a v1.2.0 -m "..." Annotated tag git tag -s v1.2.0 Signed tag git tag -l 'v*' List tags git push origin v1.2.0 Push one tag git push origin --tags Push all tags git tag -d v1.2.0 Delete local tag
Copy 1 git tag -a v1.2.0 -m "Release 1.2.0" 2 git show v1.2.0 3 git push origin v1.2.0 4 git tag -l 'v1.*' --sort=-v:refname
bisect
Binary search history to find the commit that introduced a bug. See Bisect .
Copy 1 git bisect start 2 git bisect bad HEAD 3 git bisect good v1.0.0 4 # test, then: 5 git bisect good # or: git bisect bad 6 # automate: 7 git bisect run npm test -- --runInBand 8 git bisect reset
cherry-pick
Apply the changes from existing commits onto the current branch.
Copy 1 git switch release/1.2 2 git cherry-pick abc123 3 git cherry-pick abc123 def456 4 git cherry-pick -n abc123 # apply without committing 5 git cherry-pick --abort 6 git cherry-pick --continue
reflog
Local safety net of where HEAD and branches pointed. Primary recovery tool after destructive ops.
Copy 1 git reflog 2 git reflog show main 3 git reset --hard HEAD@{3} 4 git branch recovery HEAD@{5} 5 # expire (dangerous): 6 # git reflog expire --expire=now --all 7 # git gc --prune=now
ℹ info
Reflog is local — it is not pushed. Recover quickly; entries expire (default ~90 days for unreachable).
worktree
Multiple working directories linked to one repository — better than stash for parallel work.
Copy 1 git worktree add ../app-hotfix hotfix/sev1 2 git worktree list 3 cd ../app-hotfix 4 # fix, commit, push... 5 cd - 6 git worktree remove ../app-hotfix 7 git worktree prune
sparse-checkout
Check out only part of a tree (monorepos). Cone mode is recommended.
Copy 1 git clone --filter=blob:none --sparse git@github.com:org/mono.git 2 cd mono 3 git sparse-checkout init --cone 4 git sparse-checkout set apps/web packages/ui 5 git sparse-checkout list 6 git sparse-checkout add packages/config
submodule
Nest another Git repo at a pinned commit. Heavy operational cost — prefer packages when possible.
Copy 1 git submodule add git@github.com:org/lib.git libs/lib 2 git submodule update --init --recursive 3 git submodule update --remote --merge 4 git submodule status 5 # clone with subs: 6 git clone --recurse-submodules git@github.com:org/app.git
LFS overview
Git Large File Storage replaces big binaries with pointer files. See Git LFS .
Copy 1 git lfs install 2 git lfs track "*.psd" 3 git lfs track "*.mp4" 4 git add .gitattributes 5 git add design.psd 6 git commit -m "chore: track PSD with LFS" 7 git lfs ls-files 8 git lfs migrate import --include="*.psd" --everything
Plumbing Quick Reference
Useful when explaining objects or recovering manually. Full story: Internals .
Command Purpose git hash-object -w file Create blob git cat-file -p oid Pretty-print object git ls-files -s Show index entries git write-tree Tree from index git commit-tree Commit from tree git update-ref Move a ref git rev-list --objects List reachable objects git verify-pack -v Inspect packfile
Copy 1 echo 'hello' > /tmp/hello.txt 2 BLOB=$(git hash-object -w /tmp/hello.txt) 3 git cat-file -t $BLOB 4 git cat-file -p $BLOB 5 git rev-parse HEAD^{tree} 6 git ls-tree -r HEAD | head
Daily Driver Cheat Sheet
Copy 1 git status -sb 2 git add -p 3 git commit -m "type(scope): summary" 4 git fetch origin --prune 5 git rebase origin/main 6 git push -u origin HEAD 7 git switch -c feature/x 8 git restore --staged PATH 9 git log --oneline --graph --decorate -15 10 git diff main...HEAD
✓ best practice
Memorize the daily driver; look up rare flags. Depth comes from
mastery stages , not from knowing every option.
Useful Environment Variables
Environment variables change Git behavior for a single command or shell session.
Copy 1 GIT_AUTHOR_NAME="Bot" 2 GIT_AUTHOR_EMAIL="bot@example.com" 3 GIT_SEQUENCE_EDITOR=: 4 GIT_EDITOR=true 5 GIT_TRACE=1 6 GIT_LFS_SKIP_SMUDGE=1
Pathspecs
Limit commands to subsets of the tree with pathspecs — including magic signatures.
Copy 1 git add -- '*.ts' 2 git log -- ':(exclude)vendor' -- . 3 git grep -n 'TODO' -- ':!dist' ':!node_modules' 4 git reset -- 'src/**/*.test.ts'
Exit Codes & Scripting
Copy 1 git diff --quiet || echo "dirty" 2 git diff --cached --quiet || echo "staged changes" 3 git merge-base --is-ancestor abc123 main && echo "already in main"
Undo Operations Matrix
Uncommitted file edits → git restore Unstage → git restore --staged Local commit → git reset --soft/--mixed Published commit → git revert Lost tip → git reflog + reset/branch Merge in progress → git merge --abort Rebase in progress → git rebase --abort Daily Recipes
Start a feature
recipe-feature.sh wrap Bash
Copy 1 git fetch origin 2 git switch -c feature/x origin/main 3 git add -p && git commit -m "feat(x): ..." 4 git push -u origin HEAD 5 gh pr create --fill
Update feature onto main Copy 1 git fetch origin 2 git rebase origin/main 3 git push --force-with-lease
Hotfix with worktree Copy 1 git worktree add ../hotfix -b hotfix/sev1 origin/main 2 cd ../hotfix 3 # fix + test + PR 4 git push -u origin HEAD 5 gh pr create --fill 6 cd - && git worktree remove ../hotfix
Safe undo on main Copy 1 git revert HEAD --no-edit 2 git push 3 # Never: git reset --hard HEAD~1 && git push --force origin main
Extended Practice Lab
Chain many porcelain commands in a disposable lab.
Copy 1 #!/usr/bin/env bash 2 set -euo pipefail 3 LAB=/tmp/forgelearn-cmd-lab 4 rm -rf "$LAB" && mkdir -p "$LAB" && cd "$LAB" 5 git init -b main 6 git config user.email a@b.c && git config user.name Lab 7 echo x > f && git add f && git commit -m "a" 8 git switch -c feature 9 echo y > f && git commit -am "b" 10 git switch main 11 git merge --no-ff feature -m "merge" 12 git log --oneline --graph 13 git rev-parse HEAD^{tree} 14 git cat-file -p HEAD | head 15 echo OK
Hooks Quick Commands
Full guide: Hooks . Common entry points:
Copy 1 ls .git/hooks 2 chmod +x .git/hooks/pre-commit 3 git config core.hooksPath .githooks 4 # sample pre-commit 5 cat > .githooks/pre-commit <<'EOF' 6 #!/usr/bin/env bash 7 git diff --cached --name-only | grep -E '\.env$' && exit 1 8 exit 0 9 EOF 10 chmod +x .githooks/pre-commit
Maintenance Commands
Copy 1 git maintenance run 2 git maintenance start 3 git gc --auto 4 git prune 5 git remote prune origin 6 git fetch --prune 7 git count-objects -vH 8 git fsck --full | head
Quick Glossary
HEAD — pointer to current commit (usually via branch) index/staging area — next commit snapshot fast-forward — move branch tip without merge commit detached HEAD — HEAD points at commit, not branch upstream — remote tracking branch for push/pull reflog — local history of tip movements OID — object id (hash) porcelain vs plumbing — user UI vs low-level commands ℹ info
Continue with
Internals for object model detail.