Code & delivery 30 entries 27 run in the sandbox

Git cheat sheet

Everyday workflow, history spelunking and undoing mistakes safely. Each entry has a worked example and the flags worth knowing, and where one is easy to get wrong, the gotcha.

Everyday workflow

git status -sb

Short status with the current branch and how far it is ahead of or behind its upstream.

cd ~/projects/checkout-api && git status -sb
## main...origin/main [ahead 1]
 M src/config.ts
?? forgotten.yaml
-s
Short format: left column staged, right column unstaged.
-b
Show the branch and tracking information.
??
Untracked file.

git diff [--staged]

Show unstaged changes, or with --staged exactly what the next commit will contain.

cd ~/projects/checkout-api && git add src/config.ts && git diff --staged
--staged
Index versus HEAD (alias --cached).
--stat
Files changed with line counts.
A..B
Compare two commits or branches.
-w
Ignore whitespace changes.

Gotcha Always read git diff --staged before committing. It is the cheapest code review there is.

git add -p

Stage changes hunk by hunk, so a commit contains one logical change and no stray debug lines.

git add -p src/server.ts
y / n
Stage or skip this hunk.
s
Split the hunk into smaller ones.
e
Edit the hunk by hand.

git commit -m <message>

Record the staged snapshot with a message that explains why, not just what.

cd ~/projects/checkout-api && git add src/config.ts && git commit -m "chore: debug logs to chase pool timeouts"
-m MSG
Message inline; repeat -m for a body paragraph.
-a
Also stage modified tracked files (not new files).
--fixup SHA
Mark a commit to be squashed into SHA by rebase --autosquash.

git log --oneline --graph --decorate

A compact picture of history with branch and tag labels.

cd ~/projects/checkout-api && git log --oneline --graph --decorate -15
* 9b81ea8 (HEAD -> main) Report DB pool size in /healthz
* a9612a3 (tag: v1.4.2, origin/main, origin/HEAD) Release 1.4.2
* 9f2c1ab fix: retry DB connect on startup
* 43fca6c Tune DB pool size for the smaller RDS instance
* b00e714 (tag: v1.4.1, origin/release/1.4, release/1.4) Move nginx config under deploy/
*   a5b97b1 Merge branch 'feat/metrics'
|\
| * 42ced58 (origin/old-healthcheck) Expose DB pool gauges on /metrics
* | 4908d0e Add nginx and Helm deploy config
|/
* aa75f9d (tag: v1.4.0) Add /healthz endpoint and smoke test
--oneline
Short hash and subject.
--graph
ASCII branch and merge graph.
--all
Include every branch and tag.
-N
Limit to N commits.

git show <commit>

Show one commit's message and diff, or a file as it was at that commit.

cd ~/projects/checkout-api && git show HEAD~2:deploy/values.yaml
SHA
Message plus full patch.
SHA:path
The file's content at that commit.
--stat
Files touched only.

Branches & remotes

git switch -c <branch>

Create a branch and switch to it. switch and restore split the overloaded checkout command in two.

cd ~/projects/checkout-api && git switch -c fix/db-retry
-c NAME
Create and switch.
-
Switch back to the previous branch.
--detach SHA
Check out a commit without a branch.

git branch -vv

List local branches with their upstreams, the last commit and ahead/behind counts.

cd ~/projects/checkout-api && git branch -vv
-vv
Show upstream tracking information.
-d / -D
Delete a merged branch / force-delete any branch.
--merged main
Branches already merged into main, safe to delete.

git fetch --prune

Download new commits and delete remote-tracking branches that no longer exist on the server.

cd ~/projects/checkout-api && git fetch --prune origin
--prune
Remove stale origin/* references.
--all
Fetch from every remote.

git pull --rebase

Update your branch by replaying your local commits on top of upstream, avoiding noise merge commits.

cd ~/projects/checkout-api && git stash -q && git pull --rebase origin main
--rebase
Rebase instead of merge.
--ff-only
Refuse unless it is a fast-forward.
config pull.rebase true
Make rebase the default.

git push -u origin <branch>

Publish a new branch and set its upstream so plain git push and pull work afterwards.

cd ~/projects/checkout-api && git switch -c fix/db-retry && git push -u origin fix/db-retry
-u
Set the upstream (tracking) branch.
--tags
Also push tags.
--delete BRANCH
Delete a remote branch.

git push --force-with-lease

Overwrite your own remote branch after a rebase, but refuse if someone else pushed in the meantime.

git push --force-with-lease origin fix/db-retry
--force-with-lease
Force only if the remote is where you last saw it.
--force
Overwrite unconditionally; can destroy teammates' commits.

Gotcha Never force-push a shared branch such as main. Protect it on the server so nobody can.

git merge --no-ff <branch>

Merge a branch and always create a merge commit, keeping the feature visible as a unit in history.

cd ~/projects/checkout-api && git merge --no-ff feat/cache
--no-ff
Create a merge commit even when a fast-forward is possible.
--squash
Stage the combined changes as one new commit.
--abort
Give up on a conflicted merge and restore the pre-merge state.

git rebase -i <base>

Rewrite local commits before sharing: reorder, squash, reword or drop them.

git rebase -i --autosquash origin/main
pick / squash / fixup
Keep, combine with message, or combine silently.
reword / drop
Change the message or remove the commit.
--continue / --abort
Proceed after fixing a conflict, or bail out.
--autosquash
Place fixup! commits automatically.

Gotcha Rebase rewrites commit IDs. Only rebase commits that nobody else has based work on.

git diff --name-only --diff-filter=U

List the files that still have unresolved conflicts during a merge or rebase.

cd ~/projects/checkout-api && git merge origin/hotfix/pool-size; git diff --name-only --diff-filter=U
<<<<<<< ======= >>>>>>>
Conflict markers: ours, separator, theirs.
git checkout --ours / --theirs FILE
Take one side wholesale.
git add FILE
Mark the conflict resolved.

Gotcha During a rebase, 'ours' is the branch you are rebasing onto and 'theirs' is your commit, the reverse of a merge.

git remote -v

Show the URLs behind each remote name.

cd ~/projects/checkout-api && git remote -v
origin	git@github.com:acme/checkout-api.git (fetch)
origin	git@github.com:acme/checkout-api.git (push)
add NAME URL
Add a remote, for example your fork.
set-url NAME URL
Switch between HTTPS and SSH.

git tag -a <version> -m <msg>

Create an annotated tag for a release, carrying author, date and message.

cd ~/projects/checkout-api && git tag -a v1.4.3 -m "release 1.4.3" && git push origin v1.4.3
-a
Annotated tag (recommended for releases).
-l 'v1.*'
List matching tags.
git describe --tags
Nearest tag plus commits since, handy for build versions.

Investigate history

git log -p -- <path>

Every change to one file, with patches. Answers 'when did this config line change?'

cd ~/projects/checkout-api && git log -p --follow -- deploy/nginx.conf
-p
Include the patch for each commit.
--follow
Continue through renames.
--since='2 days ago'
Limit by date.
--author=NAME
Limit by author.

git log -S <string>

The pickaxe: find commits that added or removed a string, such as a feature flag or a config key.

cd ~/projects/checkout-api && git log -S "MAX_POOL_SIZE" --oneline
-S TEXT
Commits that changed how often TEXT occurs.
-G REGEX
Commits whose diff lines match REGEX.

git blame -L <start>,<end> <file>

Show which commit last touched each line, then read that commit for context.

cd ~/projects/checkout-api && git blame -L 40,60 src/db.ts
-L A,B
Only lines A to B.
-w
Ignore whitespace-only changes.
-C
Detect lines moved or copied from other files.

git bisect start <bad> <good>

Binary-search history for the commit that introduced a bug. Twenty steps cover a million commits.

cd ~/projects/checkout-api && git bisect start HEAD v1.4.0 && git bisect run ./scripts/smoke-test.sh
good / bad
Mark the current commit while bisecting.
run CMD
Automate: exit 0 means good, 1 to 127 (except 125) means bad.
reset
Finish and return to where you started.

git log <old>..<new>

What changed between two releases: exactly the commits that are about to ship or just shipped.

cd ~/projects/checkout-api && git log --oneline v1.4.1..v1.4.2
A..B
Commits reachable from B but not from A.
A...B
Commits on either side but not both.
--no-merges
Hide merge commits.

Gotcha During an incident, git log last-good..current is the shortest list of suspects.

Undo safely

git restore <file>

Discard uncommitted changes in the working tree for a file.

cd ~/projects/checkout-api && git restore src/config.ts && git status -s
--staged FILE
Unstage, keeping the edits in the working tree.
--source=SHA FILE
Restore the file as it was at a commit.

Gotcha Discarded working-tree changes were never committed, so git cannot bring them back.

git commit --amend

Fix the last commit's message or add a forgotten file to it, before pushing.

cd ~/projects/checkout-api && git add forgotten.yaml && git commit --amend --no-edit
--no-edit
Keep the existing message.
--reset-author
Update author and date.

git reset --soft HEAD~1

Undo the last commit but keep its changes staged, so you can recommit them differently.

cd ~/projects/checkout-api && git reset --soft HEAD~1 && git status -s
--soft
Move the branch only; index and files untouched.
--mixed (default)
Also unstage the changes.
--hard
Also discard working-tree changes. Destructive.

git revert <commit>

Undo a commit that is already shared by adding a new commit with the inverse change. The safe rollback on main.

cd ~/projects/checkout-api && git revert --no-edit 9f2c1ab
--no-edit
Use the default message.
-m 1
Revert a merge commit relative to its first parent.
--no-commit
Stage the inverse change for several commits at once.

Gotcha Reverting a merge and later re-merging the same branch brings back nothing. Revert the revert first.

git reflog

Every position HEAD has been at. Recovers commits after a bad reset, rebase or deleted branch.

cd ~/projects/checkout-api && git reflog -10
9b81ea8 (HEAD -> main) HEAD@{0}: commit: Report DB pool size in /healthz
a9612a3 (tag: v1.4.2, origin/main, origin/HEAD) HEAD@{1}: checkout: moving from release/1.4 to main
b00e714 (tag: v1.4.1, origin/release/1.4, release/1.4) HEAD@{2}: checkout: moving from main to release/1.4
HEAD@{N}
Where HEAD was N moves ago.
git branch rescue SHA
Put a branch on a lost commit to keep it.

Gotcha The reflog is local and expires (90 days by default). It cannot recover work that was never committed.

git stash push -m <msg>

Shelve uncommitted work to switch context, then bring it back.

cd ~/projects/checkout-api && git stash push -u -m "wip: export" && git stash list
-u
Include untracked files.
list / show -p
See stashes and their contents.
pop / apply
Restore and drop, or restore and keep.

git cherry-pick <commit>

Apply one specific commit onto the current branch, for example to backport a hotfix to a release branch.

cd ~/projects/checkout-api && git switch release/1.4 && git cherry-pick -x 9f2c1ab
-x
Record the original commit ID in the message.
A..B
Pick a range of commits.
--abort
Cancel after a conflict.

git clean -nd

Preview removal of untracked files and directories, then run it with -f.

cd ~/projects/checkout-api && git clean -nd
-n
Dry run: list what would be removed.
-f
Actually delete.
-d
Include untracked directories.
-x
Also remove ignored files such as build output.

Your pager is ready.

Free, instant, and it works on your phone. No signup: start as a guest and save your progress later.