Skip to content

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