Topic 02

One Task, One Branch

Git

The refund diff also fixed a typo in a schedule comment, and in its summary the agent offered to upgrade the date library while it was there. Each is harmless on its own. Together with the refund change, they cannot be reviewed, reverted or searched one at a time. One task per branch keeps every change separable.

Agents make this harder than it used to be, because an agent that reads a file notices things in it, and noticing turns into fixing unless you say otherwise. The branch is where you hold the line.

What Counts as One Task

One task is one behaviour change a reviewer can hold in mind, with everything that change needs. For the refund window, that is the new value, its tests, and the cancellation email and schedule page that state the rule to members. The schedule typo does not belong, and neither does a library upgrade. The size limit is the one Chapter 5 set: a change over about 200 lines gets split.

A quick test settles most borderline cases: if this change had to be reverted next week, should the other one come out with it? The email text and the window should, because a refund rule and its explanation must never disagree. The typo fix should not, and neither should the upgrade. Things that would be reverted together belong together; everything else gets its own branch.

What goes on the refund branch, and what does not
On the branchone behaviour change
The window from 24 hours to 12. The boundary tests. The 23-hour and second-zone tests updated for the new rule. The email and the schedule page, which tell members the rule.
Somewhere elseits own branch or its own task
The typo fix in a schedule comment. The date library upgrade the agent offered. The per-gym policy object, if anyone ever decides it is wanted. Each one is good or bad on its own.

What Mixing Costs

Review first: the reader checking the refund rule also has to read unrelated hunks, and attention spent on a typo is attention not spent on the boundary. Revert second: if the refund change has to come out, the typo fix comes out with it, and the upgrade too. Search third: when Chapter 10 searches history for the commit that broke something, it lands on a commit that changed three things and has to start again inside it. Blame last: a line's last change reads "refund window" when it was really part of an upgrade.

Agents Drift Sideways

An agent that reads a file to do its task sees everything else in it: a typo, an unused import, a deprecated call, a function that could be shorter. Unless told otherwise, it fixes them, because fixing looks helpful and nothing in the task said not to. Each fix is small; together they turn a reviewable diff into an unreadable one.

One line in the project instructions file turns the drift into something useful: "list unrelated problems in your summary; do not fix them". The agent's noticing is valuable. The list it produces becomes a set of candidate tasks, each of which can get its own branch if it is worth doing.

The difference shows in the agent's summary. Without the line, the summary describes what it fixed on the way, and the fixes are already in the diff. With it, the summary ends with a short list of things it noticed and left alone, and each item is one decision for you: a task for later, a question for Ines or nothing at all.

The end of the agent's summary, before and after the instruction
Without it
"Changed the refund window to 12 hours and updated the tests. Also fixed a typo in schedule and tidied the deadline calculation. Happy to upgrade the date library while I'm here."
With it
"Changed the refund window to 12 hours; the two tests that stated the old rule now fail, as expected. Noticed, not changed: a typo in a schedule comment; the date library is two major versions behind."

Moving a Stray Change

The typo fix is a good change on the wrong branch. Give it its own: create a branch from the main line, copy the one commit onto it, and remove it from the refund branch. On a branch only you have used, removing it is a short rebase that drops one commit; the next topic covers what changes once a branch is shared.

Move the typo fix to a branch of its own, then drop it from the refund branch
$ git log --oneline main..refund-window-12h
ad3ceeb (HEAD -> refund-window-12h) Shorten the full-refund window to 12 hours
b92efa0 Fix a typo in a schedule comment
2941125 Use one refund window for refunds and the cancellation screen
a4cdd33 Pin the 24-hour refund rule an hour either side of the line
$ git switch -c fix-schedule-typo main
Switched to a new branch 'fix-schedule-typo'
$ git cherry-pick b92efa0
[fix-schedule-typo e15c664] Fix a typo in a schedule comment
 Date: Thu Oct 29 11:48:55 2026 -0700
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git switch refund-window-12h
Switched to branch 'refund-window-12h'
$ git rebase --onto b92efa0~1 b92efa0
Successfully rebased and updated refs/heads/refund-window-12h.
$ git log --oneline main..refund-window-12h
4989e1b (HEAD -> refund-window-12h) Shorten the full-refund window to 12 hours
2941125 Use one refund window for refunds and the cancellation screen
a4cdd33 Pin the 24-hour refund rule an hour either side of the line

Two branches, each about one thing. The typo fix can merge today without anyone reading the refund change, and the refund branch now holds the refund change and nothing else.

Moving a change is cheaper the earlier it happens. As a single commit on a private branch it takes four commands. Mixed into a commit with the refund change, it first has to be split out by hand, hunk by hunk. Already merged with it, it can only be reverted together with the rule, or untangled with a new commit that puts half of it back. The habit of one commit per request from the previous topic is what keeps the stray fix in a commit of its own, where moving it is trivial.

Branch Names and Scope

Name the branch for the task before the first request: refund-window-12h. The name is a scope statement. Anything that would not fit under it belongs on another branch, and a reviewer who sees a library upgrade on a branch with that name knows at once that something has drifted.

A long-lived branch that collects "while I was there" changes is the same mixing spread over a week. Its name stops describing it on the second day, and by the end nobody can say what reverting it would remove.

Small Branches Merge Easily

A one-task branch lives a day and merges cleanly, because the main line has had little time to move under it. A three-task branch lives a week and conflicts with everything that changed meanwhile. Conflicts an agent resolves are code it wrote, and they get the same reading as any other diff: a resolution that kept both sides, or the wrong side, is a change nobody asked for.

Short branches also make the agent's work easier to throw away, which the next topic depends on. Discarding a one-task branch loses one task. Discarding a branch that has collected a week of mixed changes loses the good ones with the bad, so nobody discards it, and the bad ones ship.

Misconceptions
  • "Fixing small things on the way is efficient." It saves one branch and costs a clean revert and a focused review.
  • "Separate commits on one branch are as good as separate branches." They beat one commit, but the branch merges as a unit and its pull request is reviewed as one.
  • "Fixing what it notices is what makes the agent useful." Noticing is useful. Fixing out of scope makes the diff unreadable, so ask for the list instead.
  • "The member-facing text is a separate task from the rule." A rule change whose explanation to members still says 24 hours is half done. The text belongs with the rule.
  • "Branches are overhead for one developer." They are the unit of discard and revert, whatever the size of the team.
Why It Matters
  • Name the branch for the task before the first request, and refuse changes that do not fit the name.
  • Tell the agent to list unrelated problems rather than fix them. The list becomes the backlog and the diff stays readable.
  • Keep everything one behaviour change needs on the same branch, member-facing text included.
  • Move good stray fixes onto their own branch from the main line instead of letting them ride along.

Knowledge Check

Which of these changes belongs on the refund-window-12h branch?

  • The typo fixed in a comment in the schedule module
  • The cancellation email's text, changed from 24 hours to 12
  • The date library upgrade the agent offered while it was there
  • The per-gym policy object, kept in case it is needed

The refund change shipped together with a date library upgrade, and now has to be reverted. What does the mixing cost at that moment?

  • The revert fails, since git cannot revert a commit that touches many files
  • The revert removes the rule change but keeps the upgrade, as it is separate
  • The upgrade comes out with the rule, or someone must untangle them by hand
  • Nothing extra, since reverting a commit never affects any library versions

The typo fix and the refund change are separate commits on the same branch. Why is that still not enough?

  • Separate commits on one branch can never be reverted on their own
  • The branch merges as one unit, and its pull request is reviewed as one
  • Git refuses to merge a branch that contains more than one commit in it
  • The second commit hides the first one from anyone reading the log

You find the agent's good typo fix as a commit on your private refund branch. How do you move it?

  • Leave it there and mention it in the refund branch's pull request
  • Revert it on the refund branch and forget the fix altogether
  • Retype the fix on the main line and keep the commit where it is
  • Copy it to a new branch from main, then drop it from the refund branch

You got correct