DEV Community

Nova
Nova

Posted on

Branch-per-Ask: A Safer Git Workflow for AI-Assisted Coding

If you use an assistant to help with coding, you’ve probably felt this tension:

  • You want speed (generate code, refactor, write tests, update docs).
  • You still need safety (don’t break main, don’t ship surprising changes).

The simplest workflow I’ve found that keeps both is what I call Branch-per-Ask:

Every meaningful request to your assistant happens on a fresh Git branch, with a clear goal and a tiny merge surface.

It’s not fancy. It’s just a small discipline that turns “messy chat-driven changes” into something you can review, test, and revert like normal software work.

Below is the playbook I use (with concrete commands, prompts, and a couple of habits that make it stick).


Why Branch-per-Ask works

When you ask for help in-place (on main or a long-running branch), three things tend to happen:

  1. Changes accumulate without a boundary. You lose track of what the assistant touched “for this thing” vs “for that thing.”
  2. Review becomes vague. A diff that mixes refactors + fixes + formatting is hard to approve confidently.
  3. Rollback is painful. If you need to undo one request, you often undo five.

Branch-per-Ask adds a hard boundary around a single intent. That boundary buys you:

  • a clean diff
  • a testable unit of work
  • a natural “stop” point

The core rule

One branch = one request = one outcome.

Examples of good “one outcome” asks:

  • “Add a CLI flag --dry-run and update docs.”
  • “Refactor this module to remove circular dependency, no behavior change.”
  • “Write unit tests for parseInvoice() covering these 6 cases.”

Examples of bad asks (too broad):

  • “Clean up the codebase.”
  • “Improve performance.”
  • “Modernize everything.”

If the ask isn’t specific, the branch won’t be either.


Step-by-step workflow (copy/paste)

1) Start from a known-good base

git switch main
git pull
Enter fullscreen mode Exit fullscreen mode

If you’re working off a release branch or a feature branch, start from that instead — the point is: begin from something stable.

2) Create a branch that encodes intent

git switch -c ai/add-dry-run-flag
Enter fullscreen mode Exit fullscreen mode

My naming convention:

  • prefix: ai/ (so it’s obvious this was assistant-assisted work)
  • verb-first: add-, fix-, refactor-, test-, doc-
  • small scope

This is not about credit or blame. It’s about fast filtering later when you’re scanning branches.

3) Write the ask like a tiny spec

Before you paste code, write the constraints.

Here’s a template that consistently produces reviewable changes:

Goal:
- Add a --dry-run flag to the "sync" command.

Constraints:
- No behavior changes when the flag is not provided.
- When --dry-run is set, print what would happen, but do not write.
- Update README usage examples.
- Keep changes minimal; avoid unrelated refactors.

Deliverables:
- Patch/diff.
- A short summary of what changed and why.
- Tests (unit or integration) proving dry-run does not write.
Enter fullscreen mode Exit fullscreen mode

Two subtle wins here:

  • You’re defining what not to change.
  • You’re asking for a patch + summary, which makes review easier.

4) Keep the branch “small by default”

When the assistant proposes a plan, keep the first iteration narrow.

A rule of thumb:

  • If the diff is > 250 lines, ask for a smaller slice.
  • If the assistant touches more than 3–5 files, ask why.

You can always do another Branch-per-Ask after merging.

5) Commit with a message that matches the intent

git status

git add -A

git commit -m "Add --dry-run flag to sync"
Enter fullscreen mode Exit fullscreen mode

This matters because it makes git log tell the story later.

6) Test like you mean it

Run the smallest “confidence suite” for your project. Examples:

npm test
npm run lint
Enter fullscreen mode Exit fullscreen mode

Or:

pytest
ruff check .
Enter fullscreen mode Exit fullscreen mode

If the assistant added code but no tests, don’t accept it by default. Instead, do a second ask on the same branch:

  • “Now add tests for these specific cases. Do not change implementation unless required to test.”

7) Review the diff as if it was a PR from a teammate

Two commands I use constantly:

git diff main...HEAD
Enter fullscreen mode Exit fullscreen mode

…and:

git show --stat
Enter fullscreen mode Exit fullscreen mode

What I’m looking for:

  • does the diff match the stated goal?
  • any new dependencies?
  • any formatting-only churn?
  • are errors handled consistently?

If anything feels off, don’t fix it ad-hoc on the branch. Instead, issue a new, precise ask:

  • “In this diff, file X introduces Y. Please remove that; keep behavior unchanged.”

This keeps the branch coherent.

8) Merge and delete

If you use PRs, open one and merge normally. If you merge locally:

git switch main
git merge --no-ff ai/add-dry-run-flag
git push

git branch -d ai/add-dry-run-flag
Enter fullscreen mode Exit fullscreen mode

The delete step is part of the pattern. It keeps your repo from becoming a graveyard of half-finished assistant experiments.


The “two-branch” upgrade: explore vs ship

Sometimes you do want exploration (a big refactor, alternative architecture, performance experiments).

In that case, split the work:

  • ai/explore-… — messy is allowed, prototypes are allowed
  • ai/ship-… — only contains the minimal, reviewable final change

Workflow:

  1. explore freely
  2. once you know what you want, create a clean ship branch from main
  3. cherry-pick the relevant commits
git switch -c ai/ship-http-timeout-fix main
git cherry-pick <commit>
Enter fullscreen mode Exit fullscreen mode

You get the benefits of experimentation without shipping the mess.


A tiny PR checklist (I reuse this constantly)

Paste this into your PR description:

### Intent
- (one sentence)

### Scope
- [ ] Only changes required for intent
- [ ] No drive-by refactors

### Safety
- [ ] Tests added/updated
- [ ] Lint/format passes
- [ ] Error handling consistent

### Review notes
- Files touched: __
- Risky areas: __
Enter fullscreen mode Exit fullscreen mode

The checklist does one important thing: it makes you explicitly confirm that the assistant didn’t “helpfully” expand the scope.


Common failure modes (and what to do)

1) The assistant rewrites everything

Fix: restate constraints and ask for a smaller patch.

“Keep changes limited to files A and B. Do not reformat unrelated code. Provide a minimal diff.”

2) The assistant adds dependencies casually

Fix: make “no new deps” a default constraint unless you really want them.

3) You can’t tell what changed

Fix: require a patch letter with the diff:

  • what changed
  • why it changed
  • how to validate
  • what to watch out for

(If you’re reading this thinking “that’s just a good PR description”… exactly.)


The payoff

Branch-per-Ask isn’t about ceremony. It’s about keeping your codebase legible when you’re moving fast.

Once you adopt it, you’ll notice a shift:

  • you ask smaller, clearer questions
  • you review diffs more confidently
  • you ship more often with fewer surprises

Try it for your next 5 assistant-assisted changes. If nothing else, your git log will thank you.

Top comments (0)