|$ curl https://forge-ai.dev/api/markdown?path=docs/git/commands-reference
$cat docs/git-commands-reference.md
updated Today·35-45 min read·published

Git Commands Reference

GitReferenceCommandsAll Levels🎯Free Tools
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.

KindExamplesAudience
Porcelainadd, commit, status, log, switch, merge, rebase, pushHumans & agents day-to-day
Plumbinghash-object, cat-file, update-index, write-tree, commit-tree, update-refInternals, recovery scripts
Machine porcelainstatus --porcelain=v1, log --pretty=format:CI parsers, tools
porcelain-machine.sh
Bash
1# Stable for scripts
2git status --porcelain=v1 -uall
3git diff --name-status --diff-filter=ACMR
4git log -1 --pretty=format:'%H %an %s'
5
6# Plumbing peek at an object
7git rev-parse HEAD
8git cat-file -t HEAD
9git cat-file -p HEAD | head
config

Read and write configuration at system, global, local, and worktree scopes. See Git Config for deep dive.

CommandPurpose
git config --global user.nameSet identity (required)
git config --list --show-originShow all keys with file source
git config --global -eEdit ~/.gitconfig
git config --unset keyRemove a key
git config --get-regexp aliasList aliases
config.sh
Bash
1git config --global user.name "Jane Doe"
2git config --global user.email "jane@example.com"
3git config --global init.defaultBranch main
4git config --global core.editor "code --wait"
5git config --global pull.rebase true
6git config --global fetch.prune true
7git config --list --show-origin | head -40
init / clone

Create new repositories or copy existing ones. Prefer clone when a remote already exists.

CommandPurpose
git init -b mainNew repo with main branch
git clone url dirCopy remote into dir
git clone --depth 1Shallow clone (CI)
git clone --filter=blob:nonePartial clone (blobs on demand)
git clone --recurse-submodulesInclude submodules
git clone --bareBare remote-style repo
init-clone.sh
Bash
1git init -b main
2git clone git@github.com:org/app.git
3git clone --depth 1 --branch main https://github.com/org/app.git app-ci
4git 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.

CommandPurpose
git status -sbShort branch + file status
git add pathStage file or directory
git add -pInteractive hunk staging
git add -uStage tracked modifications/deletes
git commit -m "msg"Create commit from index
git commit --amend --no-editAmend last (local only)
git commit --fixup HEAD~1Fixup for autosquash
git rm / git mvRemove / rename tracked paths
status-add-commit.sh
Bash
1git status -sb
2git add src/app.ts
3git add -p README.md
4git commit -m "feat(auth): add session refresh"
5git commit --amend --no-edit # only if not pushed
6git 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.

CommandPurpose
git log --oneline --graph --allVisual history
git log -S'symbol'Pickaxe: commits changing string
git log -p -1Patch for latest commit
git diffUnstaged vs index
git diff --stagedIndex vs HEAD
git diff main...HEADTriple-dot: changes on branch
git show HEAD:pathFile content at revision
log-diff.sh
Bash
1git log --oneline --graph --decorate -20
2git log --author='Jane' --since='2 weeks ago' --pretty=format:'%h %ad %s' --date=short
3git log -S'createHash' --oneline -- src/
4git diff main...HEAD --stat
5git diff --staged
6git show abc123 --stat
7git 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.

CommandPurpose
git branch -vvList local with upstream
git switch -c feature/xCreate and switch
git switch mainSwitch branch
git switch -Previous branch
git branch -d feature/xDelete merged branch
git branch -D feature/xForce delete
git checkout abc123 -- fileLegacy: restore file from rev
branch.sh
Bash
1git branch -vv
2git switch -c feature/login
3git switch main
4git branch --merged main
5git branch -d feature/login
6git push origin --delete feature/login
merge / rebase

Integrate histories. Merge preserves topology; rebase replays commits for linear history. See Merge and Rebasing.

CommandPurpose
git merge featureMerge into current branch
git merge --no-ff featureAlways create merge commit
git merge --abortAbort conflicted merge
git rebase mainReplay onto main
git rebase -i HEAD~5Interactive rewrite
git rebase --ontoAdvanced transplant
git rebase --abort / --continueConflict control
merge-rebase.sh
Bash
1git switch main
2git merge --no-ff feature/login -m "merge: feature/login"
3git switch feature/payments
4git fetch origin
5git rebase origin/main
6# conflict? fix files, then:
7git add -A && git rebase --continue
reset / restore / revert

Three different undo tools. Reset moves branch tip; restore fixes files; revert adds an inverse commit.

CommandPurpose
git reset --soft HEAD~1Undo commit, keep staged
git reset HEAD~1Mixed: undo commit, unstage
git reset --hard HEAD~1Destroy WD+index to tip
git restore fileDiscard WD changes
git restore --staged fileUnstage
git restore --source=HEAD~1 fileCheckout file from rev
git revert abc123New commit undoing abc123
git revert -m 1 mergeHashRevert a merge
undo.sh
Bash
1# Local unpublished: soft reset and recommit
2git reset --soft HEAD~1
3git commit -m "feat: better message"
4
5# Discard one file's uncommitted edits
6git restore src/buggy.ts
7
8# Public bugfix: revert
9git revert abc123 --no-edit
10git 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.

CommandPurpose
git stash push -m "wip"Save WD+index
git stash push -u -m "wip"Include untracked
git stash listShow stack
git stash show -p stash@{0}Show patch
git stash popApply and drop
git stash applyApply keep entry
git stash dropDelete entry
stash.sh
Bash
1git stash push -u -m "wip: login form"
2git switch main
3# hotfix...
4git switch -
5git stash pop
6git stash list
remote / fetch / pull / push

Synchronize with remotes. Fetch downloads; pull = fetch + integrate; push publishes.

CommandPurpose
git remote -vList remotes
git fetch --all --pruneUpdate remote-tracking
git pull --rebaseFetch + rebase
git push -u origin HEADPush and set upstream
git push --force-with-leaseSafer force push
git push origin :branchDelete remote branch
remote.sh
Bash
1git remote -v
2git fetch origin --prune
3git status -sb
4git pull --rebase origin main
5git push -u origin HEAD
6# Feature branch rewrite after rebase:
7git 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.

CommandPurpose
git tag -a v1.2.0 -m "..."Annotated tag
git tag -s v1.2.0Signed tag
git tag -l 'v*'List tags
git push origin v1.2.0Push one tag
git push origin --tagsPush all tags
git tag -d v1.2.0Delete local tag
tag.sh
Bash
1git tag -a v1.2.0 -m "Release 1.2.0"
2git show v1.2.0
3git push origin v1.2.0
4git tag -l 'v1.*' --sort=-v:refname
bisect

Binary search history to find the commit that introduced a bug. See Bisect.

bisect.sh
Bash
1git bisect start
2git bisect bad HEAD
3git bisect good v1.0.0
4# test, then:
5git bisect good # or: git bisect bad
6# automate:
7git bisect run npm test -- --runInBand
8git bisect reset
cherry-pick

Apply the changes from existing commits onto the current branch.

cherry-pick.sh
Bash
1git switch release/1.2
2git cherry-pick abc123
3git cherry-pick abc123 def456
4git cherry-pick -n abc123 # apply without committing
5git cherry-pick --abort
6git cherry-pick --continue
reflog

Local safety net of where HEAD and branches pointed. Primary recovery tool after destructive ops.

reflog.sh
Bash
1git reflog
2git reflog show main
3git reset --hard HEAD@{3}
4git 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.

worktree.sh
Bash
1git worktree add ../app-hotfix hotfix/sev1
2git worktree list
3cd ../app-hotfix
4# fix, commit, push...
5cd -
6git worktree remove ../app-hotfix
7git worktree prune
sparse-checkout

Check out only part of a tree (monorepos). Cone mode is recommended.

sparse.sh
Bash
1git clone --filter=blob:none --sparse git@github.com:org/mono.git
2cd mono
3git sparse-checkout init --cone
4git sparse-checkout set apps/web packages/ui
5git sparse-checkout list
6git sparse-checkout add packages/config
submodule

Nest another Git repo at a pinned commit. Heavy operational cost — prefer packages when possible.

submodule.sh
Bash
1git submodule add git@github.com:org/lib.git libs/lib
2git submodule update --init --recursive
3git submodule update --remote --merge
4git submodule status
5# clone with subs:
6git clone --recurse-submodules git@github.com:org/app.git
LFS overview

Git Large File Storage replaces big binaries with pointer files. See Git LFS.

lfs.sh
Bash
1git lfs install
2git lfs track "*.psd"
3git lfs track "*.mp4"
4git add .gitattributes
5git add design.psd
6git commit -m "chore: track PSD with LFS"
7git lfs ls-files
8git lfs migrate import --include="*.psd" --everything
Plumbing Quick Reference

Useful when explaining objects or recovering manually. Full story: Internals.

CommandPurpose
git hash-object -w fileCreate blob
git cat-file -p oidPretty-print object
git ls-files -sShow index entries
git write-treeTree from index
git commit-treeCommit from tree
git update-refMove a ref
git rev-list --objectsList reachable objects
git verify-pack -vInspect packfile
plumbing.sh
Bash
1echo 'hello' > /tmp/hello.txt
2BLOB=$(git hash-object -w /tmp/hello.txt)
3git cat-file -t $BLOB
4git cat-file -p $BLOB
5git rev-parse HEAD^{tree}
6git ls-tree -r HEAD | head
Daily Driver Cheat Sheet
daily.sh
Bash
1git status -sb
2git add -p
3git commit -m "type(scope): summary"
4git fetch origin --prune
5git rebase origin/main
6git push -u origin HEAD
7git switch -c feature/x
8git restore --staged PATH
9git log --oneline --graph --decorate -15
10git 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.

env.sh
Bash
1GIT_AUTHOR_NAME="Bot"
2GIT_AUTHOR_EMAIL="bot@example.com"
3GIT_SEQUENCE_EDITOR=:
4GIT_EDITOR=true
5GIT_TRACE=1
6GIT_LFS_SKIP_SMUDGE=1
Pretty Formats & Log Recipes
pretty.sh
Bash
1git log --pretty=format:'%h %ad %an %s' --date=short
2git log --pretty=fuller -1
3git shortlog -sn --all --no-merges
4git log --first-parent main
5git log --merges --oneline
6git log -G'todo' --oneline
7git log --follow -- path/renamed.ts

best practice

Machine-readable formats beat parsing human log output in CI scripts.
Pathspecs

Limit commands to subsets of the tree with pathspecs — including magic signatures.

pathspecs.sh
Bash
1git add -- '*.ts'
2git log -- ':(exclude)vendor' -- .
3git grep -n 'TODO' -- ':!dist' ':!node_modules'
4git reset -- 'src/**/*.test.ts'
Exit Codes & Scripting
scripting.sh
Bash
1git diff --quiet || echo "dirty"
2git diff --cached --quiet || echo "staged changes"
3git 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
Bash
1git fetch origin
2git switch -c feature/x origin/main
3git add -p && git commit -m "feat(x): ..."
4git push -u origin HEAD
5gh pr create --fill

Update feature onto main

recipe-update.sh
Bash
1git fetch origin
2git rebase origin/main
3git push --force-with-lease

Hotfix with worktree

recipe-hotfix.sh
Bash
1git worktree add ../hotfix -b hotfix/sev1 origin/main
2cd ../hotfix
3# fix + test + PR
4git push -u origin HEAD
5gh pr create --fill
6cd - && git worktree remove ../hotfix

Safe undo on main

recipe-undo.sh
Bash
1git revert HEAD --no-edit
2git push
3# Never: git reset --hard HEAD~1 && git push --force origin main
Extended Practice Lab

Chain many porcelain commands in a disposable lab.

deep-lab.sh
Bash
1#!/usr/bin/env bash
2set -euo pipefail
3LAB=/tmp/forgelearn-cmd-lab
4rm -rf "$LAB" && mkdir -p "$LAB" && cd "$LAB"
5git init -b main
6git config user.email a@b.c && git config user.name Lab
7echo x > f && git add f && git commit -m "a"
8git switch -c feature
9echo y > f && git commit -am "b"
10git switch main
11git merge --no-ff feature -m "merge"
12git log --oneline --graph
13git rev-parse HEAD^{tree}
14git cat-file -p HEAD | head
15echo OK
Hooks Quick Commands

Full guide: Hooks. Common entry points:

hooks.sh
Bash
1ls .git/hooks
2chmod +x .git/hooks/pre-commit
3git config core.hooksPath .githooks
4# sample pre-commit
5cat > .githooks/pre-commit <<'EOF'
6#!/usr/bin/env bash
7git diff --cached --name-only | grep -E '\.env$' && exit 1
8exit 0
9EOF
10chmod +x .githooks/pre-commit
Maintenance Commands
maintenance.sh
Bash
1git maintenance run
2git maintenance start
3git gc --auto
4git prune
5git remote prune origin
6git fetch --prune
7git count-objects -vH
8git 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.

Community

Get help on Slack, Discord or VIP

Stuck on a guide? Join the community and ask.