git diff
Unstaged changes — working tree vs index
git diff --staged
Staged changes — index vs last commit (what you're about to commit)
git diff HEAD~1
# HEAD vs one commit back
Compare current HEAD to its parent
git diff main..feature
Compare tips of two branches
git diff HEAD~3..HEAD --stat
Summary of files changed over last 3 commits
git restore file.txt
Discard unstaged changes to a file
git restore --staged file.txt
Unstage a file (keep changes in working tree)
git revert HEAD
# creates a new "undo" commit — safe for shared branches
Safe. Adds a commit that reverses the last one
git reset --soft HEAD~1
# undo commit, keep changes staged
git reset --mixed HEAD~1
# undo commit + unstage (default)
git reset --hard HEAD~1
# ⚠ wipe commit + all changes
Rewrites history. Avoid on shared branches
git switch -c new-feature
# create + switch (modern)
git branch -d old-branch
# safe delete (only if merged)
git branch -D old-branch
# force delete
git branch -m old-name new-name
Rename a local branch
git branch -vv
# shows tracking remotes + ahead/behind
git stash push -m "wip: refactor auth"
Save dirty state with a label
git stash push -u
# include untracked files
git stash list
git stash show -p stash@{1}
# show diff of a specific stash
git stash pop # apply + drop
git stash apply stash@{2} # apply, keep stash
git stash drop stash@{0} # delete one
git fetch --prune
# fetch + remove stale remote-tracking branches
git pull --rebase
# rebase local commits on top of upstream (cleaner log)
git push -u origin HEAD
# push + set upstream for current branch
git push origin --delete old-branch
Delete a remote branch
git rebase main
# replay current branch on top of main
git rebase -i HEAD~4
# interactive: squash / reorder / edit last 4 commits
Opens editor with pick / squash / fixup / reword / drop
git rebase --continue # after fixing conflict
git rebase --abort # bail out entirely
git log --oneline --graph --decorate --all
# visual branch topology
git log -p --follow -- path/to/file
# full diff history for a file
git log --author="Alice" --since="2 weeks ago"
git show abc1234
# diff + metadata for a specific commit
git blame -L 10,25 src/app.js
# who changed lines 10–25
git log --diff-filter=D --summary
# find deleted files across history
git cherry-pick abc1234
# apply a single commit to current branch
git cherry-pick abc1234..def5678
# apply a range of commits
git cherry-pick -n abc1234
# apply changes without committing (stage only)
git grep "TODO" --count
# search working tree, show match counts per file
git log -S "functionName" --oneline
# pickaxe: commits that added/removed a string
git bisect start
git bisect bad # current = broken
git bisect good v1.2.0 # known good tag
# git checks out midpoint — test, then:
git bisect good | bad # repeat until found
git bisect reset
Binary-search history to find a regression
git tag -a v2.0.0 -m "Release 2.0"
# annotated tag (preferred for releases)
git push origin --tags
git push origin v2.0.0 # push one tag
git tag -d v2.0.0
git push origin --delete v2.0.0
Delete tag locally and on remote
git worktree add ../hotfix hotfix/login
# check out a branch in a separate directory
# work on two branches simultaneously
git worktree list
See all linked working trees
git worktree remove ../hotfix
git config --global alias.st "status -sb"
git config --global alias.lg "log --oneline --graph --decorate --all"
git config --global alias.undo "reset --soft HEAD~1"
Add these to ~/.gitconfig under [alias]
git config --global pull.rebase true
# always rebase on pull (recommended)
git config --global push.autoSetupRemote true
# auto -u on first push