joeOS · AI · Reference

Git & GitHub Bible

Cookbook-first reference for every Git and GitHub workflow Joe runs. Read the Safety Rules once. After that, jump to the scenario you're in.

21 scenarios deep-space 2026-05-11 ↗ source .md ↗ github

All examples assume you are in the repo: cd ~/Documents/Development/<repo>. Worktree paths look like ~/Documents/Development/<repo>/.claude/worktrees/<name> and the same commands apply inside them.

§1Safety Rules

If you find yourself reaching for any command, pause and read the matching scenario in §6 first.

RuleWhy
Never git push --force to main / master / shared branchesRewrites history other people depend on. Use --force-with-lease only on your own feature branches.
Never git reset --hard without running git status and git stash first if there's anything uncommitted--hard discards working-dir changes silently. No undo unless they were committed or stashed.
Never git rebase a branch that's already been merged into main or pulled by someone elseRewrites SHAs; collaborators (or other machines) will diverge.
Never commit secrets (.env, keys, tokens). If you do, rotate the secret first, then scrub historyHistory rewrite alone doesn't help — the secret is already exposed.
Always git fetch before assuming you know the remote stateLocal view of origin/main is only as fresh as your last fetch.
Always create a new commit instead of --amend after a pushAmend rewrites the last commit. If it's pushed, others may have it.
Always prefer --force-with-lease over --force when force-push is unavoidableAborts if the remote moved since your last fetch; --force blindly overwrites.
Never skip pre-commit hooks (--no-verify) without a documented reasonHooks exist to catch real problems; bypassing them shifts the bug to CI or prod.

§2Mental Model

Git tracks state across three trees.

Working Directory     files you can see and edit
         git add
Index (Staging)       what will be in your next commit
         git commit
HEAD (Committed)      the current commit on your current branch
         git push
Remote                origin/<branch> on GitHub
ConceptWhat it is
CommitAn immutable snapshot of the index, identified by a SHA-1 hash.
BranchA movable pointer to a commit. main, feature/x, etc.
HEADPointer to the commit currently checked out (usually via a branch ref).
RefAny name that points at a commit: branch, tag, HEAD, HEAD~3, HEAD@{2}.
RemoteA named URL to another repo. origin is default; upstream is convention for the repo you forked from.
Upstream branchThe remote branch your local branch tracks. Set with git push -u origin <branch>.
Fast-forwardMerge where the target's tip is a direct ancestor of source. No merge commit needed.
Key insight: branches are cheap pointers, not directories. git switch other-branch doesn't copy files — it moves HEAD and updates your working dir. This is why cherry-pick and rebase can shuffle commits between branches so easily.

§3Daily Golden Path

The 90% workflow.

StepCommandNotes
1. Sync maingit switch main && git pullAlways start from current main
2. Branchgit switch -c feat/short-nameOne branch per logical change
3. Edit(work)Small, focused commits
4. Stagegit add <file> or git add -pPrefer named files over git add .
5. Commitgit commit -m "feat: short imperative summary"First line ≤72 chars
6. Pushgit push -u origin feat/short-name-u only the first time
7. Open PRgh pr create --title "..." --body "..."See §9 for the heredoc body pattern
8. Iterateedit → add → commit → pushNo -u after first push
9. Mergegh pr merge --squash --delete-branchOr merge in UI after review
10. Clean upgit switch main && git pull && git branch -d feat/short-name-d refuses if unmerged; safe

Commit message style: <type>: <imperative summary> where type ∈ {feat, fix, refactor, docs, test, chore}. Body: why, not what — the diff shows what.

§4Decision Matrices

4.1Merge vs Rebase

SituationUse
Integrating a long-lived feature into main, want to preserve branch historygit merge --no-ff
Updating your in-flight feature branch with latest maingit rebase main (cleaner) or git merge main (safer if shared)
Branch is shared with another machine or another persongit merge — never rebase shared history
Branch exists locally on multiple of your own machines but nothing's been pulled from origin yetRebase OK — "shared" means pulled by someone else, not just pushed
Cleaning up local commits before opening a PRgit rebase -i to squash/reorder
One commit on main per featurePR's "Squash and merge" button (or gh pr merge --squash)

Default for solo feature branches: rebase locally for cleanup, then gh pr merge --squash for the final integration.

4.2Reset Modes

ModeHEAD moves?Index reset?Working dir?When
--softyesnonoUndo commit, keep changes staged. Common for "redo my last commit."
--mixed (default)yesyesnoUndo commit, unstage changes, keep edits in working dir.
--hard yesyesyesThrow everything away back to the target ref. Destructive — only reflog can save you.

HEAD~1 = one commit back. HEAD~3 = three back. HEAD@{2} = where HEAD was 2 movements ago (reflog).

4.3Reset vs Revert vs Checkout

GoalCommand
Undo a commit on a private branch (rewrite history)git reset
Undo a commit on a shared/pushed branch (preserve history)git revert (new commit that inverts)
Discard uncommitted changes to one filegit restore <file>
Discard all uncommitted changesgit restore . (or git stash if you might want them later)
Switch to a different branchgit switch <branch>
Switch to a specific commit (detached HEAD)git switch --detach <sha>

git checkout still works for all of these; switch and restore (Git ≥2.23) are clearer — checkout was overloaded.

4.4Force-Push Decision Tree

Need to push but remote rejects?
├─ Did you rebase or amend?
│   ├─ Yes, branch is YOURS only          → git push --force-with-lease ✓
│   ├─ Yes, branch is shared              → STOP. Talk to collaborators first.
│   └─ Yes, branch is main/master         → STOP. Never force-push main.
└─ No, just behind                        → git pull --rebase, then git push

Always prefer --force-with-lease over --force. It refuses if the remote has commits you haven't fetched, preventing you from clobbering someone else's work.

§5Command Reference

5.1Inspecting State

git statusWhat's staged, modified, untracked. First command of every session.
git status -sShort format
git log --oneline -20Last 20 commits, one per line
git log --graph --oneline --all -20Visual branch graph
git log -p <file>Every commit that touched a file, with diffs
git log -S "string""Pickaxe" — every commit that added/removed that string
git log -G "regex"Pickaxe with regex
git diffUnstaged changes
git diff --stagedStaged but uncommitted
git diff main..HEADEverything different between main and current branch
git show <sha>Diff and message of one commit
git blame <file>Per-line, who last changed it
git reflogEvery HEAD movement (the "undo journal")

5.2Staging & Committing

git add <file>Stage a specific file
git add -pStage hunks interactively (review every change)
git add .Stage everything in current dir risk of secrets/junk
git restore --staged <file>Unstage a file (keeps edits)
git commit -m "msg"Commit staged changes
git commit -a -m "msg"Stage all tracked-file changes & commit (skips untracked)
git commit --amendReplace last commit (message + staged) if pushed
git commit --amend --no-editAdd staged changes to last commit, keep message

5.3Branching

git branchList local branches
git branch -aList local + remote-tracking
git branch -vvList with upstream tracking
git switch <branch>Switch to existing branch
git switch -c <new>Create + switch from current HEAD
git switch -c <new> origin/<remote>Create local tracking a remote
git branch -d <branch>Delete (refuses if unmerged)
git branch -D <branch> Force-delete (loses commits if unmerged)
git branch -m <old> <new>Rename branch

5.4Syncing

git fetchDownload remote refs, don't merge. Safe anytime.
git fetch --all --pruneFetch all; remove tracking refs for deleted remote branches
git pullfetch + merge on current branch
git pull --rebasefetch + rebase — cleaner history when collaborating
git pushPush current branch to its upstream
git push -u origin <branch>First push: set upstream
git push --force-with-leaseForce-push with safety check (§4.4)
git push --tagsPush annotated tags (not pushed by default)

Set pull.rebase = true globally if you want pulls to always rebase: git config --global pull.rebase true.

5.5Integrating

git merge <branch>Merge into current. FF if possible, else merge commit.
git merge --no-ff <branch>Always create merge commit (preserves branch shape)
git merge --squash <branch>Squash into staged changes on current; commit manually
git merge --abortBail out of an in-progress merge
git rebase <base>Replay current branch's commits on top of <base>
git rebase -i <base>Interactive: pick/squash/reword/edit/drop
git rebase --onto <new> <old> <branch>Surgical: move <branch> from old-base to new-base
git rebase --continue / --skip / --abortContinue after resolving / skip current / bail out

5.6Moving Commits

git cherry-pick <sha>Apply that commit to current branch (new SHA)
git cherry-pick <sha1>..<sha2>Pick a range (exclusive of sha1; use <sha1>^..<sha2> to include)
git cherry-pick -x <sha>Add "(cherry picked from commit ...)" to message
git cherry-pick --abort / --continueBail / continue after conflict
git revert <sha>New commit that undoes <sha>. Safe on shared history.
git revert -m 1 <merge-sha>Revert a merge commit (must pick parent line; -m 1 = first parent)
git revert -n <sha>Stage revert without committing (combine multiple)
git revert <sha1>..<sha2>Revert a range

5.7Saving Work In Progress

git stashSave unstaged + staged; revert working dir to HEAD
git stash push -m "msg"Stash with a label
git stash push -uInclude untracked files
git stash listShow all stashes
git stash show -p 'stash@{0}'Show diff of a stash
git stash popApply latest and drop it
git stash pop 'stash@{2}'Apply specific and drop it
git stash apply 'stash@{0}'Apply but don't drop (safer)
git stash drop 'stash@{0}'Delete a specific stash
git stash clear Delete all stashes

zsh quoting: wrap stash@{N} or HEAD@{N} in single quotes — zsh treats {...} as brace expansion and bare forms error. Bash users can drop the quotes.

5.8Recovery (Reflog & Friends)

git reflogEvery HEAD movement, newest first. Your time machine.
git reflog show <branch>Reflog for one branch
git reset --hard 'HEAD@{2}' Jump HEAD back 2 movements ago
git reset --hard <sha> Jump HEAD to a specific commit
git fsck --lost-foundFind dangling commits orphaned by rebases/resets
git cat-file -p <sha>Inspect any object by SHA

Reflog entries persist ~90 days by default (gc.reflogExpire). If you "lose" a commit via reset/rebase, it's almost always still in the reflog.

5.9Investigation

git bisect startBegin a binary-search bug hunt
git bisect bad / good <sha>Mark current bad / a known-good sha
git bisect resetExit bisect, return to original HEAD
git bisect run <script>Automated — script exits 0 = good, non-zero = bad
git blame -L 10,20 <file>Blame lines 10–20
git log --follow <file>Log including history before file was renamed

5.10Tags & Releases

git tagList all tags
git tag -a v1.2.0 -m "Release 1.2.0"Annotated tag (recommended for releases)
git tag v1.2.0Lightweight tag (no metadata; personal markers)
git tag -d v1.2.0Delete local tag
git push origin v1.2.0 / --tagsPush one tag / all annotated tags
git push --delete origin v1.2.0Delete remote tag
gh release create v1.2.0 --notes "..."GitHub Release attached to the tag
gh release create v1.2.0 dist/*.zipRelease with binary assets

5.11Worktrees

Separate working directory backed by the same .git. Lets you have main in one folder and feat/x in another. Claude Code uses these per-task.

git worktree listShow all worktrees
git worktree add .claude/worktrees/feat-x feat/xCreate at that path checked out to feat/x (Joe's convention; see §7)
git worktree add -b feat/y .claude/worktrees/feat-y mainCreate worktree + new branch off main
git worktree remove <path>Remove (refuses if dirty)
git worktree remove --force <path> Force-remove dirty worktree
git worktree pruneClean up records for worktrees whose dirs are gone

5.12Submodules (use sparingly)

Avoid submodules unless absolutely necessary. They complicate every workflow. Prefer monorepo or package managers.

git submodule add <url> <path>Add a submodule
git submodule update --init --recursiveInitialize + check out all after a fresh clone
git clone --recurse-submodules <url>Clone with submodules in one shot

§6Scenario Cookbook

Format: Situation → What's happening → Run this → Verify → Gotchas.

6.1I committed to the wrong branch

You meant to be on feat/x but you were on main when you committed.

Run this (commit not yet pushed)

git log -1                            # note the SHA of the commit to move
git log --oneline origin/main..HEAD   # ⚠ MUST show exactly one commit
git switch feat/x                     # or: git switch -c feat/x
git cherry-pick <sha>                 # use the SHA, not the branch name
git switch main
git reset --hard HEAD~1               # ⚠ destructive; previous --oneline check is the precondition

Verify

git log --oneline -3 main             # bad commit gone
git log --oneline -3 feat/x           # bad commit landed here as new SHA
Gotcha: if you already pushed to main, do not reset main. Use revert (§6.4) and cherry-pick to feat/x instead.
Recovery: if reset removes more than you wanted, git reflog → find the pre-reset HEAD → git reset --hard 'HEAD@{1}'. See §5.8.

6.2Undo my last commit (keep my changes)

Last commit was wrong, but the file edits are fine — you want to redo the commit.

git reset --soft HEAD~1     # commit gone, changes still staged
# edit, restage as needed
git commit -m "better message"

Verify

git status                  # should show staged changes
git log --oneline -3

6.3Undo my last commit (discard my changes)

Last commit was wrong AND the changes are bad — throw it all away.

git status                  # confirm nothing else uncommitted you'd lose
git reset --hard HEAD~1     # ⚠ destructive
Panic recovery: git reflog → find the lost commit → git reset --hard 'HEAD@{1}' brings it back (quote braces in zsh).

6.4Undo a commit that's already pushed

Bad commit is on a shared branch (or main). Rewriting history is unsafe.

git revert <sha>            # creates a new commit that inverts the bad one
git push

For merge commits, plain git revert errors. You must pick a parent:

git revert -m 1 <merge-sha>   # -m 1 = keep first-parent line (branch that received the merge)
Gotcha: revert only inverts the diff. State that depends on the bad commit (db migrations, deployed artifacts) is not undone.

6.5Fix the last commit message

Not yet pushed

git commit --amend          # opens editor for new message

Already pushed (your own feature branch)

git commit --amend
git push --force-with-lease   # ⚠ never on main/shared

Already pushed to main / shared branch: leave it. Don't rewrite history others may have pulled.

6.6I accidentally committed a secret or wrong file

Not yet pushed (last commit only)

git rm --cached <file>             # untrack but keep on disk
echo "<file>" >> .gitignore
git commit --amend --no-edit

Already pushed — the secret is already exposed

  1. Rotate the secret immediately (regenerate token, change password). History rewrites alone do not protect a leaked credential.
  2. Then scrub history with git-filter-repo:
    brew install git-filter-repo                   # or: pip install git-filter-repo
    git filter-repo --path <file> --invert-paths   # ⚠ rewrites entire history
    git push --force                               # ⚠ see note
    Note: this is the one place the bible uses bare --force instead of --force-with-lease (§1). filter-repo deliberately rewrites every ref; lease checks fight that intent and can leave dangling refs holding the secret.
  3. Tell collaborators to re-clone. Their local clones still have the secret.
Gotcha: GitHub caches commits in PRs and forks. Even after force-push, the SHA may still be reachable via direct URL. Rotation comes first.

6.7My PR needs the latest changes from main

git switch main
git pull
git switch feat/x
git rebase main             # replay your commits on top of new main
# resolve any conflicts (see §6.11)
git push --force-with-lease # ⚠ rebase rewrote your SHAs

Alternative (if branch is shared)

git switch feat/x
git merge main              # creates a merge commit; no force-push needed
git push
Gotcha: if the PR has been reviewed, prefer merge over rebase — rebases can detach review comments from their commits. The GitHub PR UI's "Update branch" button defaults to a merge and is the safest one-click option for a shared PR.

6.8Combine my last 3 commits into 1

git rebase -i HEAD~3
# In the editor: leave first as `pick`, change others to `squash` (or `s`)
# Save, then edit the combined message in the next editor view

If already pushed (your own branch only): git push --force-with-lease

Gotcha: fixup (or f) is like squash but discards the squashed commits' messages — useful when they were just "wip" or "fix".

6.9Split one big commit into smaller commits

git rebase -i HEAD~N        # N puts the big commit in range
# Mark the commit `edit` (or `e`) and save. Rebase pauses there:
git reset HEAD~              # un-commit but keep changes in working dir
git add -p                   # stage one logical chunk
git commit -m "first piece"
git add -p
git commit -m "second piece"
# repeat until clean
git rebase --continue

6.10I'm mid-rebase and want out

git rebase --abort
Gotcha: works only if rebase is still in progress (.git/rebase-merge/ or .git/rebase-apply/ exists). After --continue finishes, --abort is no longer available — recover via reflog (§5.8): find the pre-rebase HEAD with git reflog, then git reset --hard 'HEAD@{N}'.

6.11Merge conflict, and I don't know what to do

Git can't auto-merge two changes to the same lines.

git status                  # lists files "both modified"
# Open each conflicted file. Find conflict markers:
#   <<<<<<< HEAD
#   your version
#   =======
#   their version
#   >>>>>>> branch-name
# Edit to the final version. Remove all markers.
git add <resolved-file>
# When all conflicts resolved:
git merge --continue        # if mid-merge
git rebase --continue       # if mid-rebase
git cherry-pick --continue  # if mid-cherry-pick

Tools that help

git mergetool               # 3-way merge tool (configurable)
git diff                    # shows conflict hunks before resolving
git checkout --ours <file>  # take your version wholesale
git checkout --theirs <file> # take their version wholesale
Gotcha: during a rebase, "ours" and "theirs" are swapped relative to merge — --ours means the branch you're rebasing onto, --theirs means your commits. This trips everyone up.

6.12I deleted a branch I needed

git reflog                  # find the last commit on that branch
# Look for "checkout: moving from <branch>" or its tip
git switch -c <branch> <sha>
Gotcha: if the branch only existed on the remote, git fetch and check git branch -a — it may still be there.

6.13Commit from another branch without merging the whole branch

git log --oneline other-branch    # find the SHA
git switch feat/x
git cherry-pick <sha>

Multiple commits

git cherry-pick <sha1> <sha2> <sha3>
git cherry-pick <sha1>..<sha2>     # range, exclusive of sha1
Gotcha: cherry-pick creates a new commit with a different SHA. If the original branch later merges into yours, you'll have the change twice. Range inclusivity: use <sha1>^..<sha2> to include <sha1>.

6.14I pushed to main by mistake

Haven't yet been overwritten

git revert <sha>            # creates an undo commit
git push

Broke production: revert immediately as above. Root-cause separately. Do not force-push main.

6.15Two machines have diverged on the same branch

You committed on Mac, then committed on Windows without pulling first. Both have local commits the other doesn't.

git fetch
git status                  # will say "diverged"
git pull --rebase           # replays your local commits on top of remote's
# resolve conflicts if any (§6.11)
git push

Or, to merge instead

git pull                    # creates a merge commit
git push
Force-pushed from the other machine: if you ran git push --force-with-lease on machine A, the remote SHA changed. On machine B, git pull --rebase can surface phantom conflicts. If A is canonical: git fetch && git reset --hard origin/<branch> (discards local commits).

Prevention: push at end of every session; pull at start. See Multi-Instance Protocol.

6.16My worktree is in a weird state

worktree path is gone but git worktree list still lists it; or you can't switch branches because Git says it's checked out elsewhere.

git worktree list           # see what Git thinks exists
git worktree prune          # remove records for worktrees whose dirs are gone
git worktree remove <path>  # remove a specific one
git worktree remove --force <path>   # ⚠ if dirty

Claude Code worktrees live at ~/Documents/Development/<repo>/.claude/worktrees/<adjective-name> with branches claude/<adjective-name>. They persist after the task ends. Prune periodically with git worktree prune.

6.17Remove a file from all of git history

Giant file accidentally committed, blowing up clone size. Or a leaked secret (but rotate first — §6.6).

brew install git-filter-repo                         # or: pip install git-filter-repo
git filter-repo --path path/to/file --invert-paths   # ⚠ rewrites all history
git push --force --all                               # ⚠ bare --force intentional — see §6.6
git push --force --tags                              # ⚠ rewrites tags

Preconditions

  • All collaborators warned and ready to re-clone.
  • Backup of the repo exists (cp -r repo repo.bak first).
  • Not on main/master of a high-traffic repo without team coordination.
Gotcha: git filter-branch is deprecated and slow. Always use git-filter-repo.

6.18gh pr create failed because branch isn't pushed

git push -u origin <current-branch>
gh pr create --title "..." --body "..."

-u only needed the first time per branch.

6.19PR has conflicts and I'm scared to resolve them

Option A — locally (recommended)

gh pr checkout <pr-number>      # switches to PR's branch
git fetch origin main
git rebase origin/main          # or: git merge origin/main
# resolve conflicts (§6.11)
git push --force-with-lease     # ⚠ rebase only; plain push if you merged

Option B — in GitHub UI: click "Resolve conflicts" on the PR. Only works for simple cases.

Gotcha: never resolve conflicts by accepting "all theirs" or "all ours" without reading the actual diff. Conflicts mean both sides changed the same lines for a reason.

6.20What changed between two refs?

Diff between two commitsgit diff <sha1>..<sha2>
Diff between two branchesgit diff main..feat/x
Just the file listgit diff --name-only main..feat/x
Just the stat summarygit diff --stat main..feat/x
Commits in B but not Agit log A..B --oneline
Commits unique to eachgit log A...B --oneline --left-right (note 3 dots)
Compare two PRsgh pr diff <pr-number>

6.21Find when a bug was introduced (git bisect)

Manual

git bisect start
git bisect bad                  # current commit is broken
git bisect good <known-good-sha>
# Git checks out a midpoint. Test it.
git bisect good                 # or: git bisect bad
# Repeat until Git names the first bad commit.
git bisect reset                # return to original HEAD

Automated

git bisect start HEAD <good-sha>
git bisect run ./test.sh        # exit 0 = good, non-zero = bad
git bisect reset
Gotcha: bisect run requires a deterministic, fast test. Flaky tests produce wrong results.

§7Worktree Workflows

Claude Code creates a worktree per task at ~/Documents/Development/<repo>/.claude/worktrees/<adjective-name>. Each has its own branch claude/<adjective-name> but shares the underlying .git.

When to use worktrees instead of branches

Manual worktree (without Claude Code)

cd ~/Documents/Development/<repo>
git worktree add ../<repo>-feat-x feat/x          # existing branch
git worktree add -b feat/y ../<repo>-feat-y main  # new branch off main

Cleanup

git worktree list
git worktree remove ~/Documents/Development/<repo>-feat-x
git worktree prune                                # stale entries

Rules

§8Multi-Machine Workflows (Mac ↔ Win)

Golden flow

WhenRun
Starting work on machine Agit fetch && git pull on every active branch
Pausing workgit status (verify clean) → git push
Resuming on machine Bgit fetch && git pull

Handling divergence

If you forget to push on machine A and start working on machine B:

# On machine B, after fetch:
git status                  # "diverged"
git pull --rebase           # cleanest history
# OR
git pull                    # merge commit; safer if rebase scares you

Stash hand-off (rare)

Stash doesn't sync via Git. Either:

§9PR Workflow with gh CLI

Create

gh pr create --title "feat: short summary" --body "$(cat <<'EOF'
## Summary
- bullet 1
- bullet 2

## Test plan
- [ ] manual test step
- [ ] CI passes
EOF
)"

Inspect

gh pr listAll open PRs in this repo
gh pr list --author @meJust yours
gh pr viewCurrent branch's PR
gh pr view <num>Specific PR
gh pr view <num> --webOpen in browser
gh pr diff <num>Show the diff
gh pr checksCI status for current branch's PR

Switch to a PR locally (e.g. to review)

gh pr checkout <num>        # creates/switches to local branch tracking the PR

Comment / review

gh pr comment <num> --body "LGTM"
gh pr review <num> --approve
gh pr review <num> --request-changes --body "see comments"

Merge

gh pr merge <num> --squash --delete-branch    # solo workflow default
gh pr merge <num> --merge                     # preserves all commits
gh pr merge <num> --rebase                    # rebases onto base, no merge commit

Drafts

gh pr create --draft --title "..." --body "..."
gh pr ready <num>           # convert draft → ready for review

Useful one-off API calls

gh api repos/{owner}/{repo}/pulls/<num>/comments    # all review comments on a PR
gh api repos/{owner}/{repo}/issues/<num>/comments   # general PR comments

{owner} / {repo} / {branch} are documented placeholders gh api expands from current repo context. The older :owner/:repo colon form sometimes still works but is undocumented — don't rely on it.

§10Co-Authored Commits with Claude

When Claude Code drives a commit, the convention (from ~/.claude/CLAUDE.md) is to add a Co-Authored-By trailer. Use a heredoc so the multiline message renders correctly.

git commit -m "$(cat <<'EOF'
feat(audio): add onset detector hints

Why: tempo and valence cues need a single source of truth across
web and iOS. This wires the C2 detector to both targets.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"

Add the trailer when: Claude wrote substantive code in the commit. Mechanical edits (rename, formatter run) don't need it.

Skip when: purely human commits, version bumps, merge commits.

§11Glossary & Authoritative Sources

Terms

TermMeaning
HEADPointer to the current commit (usually via a branch)
detached HEADHEAD points directly at a commit, not a branch — commits made here are easy to lose
fast-forward (FF)Merge that just moves the branch pointer because the target is an ancestor of the source
upstreamThe remote branch your local branch tracks
originConvention for the default remote
forkA copy of a repo on GitHub under your account; you push to your fork, then PR upstream
squashCombine multiple commits into one
rebaseReplay commits on top of a different base
cherry-pickApply one commit's diff onto current branch as a new commit
revertCreate a new commit that inverts another commit's diff
reflogLog of every HEAD movement; the undo history
dangling commitA commit no branch/tag references; reachable only via reflog or fsck
annotated tagTag stored as a full Git object with author/date/message; preferred for releases
lightweight tagTag that's just a name pointing at a commit; for personal markers

Authoritative sources