ع
Start Topics Teams Reference What's new Saved
Workflows & power-user

Landing a change on a team: branches, pushes and pull requests

Six steps between "I made a change" and "the change is in the real project" — plus the one thing that must never reach a commit, because git's history is permanent by design.

10 min read · Updated 2026-08-20
Landing a change on a team: branches, pushes and pull requests

There are two versions of git and they feel almost unrelated.

The first is git as undo for an entire project — commit as you go, and any earlier state can be restored exactly. That version is solo, it lives entirely on your machine, and it’s the reason letting an agent edit your files is a reasonable thing to do at all. It’s covered in version control (git), and if you’re working alone it’s genuinely all you need.

The second version starts the moment someone else depends on the project. Now a change isn’t just something you make; it’s something you land — isolated somewhere safe, proposed rather than imposed, reviewed, and then folded in on purpose. That’s six extra moves, and this page is all of them.

The division of labour is worth stating up front, because it’s what makes this approachable: Claude runs every git command; every judgment call is yours. Is this one commit or two? Is that message honest? Is this ready to be public? Is the reviewer right? None of those are mechanics, and none of them can be delegated.

1. Branch it

A branch is a cheap, disposable copy of the whole project where you can experiment without touching the version everyone relies on.

It’s “Save As” before you start editing aggressively, except instant and free. The main version — called main — keeps working exactly as it was. Your branch is a parallel universe. If the experiment works, you fold it back in. If it goes sideways, you delete the branch and it’s as though it never happened.

make a branch for the contact form fix

This is the safety net underneath everything else on this page, and it’s what makes “just let Claude try it” a reasonable instruction rather than a reckless one. On a branch you can let Claude attempt something bold — a large refactor, a risky rewrite — and if it turns into a mess you don’t carefully unpick each change. You abandon the branch. main never saw any of it. The branch absorbs the chaos.

The one word worth internalising is main: the trunk, the version considered real. Everything else hangs off it, waiting to either join or be thrown away.

2. Commit one idea at a time

Left alone, Claude will happily bundle everything you touched this afternoon into one commit. Resist that.

A good commit is one coherent change. Chapters in a book, not a daily diary dump.

The reason isn’t tidiness, it’s your undo. Rolling back a commit is clean only if that commit is one thing. Tangle a contact-form fix together with an unrelated headline reword, and when the reword turns out to be wrong a week later you can’t remove it without also throwing away the bug fix riding along beside it.

You set the boundary; Claude does the staging:

commit just the contact form fix — leave the headline reword for a separate commit

Then glance at the message it drafts. A good one says what changed and why, in a sentence you’d be happy for a stranger to read in six months: “Reject contact messages with an empty name instead of silently dropping them.” Claude writes these better than most people bother to. Your job is only to confirm it’s true and complete, because you’re the one who knows what you actually did.

The thing that must never reach a commit

This deserves its own section rather than a footnote, because it is the one mistake on this page with consequences you cannot undo.

Secrets don’t belong in git. .env files, API keys, passwords, access tokens, database URLs with credentials in them — anything you wouldn’t paste into a public chat.

Git history is permanent by design. A secret that lands in a commit is in that commit forever, even if the very next commit deletes the file. And once it’s pushed, you have to assume someone has it.

That’s the whole hazard: the mechanism that makes git trustworthy — nothing is ever really lost — is exactly what makes a committed secret unrecoverable. Deleting it later removes it from the current state, not from history.

The protection is a file called .gitignore, which lists what git should never track. You don’t have to write one from memory. Before your first commit in a new project, ask:

is anything here that shouldn't go into git? Set up a .gitignore if so.

And if one has already slipped through: don’t reach for history surgery first. Rotate the credential — revoke the old one, issue a new one — because that’s the step that actually makes it harmless, and it works whether or not anyone has already cloned the repository. Cleaning the history is second, and optional.

3. Push — the line between private and public

Here’s what surprises almost everyone: every commit you’ve made so far is private. It exists on your computer and nowhere else. Your teammate can’t see it. A second machine of your own can’t see it.

There are two copies of the project: yours (local) and the shared one on GitHub (the remote). Commits pile up locally; push sends them to the remote, and pull brings other people’s down to you.

push this branch

Pushing is a different kind of door than committing. A local commit is entirely yours — rewrite it, delete it, nobody has seen it. Once your commits reach the shared copy, other people can pull them, build on top of them, and depend on them, and you can’t cleanly un-ring that bell. It’s a one-way door, and it deserves the half-second of attention any one-way door deserves.

It’s also exactly why a pushed secret is compromised rather than merely embarrassing.

None of this makes pushing dangerous — you’ll do it constantly. But nothing leaves your machine until you say so, and knowing that silence means still private is half the model.

4. Open a pull request

Your branch is on GitHub now, but off to the side. main still doesn’t have your changes. You could merge your own branch straight in. On a project with other people, you don’t.

A pull request says: here’s my change, look it over before it goes into the real project.

The name reads backwards — you’re requesting that the project pull your branch in. In practice it’s a page showing your diff, a description explaining the change, and a space for people to comment, all before anything merges.

What it buys you over merging yourself is two things: a deliberate pause for review, and a permanent record of why the change happened.

open a pull request for this branch

Claude reads every commit on the branch, writes the title and description, opens the PR and hands you the link. Note the relationship between the two kinds of writing here: commit messages explain each individual step; the PR description zooms out and explains the whole change at once — what it does, why it was needed, and what a reviewer should know before they look. Read it before it goes out. You’re the one who knows whether it’s actually ready.

5. Handle the review

Someone reviews it — a teammate, an automated check, sometimes Claude itself in a review pass — and leaves comments. This could leak memory. Rename this for clarity. You’re missing a test here. For a lot of people this is the part that feels like a verdict.

It isn’t. A review comment is just another kind of prompt.

address the review comments on this PR

You don’t start over and you don’t open a new PR. Changes go on the same branch; you commit and push, and the open pull request picks up the new commits automatically. It updates in place.

But do not skip the judgment. Not every comment is right. A reviewer can be mistaken. Claude can misread what a comment was asking for. A comment is part of a discussion, and you decide which ones to act on and which to push back on with your reasoning. “Good catch, fixed” and “I left this as-is because the empty case is handled upstream” are both complete, professional answers. Silently ignoring one is the only bad option, because the disagreement then resurfaces at merge time.

6. Merge, then delete the branch

The reviewer approves. You merge the pull request, and now main finally has the change — reviewed, recorded, and attached to the conversation that produced it. The branch has done its job, so you delete it.

If both branches changed the same lines, git will report a merge conflict rather than guess. This sounds alarming and isn’t; it’s git declining to make a decision that isn’t its to make. Paste the conflict at Claude and ask what each side was trying to do — explaining the intent behind two competing edits is exactly the kind of reading it’s good at.

The whole loop, on one real change

The bug: the contact form silently drops a message when the visitor leaves the name field blank. handleContact saves nothing and the visitor never finds out.

  1. Branch it. “Make a branch for the contact form fix.” main — the version that’s live right now — is untouched no matter what happens next.
  2. Fix and commit one idea. Claude fixes handleContact. You commit just that — not the unrelated typo you also spotted on the about page.
  3. Check the message. “Reject contact messages with an empty name instead of silently dropping them.” True, scoped, explains the why. Good.
  4. Push it. Your work is on GitHub. Nothing is proposed yet; you’ve just got it off your laptop.
  5. Open the PR. Claude writes the description. You confirm it’s honest. It’s now a proposal anyone can see.
  6. Handle the review. A reviewer notices the fix rejects an empty name but still lets a blank email through. Claude adjusts, you push, the PR updates itself. You agreed the catch was right — if you hadn’t, you’d have said so in the thread.
  7. Merge and clean up. Approved, merged, branch deleted. Done.

Look back at that. Not one step was clever. A branch is a sentence. A commit is a sentence. Opening a PR is a sentence. Individually none of it would impress anyone.

Together they’re the difference between hoping a change is safe to ship and knowing it is: isolated on a branch, scoped into clean commits, proposed for review, merged on purpose. And the split holds the whole way down — Claude ran every command, and every decision that needed a human ran through you.

Topics

Questions people ask

Do I need to learn git commands to work this way?
No. Every step here is a sentence — *"make a branch for the contact form fix"*, *"push this branch"*, *"open a pull request"* — and Claude runs the underlying commands. What you do need is the *model*: that a branch is disposable, that pushing is public, that a pull request is a proposal. The commands are mechanics and Claude is better at them than you'll ever need to be. The judgment about when to do each one is the part that can't be delegated.
I committed an API key by accident. Is deleting it in the next commit enough?
No, and this is the one place to be blunt about it. Git history is permanent by design — the old commit still contains the key even after a later commit removes the file. If you have already pushed, treat the key as compromised and **rotate it**: revoke the old one and issue a new one. Scrubbing it out of history is possible but disruptive, and it doesn't help you if anyone has already fetched the repository. Rotate first, clean up second.
What's the difference between committing and pushing?
A commit saves a snapshot on *your* machine. A push sends your commits to the shared copy — usually GitHub — where teammates can see and build on them. Everything you commit is private until you push, which is why a local commit is cheap to redo and a pushed one isn't. It's the line between a draft on your laptop and something out in the world.
A reviewer left a comment I think is wrong. What do I do?
Say so, with your reasoning, in the PR thread. A review comment is part of a discussion, not an order — the reviewer can be mistaken, or can have misread what the code was doing. *"Good catch, fixed"* and *"I left this as-is because the empty case is handled upstream"* are both complete, professional answers. What isn't fine is silently ignoring it, because then the disagreement never gets resolved and it resurfaces at merge time.
Put it into practice
Browse the topics
Start