Git Cheat Sheet
Section 16 · Lesson 1 · Level: beginner · ~10 min · Prereq: Git essentials
Why this matters¶
Git ships around a hundred and fifty commands and you will use about twelve. This page is those twelve, grouped by what you are trying to do, followed by the recovery commands you reach for when an agent has just rewritten four files you did not mean to touch. Read it once, then search it instead of guessing.
Set up once per machine¶
git config --global user.name "Your Name" # identify your commits
git config --global user.email you@example.com # use the address on your GitHub account
git config --global init.defaultBranch main # new repos start on main
git config --global pull.rebase false # pull merges instead of rewriting commits
git config --list --show-origin # every setting, and which file set it
git config --list can print credential-helper settings. Read it on your own machine; never paste the output into an issue, a chat, or an agent session.
Every day¶
git status # first command before and after any agent edit
git diff # read unstaged edits line by line
git diff --staged # read exactly what is about to be committed
git add -p # stage one hunk at a time, not one `git add -A` sweep
git add path/to/file.py # stage a single file
git commit -m "why, not what" # save a checkpoint; small and often beats one big commit
git log --oneline -10 # confirm your last few commits say what you think
git switch -c feat/add-health-endpoint # branch so main stays deployable
git push -u origin feat/add-health-endpoint # publish; -u makes later pushes just `git push`
Branches¶
git branch # list local branches, and which one you are on
git switch main # move to an existing branch (prefer switch over checkout)
git merge main # bring main into your feature branch
git branch -d feat/done # delete a branch after its pull request merges
git cherry-pick <sha> # copy one commit from another branch, and nothing else
Undo: what each command preserves¶
The difference between these is only ever what survives.
| Command | What it preserves |
|---|---|
git restore <path> |
Nothing. Discards uncommitted edits; work never added has no reflog entry. |
git restore --staged <path> |
Your edits, in the working tree. Only the staging decision is undone. |
git restore --source=HEAD~1 -- <path> |
The file at an older commit, restored into the working tree while history stays untouched. |
git commit --amend --no-edit |
Rewrites the last commit in place. Safe only while it is unpushed. |
git revert <sha> |
Everything else: adds an undo commit, so history is appended rather than rewritten. |
git reset --soft HEAD~1 |
Uncommits the last commit and leaves its changes staged. |
git reset HEAD~1 |
Uncommits and unstages, but keeps the changes on disk. This is the default mode. |
git reset --hard HEAD~1 |
Nothing. Deletes the commit and the changes; only the reflog can help, and only briefly. |
git reflog |
The list of everywhere HEAD has pointed — the way back after a bad reset or rebase. |
Worth memorising: --soft keeps work staged, plain HEAD~1 keeps it unstaged, --hard keeps nothing.
Inspecting before you blame¶
git diff --stat # file-level summary when a diff is too large to read
git diff main...HEAD # everything your branch adds — the reviewer's view
git log --oneline --graph --decorate --all # one-screen map of branches and merges
git log -S "duplicate_charge_guard" # find the commit that added or removed a string
git log -p -- path/to/file.py # one file's history with patches attached
git show <sha> # one commit: message, diff, metadata
git blame -L 20,40 path/to/file.py # the commit that last changed those lines
git bisect start # binary search for the breaking commit
git bisect bad # mark the current commit as broken
git bisect good <old-sha> # mark a known-good commit
git bisect run pytest tests/test_x.py # let bisect test each candidate for you
git bisect reset # end the search, back to your branch
git blame names the commit that last touched a line, not the person at fault — often whoever reformatted the file.
Remotes and stashing¶
git remote -v # check which URL origin actually points at
git fetch --prune # refresh remote state, drop stale branch refs
git pull # fetch and merge, when your branch is clean
git stash push -m "wip before agent run" # park uncommitted work so you can pull or switch
git stash list # see what is parked
git stash apply # reapply and keep the stash entry (safer)
git stash pop # reapply and drop the entry
git clean -n # dry run: list what a cleanup would delete
git clean -fd # delete untracked files and dirs — nothing here is recoverable
Commit before you stash when you can; a stash is easy to forget and easy to drop.
Pick the right undo¶
flowchart TD
A["Something went wrong"] --> H{"Is the commit gone from history?"}
H -- "yes, I lost it" --> H1["git reflog"]
H1 --> H2["git reset --hard HEAD at that entry"]
H -- "no" --> B{"Is it committed yet?"}
B -- "no" --> C{"Did you stage it?"}
C -- "no" --> C1["git restore the file"]
C -- "yes" --> C2["git restore --staged the file"]
B -- "yes" --> D{"Has it been pushed?"}
D -- "no" --> E{"Do you want to keep the edits?"}
E -- "yes" --> E1["git reset --soft HEAD~1"]
E -- "no" --> E2["git reset --hard HEAD~1"]
D -- "yes" --> F["git revert the commit, then push"]
I broke it — the six wounds¶
# 1. An agent rewrote files and you want them back
git status # see the damage first
git restore . # discard working-tree edits; untracked junk needs `git clean -n` then `git clean -fd`
# 2. You staged far more than you meant to
git restore --staged . # rebuild the index; every edit stays on disk
git add -p # then stage deliberately
# 3. Your last commit landed on the wrong branch
git switch -c right-branch # the commit comes with you
git switch wrong-branch # then, back on the wrong branch:
git reset --hard HEAD~1 # remove it there — safe, it is unpushed
# 4. A bad commit is already on a shared branch
git revert <sha> # adds an undo commit
git push # everyone else's clone still matches the remote
# 5. Commits vanished after a reset or a rebase
git reflog # find the entry before the mistake
git reset --hard HEAD@{2} # or: git switch -c rescue <sha>
# 6. You are stuck mid-merge or mid-rebase with conflict markers
git status # prints the next step
# resolve, then: git add <file> && git rebase --continue
git merge --abort # or back out entirely
git rebase --abort
Wounds 4 to 6 cost the most time: reverting is the only safe undo for published history, the reflog is the only way back from a hard reset, and git status always says whether you are mid-merge, mid-rebase, or merely dirty.
Never do this to a shared branch¶
git push --force rewrites commits other people already have: their next pull produces conflicts they did not cause, and open pull requests break. Rebasing or amending pushed commits does the same, because every rewritten commit gets a new identity — review comments, check runs and tags anchored to the old ones point at nothing. git reset on a published branch deletes history for everyone who fetches; use git revert. Rewriting is legitimate on a branch nobody else has checked out, and even there git push --force-with-lease is safer: it refuses the push if someone pushed while you were rewriting. Treat release tags as fixed — moving one makes everything keyed to it lie.
Try it¶
- In a scratch directory,
git init, commit one file, then rungit log --oneline. - Edit the file badly, run
git restore <file>, and confirm withgit statusthat nothing changed. - Edit it again, stage it, then
git restore --staged .— the edit is still on disk, unstaged. - Commit, run
git reset --hard HEAD~1, then recover the commit withgit reflogandgit reset --hard HEAD@{1}. - In a real repository, run
git log -S "<a function you renamed>"and read the commit that changed it. - Break one test across three commits, then find the culprit with
git bisect start,git bisect bad,git bisect good <old-sha>,git bisect run pytest,git bisect reset.
Common mistakes¶
- Treating
git restoreas an undo. It deletes. A file you never staged has no reflog entry, so the edit is gone. - Using
git add -Aon a dirty tree. It sweeps your unrelated edits into the agent's commit, so one diff holds two intentions. - Reaching for
git reset --hardfirst. It is the one command here that destroys work; the reflog usually rescues you, but only briefly. - Force-pushing to
mainafter a bad merge. It rewrites history for every clone and can erase a teammate's commit. - Reading
git blameas a list of who to blame. Read the commit and its diff before concluding anything about a person.
Key takeaways¶
- Twelve commands cover most days; the rest are lookups.
--softkeeps work staged, plainHEAD~1keeps it unstaged,--hardkeeps nothing.git revertis the undo for anything already pushed;git resetis for commits only you have.git reflogis the safety net under a bad reset or rebase. Use it before you give up.git statusbefore and after every agent edit is what makes fast editing safe.- Never rewrite history on a shared branch; prefer
--force-with-leaseeven on your own.
Further learning¶
git help <command>andgit <command> --help— the offline reference, always the version you have installed.- Git essentials — the concepts behind these commands, including the four places a change lives.
- Keeping diffs small — the review habit that makes small commits pay off.
- CI troubleshooting — what to do when the pipeline is red because of a commit.
- GitHub docs — search this root for git workflow, pull request, and history topics.
- GitHub CLI cheat sheet — the same tasks through
ghinstead of raw git.