Coding & Tech · Guide
Git Commands Every Developer Should Know
The 20 git commands you'll use every day, with real examples and when to reach for each.
Most developers use about six git commands and wing the rest. That’s fine until something goes wrong and you’re staring at a detached HEAD with uncommitted changes, wondering if reset --hard is going to delete two hours of work.
This guide covers the commands that actually matter day-to-day, organized by what you’re trying to do — plus the “oh no” recovery commands that every engineer needs at some point.
Daily-use commands
git status
The command you run more than any other. Shows branch, staged vs unstaged changes, and untracked files. If in doubt — run git status.
git add -p
Interactive staging. Walks through each change and asks whether to stage it. Prevents the classic “I accidentally committed my console.logs” mistake. Use this instead ofgit add . as a default.
git commit -m "message"
Basic commit. Write clear messages — imperative mood (“Add” not “Added”), brief first line, blank line, then detail if needed.
git commit --amend
Edit the most recent commit. Great for typo fixes or adding a forgotten file. Don’t amend commits you’ve already pushed to shared branches — it rewrites history.
git log --oneline --graph --decorate --all
The view you actually want from git log. One line per commit, ASCII graph of branches and merges, shows all refs. Alias it to git lg.
git diff and git diff --staged
See unstaged changes (git diff) and staged changes (git diff --staged). Read the diff before every commit — you’d be surprised how often it catches mistakes.
Branching
git switch -c feature/name
Modern way to create and switch to a new branch (replaces git checkout -b).git switch branch-name to switch between existing branches.
git branch -vv
List branches with their tracking branch and how far ahead/behind. Useful when multiple feature branches are in flight.
git branch -d branch-name
Delete a merged branch. Use -D only when you’re sure — forces deletion even if unmerged.
Syncing
git fetch
Download refs from remote without merging. Check what’s on origin before integrating. Safer than git pull when you want to know what’s changed.
git pull --rebase
Fetch and replay your local commits on top of origin. Keeps history linear, avoids the “merge commit spam” from default git pull. Set as default with git config --global pull.rebase true.
git push and git push -u origin branch
Standard push. -u sets upstream on first push so future pushes know where to go.
History and rewriting
git rebase -i HEAD~N
Interactive rebase — the cleanup tool. Reorder, squash, edit, or reword the last N commits before pushing. Essential for turning messy WIP commits into a clean PR history.
git cherry-pick <sha>
Apply a specific commit from another branch. Great when you need one fix from a feature branch without the rest.
git stash / git stash pop
Save uncommitted changes temporarily. Useful when switching branches urgently. Check git stash list periodically — stashes are easy to forget about.
Recovery (the “oh no” commands)
git reflog
History of HEAD movements — shows everything you’ve done, including resets and checkouts. If you think you’ve lost work, this is where you look first. Almost nothing is truly lost in git if you act within 90 days.
git reset --soft HEAD~1
Undo the last commit but keep changes staged. The safe “oops, let me redo that commit” command.
git reset --hard HEAD
Nuclear option: discards all uncommitted changes. Only use when you’re sureyou want to throw work away. Triple-check with git status first.
git revert <sha>
Create a new commit that undoes a previous commit. Safe for shared branches because it doesn’t rewrite history. Use this on main instead of reset.
Bonus: config that makes your life easier
Set these once and benefit every day: git config --global pull.rebase true, git config --global push.autoSetupRemote true, git config --global init.defaultBranch main, git config --global rerere.enabled true. Pair with our clean code guide — clean commits belong to clean code.