# Choosing a task's base branch

Set which branch a task's sandbox is cut from and where its merge request lands — at creation, afterwards, and how CodeHerder resolves one when you don't.

Source: https://codeherder.com/docs/base-branch/

Set which branch a task's sandbox is cut from and where its merge request lands — at creation, afterwards, and how CodeHerder resolves one when you don't.

Every task builds its change on top of some starting point in your repository (or repositories — a task can work in more than one, see [Tasks that span several repositories](https://codeherder.com/docs/multi-repo-tasks/)). By default that’s each repo’s own default branch — usually the same branch a fresh `git clone` checks out, unless your workspace has set a different one. A task’s **base branch** lets you override that with a single name, applied to every repo the task works in, so its sandbox branches from — and its merge requests target — wherever you name instead.

Reach for this when a task belongs on a release branch, a long-lived feature branch, or anything other than the branch most work builds on.

## Setting a base branch at creation

Pass `--base-branch` to `ch task create`:

```
ch task create --title "Backport the auth fix" --type story --base-branch release/2.1
```

From the web app, the **New task** form has a **Base branch** field. Leave it blank — its placeholder text reads `(repo default)` — and the task uses your repo’s default branch, same as if you’d omitted the flag on the CLI.

## Changing it afterwards

Set or clear a base branch on an existing task with `ch task edit`:

```
ch task edit <taskId> --base-branch release/2.1
```

Pass an empty string to clear it and fall back to the repo default:

```
ch task edit <taskId> --base-branch ""
```

From the web app, the task page has its own editable **Base branch** row, next to the task’s other details — click it to set or clear the value the same way.

`ch task show` displays the current base branch when one is set (and the task page in the web app always shows it, including the repo-default case). `ch task edit` also echoes back what it just set, or cleared, when you change it.

## It’s fixed once work starts

You can only change a task’s base branch before it has a sandbox. Once one exists, the branch is already cut from wherever it started, and CodeHerder refuses the change:

```
edit task: HTTP 409: baseBranch cannot change while the task has a live sandbox; the worktree is already checked out from the current base
```

Set the base branch before the task is staffed if you know it needs one. If a task has already started on the wrong branch, file a fresh one with the right `--base-branch` instead of trying to redirect the one in progress.

## Where CodeHerder starts from

When a task’s sandbox is provisioned, CodeHerder picks the starting ref for **each repo it works in**, independently, in this order:

1. **The task’s own base branch**, if one is set — the same name applies to every repo in the task’s set.
2. **That repo’s own default branch**, if the task doesn’t set a base branch but the repo has one.
3. **Whichever branch that repo’s own remote HEAD points at**, if neither is set.

So on a task spanning several repos, a base branch named on the task is tried against every one of them; a repo without its own default branch falls back independently to its own remote HEAD, regardless of what the others do. CodeHerder resolves this fresh every time it provisions a sandbox, against a live read of each repo — so changing a repo’s default branch later, or clearing a task’s own base branch, takes effect the next time that task needs a new sandbox.

## A base branch that doesn’t exist yet

Name a base branch that isn’t on a repo’s remote yet, and CodeHerder creates it for you on that repo — cut from that repo’s own default branch and pushed — before the task’s sandbox is provisioned. This applies independently to every repo the task works in: a repo whose remote already has the branch is left alone, and only a repo that’s missing it gets the new branch created for it. It only ever does this for a branch you named on the task itself; it never invents one on your behalf.

It won’t create one in a couple of cases: if the name is already taken by a tag on that repo’s remote, or if it looks like a raw commit ID rather than a branch name. Either one fails the task’s sandbox provisioning with a clear error, so you can rename the task’s base branch and try again.

## What else follows the base

The merge request a task’s build stage opens for each repo targets that task’s base branch, not necessarily the repo’s own default branch — so review, merge, and verify all happen against it too. See [How work flows](https://codeherder.com/docs/how-work-flows/) for the full pipeline these stages run.

## Related guides

- [Writing tasks an agent can build](https://codeherder.com/docs/writing-tasks/) — set a base branch and everything else at creation
- [Editing and cancelling tasks](https://codeherder.com/docs/editing-tasks/) — every other native field you can change after creation
- [Connecting repositories](https://codeherder.com/docs/repositories/) — set and change a repo’s own default branch
- [Tasks that span several repositories](https://codeherder.com/docs/multi-repo-tasks/) — how a task’s repo set works, and how the base branch resolves for each one
