Git Cheat Sheet

A concise, visual Git command reference

Everyday

Getting Started

Set your name & email

git config --global user.name "Your Name"
git config --global user.email "you@example.com"

Without --global, the setting applies only to the current repo.

Initialize a new repo

git init

Clone an existing repo

git clone <url>
git clone <url> <directory>

Set default branch name

git config --global init.defaultBranch main

Making Changes

Show working tree status

git status

Stage files

git add <file>
git add .

Stage hunks interactively

git add -p

Unstage a file (keep changes)

git restore --staged <file>

Commit staged changes

git commit -m "message"

Stage & commit all tracked files

Skips git add for files Git already tracks. Does not add new untracked files.

git commit -am "message"

Move, rename, or delete

git mv <old> <new>
git rm <file>
git rm --cached <file>

--cached untracks without deleting the file.

Stashing

Stash changes

Saves uncommitted changes and reverts the working directory. Useful for switching branches without committing.

git stash

List stashes

git stash list

Restore & delete most recent stash

git stash pop

Restore but keep the stash

git stash apply

Drop a specific stash

git stash drop stash@{n}

Branching

List branches

git branch
git branch --sort=-committerdate

Create a branch

git branch <name>

Switch to a branch

git switch <name>

Create & switch

git switch -c <name>

Delete a branch (safe)

Fails if the branch has unmerged changes.

git branch -d <name>

Delete a branch (force)

git branch -D <name>

Check out a specific commit

Creates a detached HEAD — you’re not on any branch.

git checkout <commit>

To start a branch from that point:

git switch -c <name> <commit>

Inspect & Sync

Viewing Changes

Show unstaged changes

git diff

Show staged changes

git diff --staged

Show all changes (staged + unstaged)

git diff HEAD

Compare two branches

git diff main..feature

Diff a file since a commit

git diff <commit> -- <file>

Summary of changes

git diff <commit> --stat

Show a specific commit

git show <commit>

Diff two commits

git diff <commit1> <commit2>

History & Blame

Show commit history

git log --oneline

History with graph

git log --oneline --graph --all

Commits that modified a file

git log <file>

Follow file through renames

git log --follow <file>

Find commits that added or removed text

git log -G "pattern"

Who last changed each line

git blame <file>

Push & Pull

Push to remote

git push origin main

Push & set upstream tracking

Links local branch to remote so future push/pull work without arguments.

git push -u origin <branch>

Force push (safe)

Fails if someone else pushed first.

git push --force-with-lease

Fetch changes (don’t merge)

git fetch origin

Fetch & prune deleted remote branches

git fetch --prune

Pull (fetch + merge)

git pull

Pull with rebase

git pull --rebase

Remote Setup

Add a remote

git remote add <name> <url>

List remotes

git remote -v

Rename / remove a remote

git remote rename <old> <new>
git remote remove <name>

Show remote details

git remote show origin

See which branch tracks which remote

git branch -vv

Set upstream for existing branch

git branch -u origin/<branch>

List / check out remote branches

git branch -r
git switch <remote-branch>

Delete a remote branch

git push origin --delete <branch>

Integrate

Merging

Merge a branch into current

Creates a merge commit that joins both histories.

git merge <branch>
gitGraph commit id: "A" commit id: "B" branch feature commit id: "C" commit id: "D" checkout main commit id: "E" merge feature id: "M (merge)"

Fast-forward merge

When main has no new commits, the pointer moves forward. No merge commit needed.

gitGraph commit id: "A" commit id: "B" branch feature commit id: "C" commit id: "D" checkout main merge feature id: " " tag: "main fast-forwards"

Squash merge

Combines all branch commits into one on the target.

git merge --squash <branch>
git commit -m "message"

Rebasing

Rebase current branch onto another

Replays your commits on top of the target, creating linear history. Rewrites commit hashes.

git switch feature
git rebase main

Before — branches have diverged:

%%{init: { 'gitGraph': {'showCommitLabel': true}} }%% gitGraph commit id: "A" commit id: "B" branch feature commit id: "C" commit id: "D" checkout main commit id: "E"

After git rebase main — linear history:

%%{init: { 'gitGraph': {'showCommitLabel': true}} }%% gitGraph commit id: "A" commit id: "B" commit id: "E" commit id: "C'" commit id: "D'"

Interactive rebase (last N commits)

Squash, reorder, edit, or drop commits.

git rebase -i HEAD~<n>

Verbs: pick keep, squash meld into previous, fixup meld & discard message, reword change message, edit pause to amend, drop remove.

After rebase, force push to update remote

git push --force-with-lease

Cherry-Pick & Tags

Cherry-pick a commit

Copies a single commit onto the current branch.

git cherry-pick <commit>
%%{init: { 'gitGraph': {'showCommitLabel': true}} }%% gitGraph commit id: "A" commit id: "B" branch feature commit id: "C" commit id: "D" checkout main commit id: "E" cherry-pick id: "D"

Create a tag

git tag <name>

Create an annotated tag

git tag -a <name> -m "message"

Push tags to remote

git push --tags

Resolving Conflicts

When do conflicts happen?

When two branches change the same lines, or one deletes a file the other modified.

Conflict markers

<<<<<<< HEAD
your changes
=======
their changes
>>>>>>> feature-branch

Edit the file to keep the correct code, then remove all markers.

After resolving, stage & continue

git add <file>
git merge --continue
git rebase --continue
git cherry-pick --continue

Abort & go back

git merge --abort
git rebase --abort
git cherry-pick --abort

Accept all of theirs or ours

git checkout --theirs <file> && git add <file>
git checkout --ours <file> && git add <file>

Fix Mistakes

Undoing Local Changes

Discard unstaged changes to a file

git restore <file>

Discard all staged & unstaged changes to a file

git restore --staged --worktree <file>

Discard all unstaged changes

git restore .

Discard everything (staged + unstaged)

git reset --hard

Delete untracked files

Preview first with -n, then run with -f.

git clean -n
git clean -f

Reverting Commits

Revert a commit

Creates a new undo commit. Safe for shared branches — doesn’t rewrite history.

git revert <commit>

Before — C introduced a bug:

%%{init: { 'gitGraph': {'showCommitLabel': true}} }%% gitGraph commit id: "A" commit id: "B" commit id: "C" type: REVERSE

After git revert C — bug undone, history preserved:

%%{init: { 'gitGraph': {'showCommitLabel': true}} }%% gitGraph commit id: "A" commit id: "B" commit id: "C" type: REVERSE commit id: "Revert C"

Revert without auto-committing

git revert --no-commit <commit>

Revert a merge commit

-m 1 keeps the first parent (the branch you merged into).

git revert -m 1 <merge-commit>

Revert a range of commits

git revert <oldest>^..<newest>

Rewriting History

Amend last commit message

git commit --amend -m "new message"

Add forgotten files to last commit

git add <file>
git commit --amend --no-edit

Undo last commit, keep changes staged

git reset --soft HEAD~1

Undo last commit, keep changes unstaged

git reset HEAD~1

Undo last commit, discard changes

git reset --hard HEAD~1

Restore a file from another commit

git restore <file> --source <commit>

Recover lost commits

reflog shows everywhere HEAD has pointed.

git reflog
git reset --hard <commit>

Commit References

By name, tag, or hash

main, feature/login, v1.0, 3e887ab, origin/main

HEAD — current commit

HEAD

~ walks back linearly

HEAD~1    # one commit back
HEAD~3    # three commits back

^ picks a parent (for merges)

HEAD^     # first parent (same as HEAD~1)
HEAD^2    # second parent of a merge

Combine them

HEAD~2^2  # back 2, then second parent

Ranges

git log main..feature    # in feature, not main
git log main...feature   # in either, not both
%%{init: { 'gitGraph': {'showCommitLabel': true}} }%% gitGraph commit id: "HEAD~3" commit id: "HEAD~2" commit id: "HEAD~1 (HEAD^)" commit id: "HEAD"

Practices & Patterns

Naming & Messages

Branch naming conventions

Prefixes create logical grouping in tools and listings.

  • feature/<name> — new functionality
  • bugfix/<name> — fixing a bug
  • hotfix/<name> — urgent production fix
  • release/<name> — preparing a release
  • chore/<name> — maintenance, docs
git switch -c feature/user-login
git switch -c bugfix/null-pointer
git switch -c hotfix/security-patch

Commit message conventions

feat: add user authentication
fix: prevent null pointer on login
docs: update API reference
refactor: extract validation logic
test: add login unit tests
chore: update dependencies

Workflows

GitHub Flow (simple)

One long-lived branch. Features branch off, get reviewed via PR, merge back.

  1. git switch -c feature/thing from main
  2. Commit, push, open a pull request
  3. Review, then merge PR into main
  4. Deploy from main
gitGraph commit id: "A" commit id: "B" branch feature/login commit id: "C" commit id: "D" checkout main merge feature/login id: "PR merge" commit id: "deploy"

GitFlow (structured releases)

main for production, develop for integration.

  • feature/* → branches off & merges to develop
  • release/* → branches off develop, merges to main + develop
  • hotfix/* → branches off main, merges to main + develop

Trunk-based development

Everyone commits to main (or short-lived branches merged within a day). Relies on feature flags and CI.

Gitignore

Pattern syntax

*.log          # any .log file
build/         # directory named build
/TODO          # only root TODO, not sub/TODO
!important.log # negate: do track this file
**/debug       # match in any subdirectory
doc/*.txt      # doc/notes.txt but not doc/a/b.txt

Remove a tracked file from the repo

git rm --cached <file>

File stays on disk but leaves version control. Commit afterward.

Global ignore

git config --global \
  core.excludesFile ~/.gitignore_global

Check what rule is ignoring a file

git check-ignore -v <file>

.gitkeep convention

Git won’t track empty directories. Drop a .gitkeep inside to force-track them. This is a community convention, not a Git feature.

Reference

Config & Tools

Set your diff tool

git config --global diff.tool vscode
git config --global difftool.vscode.cmd \
  'code --wait --diff $LOCAL $REMOTE'

Set your merge tool

git config --global merge.tool vscode
git config --global mergetool.vscode.cmd \
  'code --wait $MERGED'

Create aliases

git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch

Set the default pager

git config --global core.pager 'less -FX'

Important files

  • .git/config — local repo config
  • ~/.gitconfig — global user config
  • .gitignore — files to exclude from tracking

Key Concepts

  • repository — a project folder tracked by Git with full change history
  • commit — a snapshot of staged changes with a descriptive message
  • branch — a movable pointer to a commit; isolates work
  • HEAD — pointer to your current commit (usually tip of a branch)
  • staging area — where you prepare changes before committing (git add)
  • working tree — the actual files on disk
  • remote — a repo hosted elsewhere (e.g. GitHub); origin is the default
  • tracking branch — local branch linked to a remote for easy push/pull
  • merge — combines two branches via a new commit
  • rebase — replays commits on another branch for linear history
  • fast-forward — merge where the pointer just moves forward (no new commit)
  • conflict — same lines changed on both sides; must resolve manually
  • stash — temporary shelf for uncommitted changes
  • tag — permanent label on a commit, typically for releases
  • reflog — log of everywhere HEAD has pointed; safety net for lost commits
  • cherry-pick — copy one commit onto another branch
  • revert — new commit that undoes a previous commit
  • reset — move HEAD to a different commit; can rewrite history