Git Cheat Sheet — The 25 Commands You Actually Use
The Git commands worth keeping in one tab — branching, undoing, rebasing, stashing, and the dangerous flags. Tables to skim, callouts for the traps.
Git has roughly 150 subcommands. You will use 25 of them weekly. This is those 25, plus the handful you reach for when something has already gone wrong.
Skim the tables. Read the callouts before running anything that ends in --force.
Setup & status
| Command | What it does |
|---|---|
git config --global user.name "Name" | Set your name on every commit you author |
git config --global user.email "you@example.com" | Set your email on every commit |
git config --global init.defaultBranch main | Stop creating master branches in 2026 |
git config --global pull.rebase true | git pull rebases instead of merging — flatter history |
git status -sb | Short branch + status, the only git status worth typing |
git log --oneline --graph --decorate -20 | Last 20 commits, graphed, with branch/tag labels |
Branching
| Command | What it does |
|---|---|
git switch -c feature/x | Create + switch to feature/x (the modern checkout -b) |
git switch main | Switch back to main (no -b) |
git branch -vv | List local branches with tracking + last commit |
git branch -d feature/x | Delete a merged branch (refuses if unmerged) |
git branch -D feature/x | Force-delete an unmerged branch |
git branch --merged main | Branches already merged into main — safe to delete |
git push -u origin feature/x | Push and start tracking; future push/pull need no args |
Committing
| Command | What it does |
|---|---|
git add -p | Interactively stage hunks — review what you’re committing |
git commit -m "msg" | Commit staged changes |
git commit -am "msg" | Stage all tracked changes and commit (skips untracked files) |
git commit --amend | Rewrite the last commit (message and/or staged changes) |
git commit --amend --no-edit | Add staged changes to the last commit, keep the message |
git commit --fixup <sha> | Mark a commit as a fix to be squashed during rebase |
--amend only rewrites the last commit. If you’ve already pushed it, amending forces a non-fast-forward push later — fine on personal branches, dangerous on shared ones. Default to a new commit unless you’re certain no one else has the old SHA.
Undo — the section everyone searches for
| Situation | Command |
|---|---|
| Unstage a file but keep edits | git restore --staged <file> |
| Discard unstaged changes to a file | git restore <file> |
| Discard all unstaged changes | git restore . |
| Move HEAD back N commits, keep changes staged | git reset --soft HEAD~N |
| Move HEAD back, keep changes unstaged | git reset HEAD~N (default --mixed) |
| Move HEAD back and throw away changes | git reset --hard HEAD~N |
| Undo a pushed commit safely (new commit) | git revert <sha> |
| Recover a “lost” commit by SHA | git reflog → git reset --hard <sha> |
git reflog is the safety net. Every reset, rebase, amend, and merge leaves a record there for ~90 days. If you panic-deleted a branch or lost commits to a bad reset, reflog has the SHA.
Remote
| Command | What it does |
|---|---|
git remote -v | List remotes |
git fetch | Update all remote-tracking refs (no merge) |
git fetch --prune | Also delete local refs for remote branches that are gone |
git pull | fetch + merge (or rebase if pull.rebase=true) |
git push | Push current branch to its tracked remote branch |
git push --force-with-lease | Force-push, but fail if the remote moved since your last fetch |
git push origin --delete feature/x | Delete a remote branch |
Never git push --force to a shared branch. Always --force-with-lease. The lease aborts the push if someone else pushed in between, instead of silently overwriting their work.
Merging & rebasing
| Command | What it does |
|---|---|
git merge feature/x | Merge feature/x into the current branch |
git merge --no-ff feature/x | Merge with an explicit merge commit, even if fast-forward |
git rebase main | Replay current branch’s commits on top of main |
git rebase -i HEAD~5 | Interactive rebase: squash, fixup, reword, drop, reorder |
git rebase --autosquash -i <base> | Auto-arrange --fixup commits into the right slots |
git rebase --continue / --abort | After resolving conflicts, or to bail out |
The rebase rule of thumb: rebase your local branch onto main before opening a PR (clean history). Don’t rebase commits other people are basing their work on.
Stash — the “hold this for me” box
| Command | What it does |
|---|---|
git stash | Stash tracked changes; index reset |
git stash -u | Also stash untracked files |
git stash list | List stashes (stash@{0} is the newest) |
git stash show -p stash@{0} | Show the diff of a stash |
git stash pop | Apply newest stash and drop it |
git stash apply stash@{1} | Apply a specific stash, keep it on the stack |
git stash drop stash@{1} | Delete a specific stash |
History detective
| Command | What it does |
|---|---|
git log -- <path> | All commits that touched a file |
git log -p -- <path> | Same, with full diffs inline |
git log -S "string" | Commits where the count of "string" changed (pickaxe) |
git log --author="Name" | All commits by an author |
git blame <file> | Per-line author + commit + date |
git show <sha> | Full diff + message of a single commit |
git diff main...feature/x | What feature/x adds compared to main’s tip |
git bisect start / bad / good | Binary-search commits to find a regression |
Worktrees, submodules, tags
| Command | What it does |
|---|---|
git worktree add ../hotfix main | Check out main into a sibling directory — work two branches at once |
git worktree list / remove | Manage active worktrees |
git submodule update --init --recursive | Pull all submodules to the SHAs the parent expects |
git tag -a v1.0.0 -m "msg" | Create an annotated tag |
git push --tags | Push all local tags |
The flags that bite
A short list of commands that have eaten someone’s afternoon. Always pause before running these on a shared branch:
git reset --hard <ref>— destroys uncommitted changes and rewinds HEADgit push --force— overwrites the remote, including other people’s work; use--force-with-leasegit clean -fd— deletes untracked files and directories permanentlygit checkout ./git restore .— discards every unstaged change in the working treegit rebaseon a branch others have based work on — orphans their commitsgit filter-branch/git filter-repo— rewrites entire history; clones must re-clone
The pattern: anything with --hard, --force, or that rewrites public history.
The shortcuts I actually keep aliased
git config --global alias.s "status -sb"git config --global alias.lg "log --oneline --graph --decorate -20"git config --global alias.last "log -1 HEAD --stat"git config --global alias.unstage "restore --staged"git config --global alias.fixup "commit --fixup"git config --global alias.squash "rebase -i --autosquash"git config --global alias.publish "push -u origin HEAD"git s, git lg, git last, git unstage <file>, git fixup <sha>, git squash <base>, git publish — the seven I type a hundred times a week.
More cheat sheets
- More entries in this channel as they ship.
Discussion for this post
Letters, marginalia, and dispatches from fellow readers.
Likes, favorites, and comments are available for signed-in readers.
Comments
Be the first to drop a thought.