# Branching strategy

> Know where to start, where to merge and what ships.

Start a project assignment · /branching-strategy/ · 2026-10-22

## Ask the agent to check your branch plan

**Prompt**

```text
Read [Jira key or URL] through the connected Jira MCP or authenticated acli, including description, acceptance criteria and comments.
If access is unavailable, ask for pasted ticket details.
Use its fix version as the target release; if none is set, ask before choosing a branch. Inspect the repository instructions and branch history.
Report the starting branch, PR target and whether a Release Merge branch is needed.
Flag inherited or excluded tickets. Say whether remote refs are up to date.
Do not switch branches, merge or push yet.
```

- Check the proposed plan against the branch rules below before proceeding.
- Start new work from `main`, the production-code baseline.
- Keep each ticket’s code and tests together; collect approved tickets on a release branch.
- After production checks, merge released code into `main`. Update documentation separately.
- Use reviewed PRs. Do not commit directly to `main` or `release/*`.

## Know the branch types

- `ENG` is an example Jira project key; `ENG-123` and `ENG-124` are tickets. Use your own ticket key.
- `RM1` means the first Release Merge branch for that ticket.

| Branch                             | Purpose                                                                                                 |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `main`                             | Latest released code after merge-back; the base for new work. Closeout then changes documentation only. |
| Ticket — `feat/ENG-123`            | One ticket’s code and tests, without unrelated tickets.                                                 |
| Release — `release/2.8.0`          | The tickets selected for a release; a candidate until approved and shipped.                             |
| Release Merge — `feat/ENG-123-RM1` | A temporary integration branch for resolving conflicts with a release.                                  |
| Fix — `fix/ENG-130`                | An urgent production fix, or a fix to a candidate bug that has no ticket branch.                        |

## Choose your starting branch and PR target

| Your change                                            | Start from                             | Open the PR into                                           |
| ------------------------------------------------------ | -------------------------------------- | ---------------------------------------------------------- |
| Planned ticket                                         | Current `main`                         | Intended release branch                                    |
| Fix to your ticket before release                      | Continue on the original ticket branch | Intended release, through its Release Merge branch if used |
| Candidate bug without an existing ticket branch to fix | A new fix branch from that candidate   | The same release branch                                    |
| Urgent production fix                                  | Current `main`                         | Its own patch release branch                               |

- The ticket's Jira fix version is its target release. If it is missing or changes, confirm with the PM before branching.
- Before branching from `main`, confirm the latest production release is merged back. Otherwise `main` lags behind production, and an urgent fix built on it ships code that differs from what is running.
- A fix branched from a candidate inherits all its tickets. It cannot be moved to another candidate without checking those dependencies.

## Follow a ticket through release

Diagram: Step 1: create ticket and release branches from main. Step 2: merge the ticket into the release. Step 3: validate the candidate. Step 4: approve and deploy the tested artifact, then verify production. Step 5: merge the release into main. Documentation closeout follows separately.

_Validate first, deploy next, then merge the released code into main._

1. **Develop.** Create the ticket and release branches from production-aligned `main`.
2. **Integrate.** Merge the approved ticket PR into the intended release branch.
3. **Validate.** Pass the required checks; record the tested commit and artifact.
4. **Deploy and verify.** Get approval, deploy the tested artifact, then check the production version and changed flow.
5. **Merge back.** Merge released code into `main` by PR, then complete [documentation closeout](/release-mgmt/).

## Resolve conflicts without mixing ticket work

- Resolve release conflicts on a Release Merge branch.
- Keep the original ticket branch free of unrelated tickets.

Diagram: Step 1: create RM1 from the ticket branch. Step 2: merge the release into RM1 and resolve conflicts. Step 3: if testing finds a ticket defect, fix the original ticket branch and merge it into RM1. Step 4: test RM1 and merge it by reviewed PR into the release. Never merge RM1 back into the ticket branch.

_Resolve conflicts on RM1; keep business-code fixes on the ticket branch._

1. **Create RM1.** Branch `feat/ENG-123-RM1` from `feat/ENG-123`.
2. **Resolve conflicts.** Merge the release into RM1 and resolve conflicts. Do not add new business behaviour.
3. **Fix on the ticket.** Fix ticket defects on the original branch, then merge it into RM1. Skip if no fix is needed.
4. **Review and merge.** Test the combined result and open RM1’s PR into the release.

- Do not develop or cherry-pick business-code fixes directly on RM1.
- Do not merge RM1 back into the ticket branch: it now includes other tickets from the release.

## Remove a ticket by rebuilding the candidate

- The old candidate contains `ENG-123` and `ENG-124`.
- If `ENG-124` is postponed, rebuild from `main` with `ENG-123` only.
- Keep `ENG-124` on its ticket branch, and move its Jira fix version to the later release.

Diagram: Step 1: ENG-123 and ENG-124 have both been merged into the old candidate; stop using that candidate when ENG-124 is postponed. Step 2: create a replacement release from main. Step 3: integrate ENG-123 only using fresh integration branches if needed. Step 4: rerun validation and obtain approval for the replacement commit and artifact; do not ship the superseded candidate.

_Left: ENG-123 and ENG-124 entered the old candidate. Right: a fresh candidate takes ENG-123 only._

1. **Retire the candidate.** Mark `release/2.8.0` superseded. Do not deploy it anywhere further.
2. **Start fresh.** Create `release/2.8.0-2` from current `main`.
3. **Include ENG-123 only.** Merge `ENG-123` by PR. Use fresh Release Merge branches; old ones can bring `ENG-124` back.
4. **Validate again.** Test and approve the replacement commit and artifact. Results for `ENG-123` + `ENG-124` do not prove `ENG-123` alone works.

- For fixes found only on the old candidate, check dependencies before adapting them through a new PR.

## Handle an urgent production fix

- Give the fix its own version. If `2.7.0` is in production, create `release/2.7.1` from `main`.
- Branch `fix/ENG-130` from `main` and open its PR into `release/2.7.1`. Validate, deploy and merge back as for any release.
- Don't branch the fix from an active candidate such as `release/2.8.0`, or merge it there directly: the candidate holds unshipped tickets.
- A candidate cut before the fix doesn't contain it. Once the patch release merges back, merge `main` into the candidate by reviewed PR and validate the candidate again; otherwise that release brings the bug back.

Next: With the branch and PR target agreed, [deliver the change](/deliver-a-change/).
