Cheat sheet: Git and GitHub with Claude Code
Claude Code can drive practically your entire git and GitHub workflow — commits, branches, pull requests, reviews, and rescuing a broken repo. This cheat sheet sums up what I hand over without worry after months of daily use, and for every situation it shows both: the prompt I type, and the commands that actually run under the hood. Because delegating doesn't mean you stop understanding what's going on.
Commits and messages
The thing I ask for most often. A plain "commit this" is enough, and under the hood this runs:
git status # what changed, what's untracked
git diff # what actually changed
git add build.mjs serve.mjs
git commit -m "fix: dev server did not serve webp from subdirectories"The message comes from what the diff actually says — not from what I think I did. What has worked for me:
- Conventions belong in CLAUDE.md. Commit message language, prefixes like
feat:/fix:, formatting — write it once into the repository instructions and Claude follows it without being reminded. - Selective commits work reliably. When I have several unrelated things in progress:
commit only the changes in build.mjs, leave the rest alone
Under the hood that's git add build.mjs and a commit — no git add -A that would sweep up the unfinished rest.
- Let it split unrelated changes. "Split this into logical commits" — Claude walks the diff, groups files by what belongs together, and stages group by group (falling back to
git add -pfor individual hunks if needed).
What I watch: push is always an explicit step. I instruct Claude to never push on its own — a commit is local and reversible, a push is publication.
Reverse gear: amend, restore, stash
The small fixes I used to look up the exact command for on Stack Overflow:
- "Add this to the last commit":
git add build.mjs
git commit --amend --no-editAmend rewrites history — it's only safe until the commit is pushed. Claude points that out on its own, but it's worth knowing.
- "Throw away the changes in serve.mjs":
git restore serve.mjs # discard unstaged changes in the file
git restore --staged serve.mjs # just unstage, keep the changes- "Stash my work in progress, I need a hotfix":
git stash push -m "wip: new footer"
git stash list
git stash popOne caveat: when git stash pop hits a conflict, it applies the changes but keeps the stash — on purpose, so you can't lose work. Once the conflict is resolved, clean it up yourself: git stash drop.
Since I started using worktrees, I stash less — see the next section.
Branches and worktrees
Creating a branch is trivial — "create a branch for the footer rework":
git switch -c feat/footerThe more interesting tool is worktrees: a second working copy of the repository on a different branch, in a sibling directory.
git worktree add ../project-fix fix/commission-rounding
git worktree list
git worktree remove ../project-fix # once it's doneWhy this matters with an AI tool: I can run two Claude Code sessions side by side — one building a feature, the other fixing a bug — and they never step on each other's files, because each works in its own directory. No branch switching, no git stash acrobatics.
Two things worktrees won't tell a newcomer: the same branch can't be checked out in two worktrees at once (git refuses — rightly so). And node_modules don't clone: every copy lives its own life, so git worktree add is followed by another npm install.
(Worktrees solve parallel work on one machine. Keeping one project — Claude Code context included — in sync across two computers is covered by One repo, two keyboards.)
Pull requests via the gh CLI
Claude Code talks to GitHub through the official gh CLI. One-time setup:
brew install gh # macOS
winget install GitHub.cli # Windows
sudo apt install gh # Debian/Ubuntu
gh auth login # one-time sign-inAfter that:
create a PR against main, keep the description short
Under the hood:
git log main..HEAD --oneline # which commits the branch brings
git diff main...HEAD # the branch's full diff against main
git push -u origin feat/footer
gh pr create --base main --title "..." --body "..."The PR description is generated from the actual diff of the whole branch against main, not just the last commit — so it stays accurate even after ten fix-up commits. The other direction works too:
fetch the review comments from PR #42 and address them
gh pr view 42 --comments # the discussion under the PR
gh api repos/{owner}/{repo}/pulls/42/comments # inline comments in the codeClaude pulls the comments, goes through them one by one and tells you what it did with each. For comments it disagrees with, I want it to say so — not to comply blindly.
Reviewing someone else's PR — "check out PR #42 and walk me through it":
gh pr checkout 42 # the PR's branch into your local copy
gh pr diff 42 # a quick look without checking outAnd the merge, once it's done — "merge PR #42 with a squash":
gh pr merge 42 --squash --delete-branchI treat merge the same as push: it's publication, so I approve it explicitly.
Issues and CI
The section I left out of the first version of this cheat sheet — even though it's half of what gh does for me daily.
- "List the open issues labeled bug":
gh issue list --label bug --state open
gh issue view 12- "File an issue for this" — mid-session, when I hit a bug I don't want to deal with right now:
gh issue create --title "..." --body "..." --label bugClaude writes the description from the session context while it's fresh — so it's concrete: what happened, where, how to reproduce it. An issue filed this way is more useful than the one I'd write from memory three days later.
- "Why did CI fail on this branch?" — possibly the biggest time-saver in this whole cheat sheet:
gh pr checks # check status on the PR
gh run list --branch feat/footer # recent workflow runs
gh run view 1234567890 --log-failed # the log of only what failedClaude pulls the failure log, finds the cause and proposes a fix right away. No clicking through the web UI, no scrolling a mile-long log.
Reviewing your own diff before the PR
Before I open a PR, I have the diff reviewed locally first — it's cheaper than burning a colleague's time:
review this branch's diff against main — look for bugs and risks, not style
git diff main...HEADThe three dots are not a typo: diffing against the common ancestor (merge-base) shows only what my branch introduced — not the changes that landed on main in the meantime.
The more specific the brief, the better it works: "focus on error handling", "look for race conditions", "check that no personal data gets logged". A generic "take a look" returns generic answers.
Rescue situations
This is where you find out whether AI helps you or hurts you.
- Merge/rebase conflicts — Claude resolves them, but I want to see the reasoning:
resolve the conflicts; for each file, tell me which side you took and why
git status # which files are in conflict
git checkout --ours file.js # take our whole side
git checkout --theirs file.js # take their whole side
git rebase --abort # emergency brake: back to before the rebaseMost of the time, though, Claude edits the conflict blocks by hand — more precise than taking whole files from one side. (And mind the classic trap: during a rebase, the meaning of --ours/--theirs flips.)
- Revert — a safe operation, it creates a new commit and rewrites nothing:
git revert abc123- Bisect — hunting the commit that broke something is finally painless with AI:
bisect to find the commit that broke the build; test with node build.mjs
git bisect start
git bisect bad # HEAD is broken
git bisect good v1.4 # it still worked here
git bisect run node build.mjs # automated test at every step
git bisect resetWith git bisect run, the whole binary search runs without a single manual step — Claude just reads off the result and points at the culprit.
- Reflog — the last resort for "there was a commit here yesterday and now it's gone":
git reflog # a journal of everywhere HEAD has ever been
git reset --hard HEAD@{2} # return to a specific stateReading the reflog is safe. The reset --hard at the end is not — which brings us to the point: git reset --hard, force push, and branch deletion I do by hand, or at minimum I want Claude to explicitly ask before running them. Claude Code's permission settings support exactly that: I keep destructive commands on manual approval.
Quick reference
| Situation | Prompt | Key command |
|---|---|---|
| Commit everything | "commit this" | git commit -m |
| Selective commit | "commit only the changes in X" | git add X && git commit |
| Fix the last commit | "add this to the last commit" | git commit --amend --no-edit |
| Discard changes | "throw away the changes in X" | git restore X |
| Park work in progress | "stash my work in progress" | git stash push -m "..." |
| New branch | "create a branch for …" | git switch -c |
| Parallel work | two sessions side by side | git worktree add |
| Pull request | "create a PR against main" | gh pr create |
| Addressing review | "fetch comments from PR #N" | gh api …/pulls/N/comments |
| Someone else's PR | "check out PR #N and walk me through it" | gh pr checkout N |
| Issues | "list the open bugs" | gh issue list --label bug |
| CI failure | "why did CI fail?" | gh run view --log-failed |
| Pre-PR review | "review this branch's diff against main" | git diff main...HEAD |
| Conflicts | "resolve conflicts and explain each" | git checkout --ours/--theirs |
| Undo a commit | "revert commit X" | git revert X |
| Regression | "bisect to find what broke …" | git bisect run |
| Lost commit | "find the lost commit" | git reflog |
Conclusion
I don't understand git any less because of Claude — quite the opposite: without that understanding, I wouldn't catch it when it gets something wrong. I just don't type the commands I can dictate anymore, and the energy saved goes into checking the results. Git stays the same, it's just someone else doing the typing.