Git's command names were chosen by people who already understood git. For everyone else, here's the translation. Two ideas unlock almost all of it:
- A commit is a snapshot of your whole project, chained to its parent.
- A branch is just a sticky note pointing at one commit. It moves freely.
Most "scary" commands are either moving sticky notes or rewriting the chain. Keep those two pictures in your head and the table below reads like common sense.
The cheat sheet
| Command | What it actually does | Danger level |
|---|---|---|
git commit --amend |
Replaces your last commit with a new version | Low (until pushed) |
git stash |
Shelves uncommitted changes on a side pile | Low |
git cherry-pick <sha> |
Copies one commit's changes onto your branch | Low |
git revert <sha> |
Adds a commit that cancels an old one | Low |
git merge <branch> |
Weaves two branches together, keeps both histories | Medium |
git rebase <branch> |
Replays your commits on top of another branch | Medium |
git reset --soft HEAD~1 |
Deletes the last commit, keeps the changes staged | Medium |
git reset --hard HEAD~1 |
Deletes the last commit and its changes | High |
git clean -fd |
Deletes untracked files. Permanently. | High |
git push --force |
Overwrites the remote branch with yours | High |
git rebase -i |
Rewrites, reorders, or drops a run of commits | High |
git reflog |
Shows everywhere HEAD has been — your undo log | None (read-only) |
The five that hurt people
git reset --hard — the number-one source of "I just lost my work." It moves your branch backwards and throws away everything in your working tree that isn't committed. The commits are usually recoverable via reflog or worse; uncommitted changes are simply gone.
git push --force — rewrites the branch on the server to match yours. If anyone pulled the old version, their history now disagrees with reality, and any commits of theirs you didn't have are orphaned. Use --force-with-lease, which bails out if the remote moved without you knowing.
git rebase -i — incredibly useful, but it's a history editor: drop, squash, reword, reorder. Every commit it touches gets a new identity, so never run it on commits you've already pushed to a shared branch. Squashing with it is its most common good use.
git clean -fd — deletes files git isn't tracking, which by definition means there's no copy in any commit, anywhere. There is no undo. Run git clean -nd first — the -n dry-run shows what would die.
git commit --amend — harmless and lovely for fixing a typo'd message, until the commit has been pushed. Amending rewrites the commit, so pushing afterwards requires a force push, with all the baggage above.
The commands that get you out of trouble
git reflog is the big one — git quietly logs every place HEAD pointed, so "deleted" work is usually one lookup away from being found again. It only knows your local clone, though, and entries expire. Treat it as a smoke detector, not a backup strategy.
git revert is the polite undo: instead of erasing the past, it appends a commit that cancels the bad one. Safe on any branch, no matter how many people pulled. Full walkthrough here.
git merge --abort — the one everyone forgets mid-panic. Stuck in a conflicted merge you regret? This cancels it and puts everything back.
Skip the memorization
git.tools reads your repo's history and shows it in plain English — and every scary operation below exists as a safe, reviewed pull request instead of a command you have to get right under pressure.
Open git.tools →A parting heuristic
If a command's description includes the words "rewrite history," the rule is always the same: fine on commits only you have, hostile on anything pushed. When in doubt, take the path that adds new history instead of rewriting old — it's almost always available, and it's the default philosophy git.tools is built on. For the rare cases where rewriting really is the answer — like purging a leaked secret — we do it with backups and guardrails, never a YOLO force push.