Git Cheat Sheet
Git cheatsheet for advanced Git commands and workflows, including staging, commits, branches, merge and rebase operations, remote synchronization, history inspection, recovery tools, multi-worktree usage, and debugging with bisect.
git init
Initialize a new Git repository in the current directory by creating a .git directory that stores repository metadata.
git init [<directory>]
$ mkdir demo && cd demo
$ git init
Initialized empty Git repository in /path/demo/.git/
git clone
Create a local copy of an existing repository from a URL, including remote configuration.
git clone <url> [<directory>]
$ git clone https://example.com/repo.git repo
Cloning into 'repo'...
remote: Enumerating objects: 120, done.
Receiving objects: 100% (120/120), 42.15 KiB | 1.23 MiB/s, done.
Resolving deltas: 100% (38/38), done.
git status
Show the state of the working tree and staging area (index), including staged changes, unstaged changes, and untracked files.
git status [-sb]
$ git status -sb
## main...origin/main
M src/app.py
A docs/notes.md
?? tmp/debug.log
git add
Add content to the index (stage changes). Supports adding files, directories, and interactive/patch staging.
git add <pathspec>...
git add -A
git add -p [<pathspec>...]
git add -N <pathspec>...
$ git add -p src/app.py
diff --git a/src/app.py b/src/app.py
@@
-stage = "dev"
+stage = "prod"
Stage this hunk [y,n,q,a,d,e,?]? y
$ git add -N README.md
$ git status -sb
## main
M src/app.py
A README.md
git reset
Move the current branch tip (HEAD) and optionally update the index and working tree, depending on the mode.
git reset [--soft|--mixed|--hard] <commit>
git reset <pathspec>...
$ git reset --mixed HEAD~1
Unstaged changes after reset:
M src/app.py
$ git reset README.md
Unstaged changes after reset:
M README.md
git restore
Restore files in the working tree and/or index from a specified source (commit/tree), supporting partial/patch restore.
git restore <pathspec>...
git restore --staged <pathspec>...
git restore --source <tree-ish> <pathspec>...
git restore -p <pathspec>...
$ git restore --staged docs/notes.md
$ git restore --source HEAD~1 src/app.py
$ git status -sb
## main
M src/app.py
git rm
Remove files from the working tree and index (or from the index only with --cached).
git rm <pathspec>...
git rm --cached <pathspec>...
$ git rm tmp/debug.log
rm 'tmp/debug.log'
$ git rm --cached .env
rm '.env'
$ git status -sb
## main
D tmp/debug.log
D .env
git mv
Move or rename a file and stage the change as a single operation.
git mv <source>... <destination>
$ git mv src/old_name.py src/new_name.py
$ git status -sb
## main
R src/old_name.py -> src/new_name.py
git commit
Create a new commit object from staged changes; --amend replaces the tip commit.
git commit
git commit -m "<message>"
git commit -am "<message>"
git commit --amend [--no-edit]
$ git commit -m "Add initial API skeleton"
[main 3e887ab] Add initial API skeleton
3 files changed, 120 insertions(+)
$ git commit --amend -m "Add API skeleton and routes"
[main 9c2fd10] Add API skeleton and routes
Date: Wed Dec 24 23:10:00 2025 +0300
3 files changed, 120 insertions(+)
git log
Inspect commit history with optional formatting, graph display, and path filtering.
git log
git log --oneline --decorate --graph --all
git log -- <path>
git log --follow <path>
git log -G <regex>
$ git log --oneline --decorate --graph --all -n 5
* 9c2fd10 (HEAD -> main) Add API skeleton and routes
* 14ab2e1 Add docs scaffold
* 1f2a9a7 Initial commit
$ git log --follow --oneline src/new_name.py
7a9b2b0 Rename module
1f2a9a7 Initial commit
git show
Show a commit, tag, tree, or blob in a human-readable form (diff and metadata).
git show <object>
git show <object>:<path>
git show --stat <object>
$ git show --stat HEAD
commit 9c2fd10...
Author: ...
Date: ...
src/app.py | 48 +++++++++++++++++++++++
src/routes.py | 64 ++++++++++++++++++++++++++++++
2 files changed, 112 insertions(+)
$ git show HEAD:README.md
# Project Title
...
git diff
Compare changes between the working tree, index, and commits; supports staged-only diffs.
git diff
git diff --staged
git diff <commit> <commit>
git diff <commit> -- <path>
git diff <commit> --stat
$ git diff --staged
diff --git a/src/app.py b/src/app.py
index 2f3a2e1..6d1e7a0 100644
--- a/src/app.py
+++ b/src/app.py
@@ -1,3 +1,4 @@
+from routes import router
Commit references
Refer to specific commits using branch names, tags, commit IDs, remote-tracking branches, and HEAD ancestry selectors.
# Examples of <commit> values
main
v1.0.0
3e887ab
origin/main
HEAD
HEAD~3
HEAD^^^
$ git show HEAD~2
commit 14ab2e1...
Author: ...
Date: ...
...
git branch
List, create, delete, and sort local branches; display the current branch with *.
git branch
git branch <name>
git branch --sort=-committerdate
git branch -d <name>
git branch -D <name>
$ git branch --sort=-committerdate
* main
feature/api
hotfix/login
$ git branch -d hotfix/login
Deleted branch hotfix/login (was 1a2b3c4).
git switch
Switch to a specified branch; can create a new branch with -c and detach with --detach.
git switch <name>
git switch -c <new-branch> [<start-point>]
git switch --detach <commit>
$ git switch -c feature/auth
Switched to a new branch 'feature/auth'
$ git switch main
Switched to branch 'main'
$ git switch --detach HEAD~1
HEAD is now at 14ab2e1 Add docs scaffold
git checkout
Switch branches or restore paths, depending on arguments; can check out a path from a specific commit.
git checkout <branch>
git checkout -b <new-branch> [<start-point>]
git checkout <commit> -- <pathspec>...
git checkout -- <pathspec>...
$ git checkout -b feature/search
Switched to a new branch 'feature/search'
$ git checkout HEAD~2 -- src/app.py
$ git status -sb
## feature/search
M src/app.py
git merge
Integrate commits from another branch into the current branch; may create a merge commit or fast-forward.
git merge <branch>
git merge --no-ff <branch>
git merge --ff-only <branch>
git merge --squash <branch>
$ git switch main
$ git merge feature/auth
Merge made by the 'ort' strategy.
src/auth.py | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 85 insertions(+)
$ git merge --ff-only feature/search
Updating 9c2fd10..c1d2e3f
Fast-forward
src/search.py | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
Merge diagram
Represent a merge commit that combines two diverged histories into one commit with two parents.
A---B---C main
\
D---E banana
A---B---C---◇ main
\ /
D---E banana
git rebase
Reapply commits from the current branch onto another base commit, rewriting commit IDs; interactive mode edits/squashes commits.
git rebase <upstream>
git rebase -i <upstream>
git rebase --onto <newbase> <upstream> [<branch>]
git rebase --continue
git rebase --abort
$ git switch banana
$ git rebase main
Successfully rebased and updated refs/heads/banana.
$ git rebase -i HEAD~6
# Editor opens with a list of commits:
# pick 1a2b3c4 Add feature A
# pick 2b3c4d5 Fix tests
# pick 3c4d5e6 Refactor
Rebase diagram
Represent a rebase of a diverged branch onto the tip of another branch, producing rewritten commits.
A---B---C main
D---E banana
A---B---C main
D'---E' banana
Squash merge diagram
Represent a squash merge where multiple commits from a branch are combined into a single commit on the target branch.
A---B---C main
D---E banana
A---B---C---S main
D---E banana
Fast-forward merge diagram
Represent a fast-forward merge where the target branch pointer moves forward without creating a merge commit.
A---B---C---D---E
main banana
A---B---C---D---E
main
banana
git cherry-pick
Apply a specific commit (or range) onto the current branch as a new commit with a new ID.
git cherry-pick <commit>
git cherry-pick <commit>^..<commit>
git cherry-pick --continue
git cherry-pick --abort
$ git switch main
$ git cherry-pick 7f3a2c1
[main 4d5e6f7] Fix login redirect
Date: Wed Dec 24 23:18:00 2025 +0300
1 file changed, 5 insertions(+), 2 deletions(-)
Cherry-pick diagram
Represent copying a commit from one branch onto another as a new commit.
A---B---C main
D---E
A---B---C---D' main
D---E
git stash
Temporarily store changes (tracked files) from the working directory and index; apply or pop later.
git stash
git stash push -m "<message>" [--] [<pathspec>...]
git stash list
git stash show -p stash@{<n>}
git stash apply [stash@{<n>}]
git stash pop [stash@{<n>}]
git stash drop [stash@{<n>}]
git stash clear
$ git stash push -m "WIP: auth form"
Saved working directory and index state WIP on feature/auth: 9c2fd10 Add API skeleton and routes
$ git stash list
stash@{0}: On feature/auth: WIP: auth form
$ git stash pop
On branch feature/auth
Changes to be committed:
modified: src/auth.py
Dropped refs/stash@{0} (a1b2c3d4e5f6...)
git clean
Remove untracked files and directories from the working tree; supports dry-run with -n.
git clean -n
git clean -f
git clean -fd
$ git clean -n
Would remove tmp/
Would remove build/
$ git clean -fd
Removing tmp/
Removing build/
git reflog
Show the history of where branch tips and HEAD have been, enabling recovery of commits after resets/rebases.
git reflog
git reflog <ref>
$ git reflog -n 5
9c2fd10 HEAD@{0}: commit (amend): Add API skeleton and routes
3e887ab HEAD@{1}: commit: Add initial API skeleton
14ab2e1 HEAD@{2}: checkout: moving from main to feature/auth
1f2a9a7 HEAD@{3}: commit (initial): Initial commit
git revert
Create a new commit that reverses the changes introduced by an earlier commit; does not rewrite history.
git revert <commit>
git revert <commit>^..<commit>
git revert --no-commit <commit>
$ git revert 4d5e6f7
[main 8a9b0c1] Revert "Fix login redirect"
1 file changed, 2 insertions(+), 5 deletions(-)
git tag
Create, list, and push tags; annotated tags store metadata and messages.
git tag
git tag <name> [<commit>]
git tag -a <name> -m "<message>" [<commit>]
git show <tag>
$ git tag -a v1.2.0 -m "Release 1.2.0"
$ git tag
v1.2.0
$ git show v1.2.0
tag v1.2.0
Tagger: ...
Release 1.2.0
commit 9c2fd10...
...
git remote
Manage remote names and URLs; list remotes and show detailed remote info.
git remote -v
git remote add <name> <url>
git remote set-url <name> <newurl>
git remote remove <name>
git remote show <name>
$ git remote -v
origin https://example.com/repo.git (fetch)
origin https://example.com/repo.git (push)
$ git remote add upstream https://example.com/upstream.git
$ git remote -v
origin https://example.com/repo.git (fetch)
upstream https://example.com/upstream.git (fetch)
git fetch
Download objects and refs from a remote without changing local branches; updates remote-tracking branches.
git fetch <remote>
git fetch <remote> <refspec>
git fetch --all
$ git fetch origin
remote: Enumerating objects: 15, done.
From https://example.com/repo
9c2fd10..c1d2e3f main -> origin/main
git pull
Fetch from a remote and integrate into the current branch (merge by default; rebase with --rebase).
git pull
git pull <remote> <branch>
git pull --rebase
$ git pull --rebase
Successfully rebased and updated refs/heads/main.
git push
Upload local refs and objects to a remote; set upstream with -u; push tags; force-update with lease.
git push
git push <remote> <branch>
git push -u <remote> <branch>
git push --tags
git push --force-with-lease
$ git push -u origin feature/auth
Enumerating objects: 9, done.
Writing objects: 100% (9/9), 1.22 KiB | 1.22 MiB/s, done.
To https://example.com/repo.git
* [new branch] feature/auth -> feature/auth
branch 'feature/auth' set up to track 'origin/feature/auth'.
$ git push --force-with-lease
To https://example.com/repo.git
+ 1a2b3c4...9c2fd10 main -> main (forced update)
git config
Read and write configuration values at system, global, and local scopes; list effective config with --list.
git config --list
git config <name>
git config <name> <value>
git config --global <name> <value>
git config --local <name> <value>
git config --unset <name>
$ git config --global user.name "Example User"
$ git config --global user.email "user@example.com"
$ git config --global color.ui auto
$ git config --list | head -n 5
user.name=Example User
user.email=user@example.com
color.ui=auto
...
git blame
Show the commit and author metadata for each line of a file, enabling line-level history tracking.
git blame <path>
git blame -L <start>,<end> <path>
$ git blame -L 1,6 src/app.py
^1f2a9a7 (Example User 2025-12-20 12:00:00 +0300 1) import os
14ab2e1a (Example User 2025-12-23 18:05:00 +0300 2) from routes import router
...
git bisect
Use a binary search over history to identify a commit that introduced a change by marking tested commits as “good/old” or “bad/new”.
git bisect start
git bisect bad [<rev>]
git bisect good [<rev>...]
git bisect old [<rev>...]
git bisect new [<rev>]
git bisect run <cmd>...
git bisect reset [<commit>]
$ git bisect start
$ git bisect bad HEAD
$ git bisect good v1.1.0
Bisecting: 12 revisions left to test after this (roughly 4 steps)
[2b3c4d5e6f...] Add caching layer
$ ./run_tests.sh
FAIL
$ git bisect bad
Bisecting: 6 revisions left to test after this (roughly 3 steps)
[3c4d5e6f70...] Refactor auth
$ git bisect run ./run_tests.sh
...
3c4d5e6f70... is the first bad commit
commit 3c4d5e6f70...
Author: ...
Date: ...
Refactor auth
$ git bisect reset
git worktree
Manage multiple working trees attached to one repository so multiple branches can be checked out simultaneously.
git worktree list
git worktree add <path> [<branch>]
git worktree add -b <new-branch> <path> [<start-point>]
git worktree remove <path>
git worktree prune
$ git worktree list
/path/repo 9c2fd10 [main]
$ git worktree add ../repo-hotfix -b hotfix/login
Preparing worktree (new branch 'hotfix/login')
HEAD is now at 9c2fd10 Add API skeleton and routes
$ git worktree list
/path/repo 9c2fd10 [main]
/path/repo-hotfix 9c2fd10 [hotfix/login]
git submodule
Embed another Git repository at a specific path by recording its commit; initialize and update submodules.
git submodule add <url> <path>
git submodule init
git submodule update
git submodule update --init --recursive
git submodule status
$ git submodule add https://example.com/lib.git vendor/lib
Cloning into '/path/repo/vendor/lib'...
$ git submodule status
1a2b3c4d5e6f vendor/lib (heads/main)
$ git submodule update --init --recursive
Submodule path 'vendor/lib': checked out '1a2b3c4d5e6f...'
git range-diff
Compare two ranges of commits (commonly used to compare different versions of a series, e.g., before/after rebase).
git range-diff <old-range> <new-range>
git range-diff <base>..<tip1> <base>..<tip2>
$ git range-diff main..feature/auth main..feature/auth-v2
1: 1a2b3c4 Add login form = 1: 7e8f9a0 Add login form
2: 2b3c4d5 Fix tests ! 2: 8f9a0b1 Fix tests (updated)
3: 3c4d5e6 Refactor auth < -: -: - (dropped)
-: -: - 3: 9a0b1c2 Refactor auth (split)
git describe
Create a human-readable name for a commit based on the closest reachable tag.
git describe
git describe --tags
git describe --tags --dirty --always
$ git describe --tags --dirty --always
v1.2.0-3-g9c2fd10-dirty
git rev-parse
Resolve revisions and show Git-derived paths (useful for scripting and inspection).
git rev-parse HEAD
git rev-parse --short HEAD
git rev-parse --show-toplevel
git rev-parse --abbrev-ref HEAD
$ git rev-parse --abbrev-ref HEAD
main
$ git rev-parse --short HEAD
9c2fd10
$ git rev-parse --show-toplevel
/path/repo
git ls-remote
List references (branches/tags) available on a remote without cloning.
git ls-remote <url>
git ls-remote --heads <url>
git ls-remote --tags <url>
$ git ls-remote --heads https://example.com/repo.git
c1d2e3f4a5b6 refs/heads/main
7e8f9a0b1c2d refs/heads/feature/auth
git ls-files
List files tracked by Git; show staged files and optional flags for ignored/untracked status.
git ls-files
git ls-files --stage
git ls-files --others --exclude-standard
$ git ls-files --stage | head -n 3
100644 6d1e7a0d... 0 README.md
100644 2f3a2e1b... 0 src/app.py
100644 9ab0c1d2... 0 docs/notes.md
.gitignore patterns
Define ignore patterns to prevent unintentional staging of files; patterns can include globs and directory matches.
# In .gitignore
logs/
*.log
*.tmp
build/
.cache/
$ printf "logs/\n*.log\n*.tmp\n" >> .gitignore
$ git status -sb
## main
?? .gitignore
Git paths for configuration files
Git configuration is stored at repository, user, and system scopes; repository-specific config is under .git/config.
.git/config
~/.gitconfig
/etc/gitconfig