# GSD-Build Branching Strategies: How Branches Are Created During Execution

> Discover GSD-Build branching strategies none phase and milestone. Learn how branches are created during execution for efficient Git workflows.

- Repository: [GSD/get-shit-done](https://github.com/gsd-build/get-shit-done)
- Tags: how-to-guide
- Published: 2026-02-16

---

**GSD-Build supports three Git branching strategies—`none`, `phase`, and `milestone`—which control whether branches are created per milestone, per phase, or not at all during `gsd execute-phase` workflows.**

The `gsd-build/get-shit-done` repository provides a structured CLI for managing software milestones through Git-based workflows. Understanding the available GSD-Build branching strategies is essential for teams configuring their development pipeline, as these settings determine exactly when and how Git branches are created during phase execution.

## Supported Branching Strategies in GSD-Build

GSD-Build implements three distinct branching strategies, controlled via the `git.branching_strategy` configuration setting. According to the source code in `get-shit-done/bin/gsd-tools.cjs`, the default configuration is:

```javascript
defaults = {
  branching_strategy: 'none',
  phase_branch_template: 'gsd/phase-{phase}-{slug}',
  milestone_branch_template: 'gsd/{milestone}-{slug}',
}

```

The three strategies work as follows:

- **`none`** (default): All commits occur on the current branch (typically `main`). No new branches are created during execution.
- **`phase`**: Creates a separate branch for each phase of a milestone. The branch is created when the first `gsd execute-phase` command runs for that specific phase.
- **`milestone`**: Creates a single branch shared across all phases belonging to the same milestone. The branch is created at the start of the first phase in the milestone.

The branch naming templates use placeholder variables that are resolved at runtime:
- `{phase}`: The phase number (zero-padded to two digits)
- `{milestone}`: The milestone version identifier
- `{slug}`: A URL-friendly identifier for the phase or milestone

## How GSD-Build Creates Branches During Execution

### Configuration Initialization

When a workflow starts via `gsd execute-phase`, the CLI reads the configuration to determine the `branching_strategy`, `phase_branch_template`, and `milestone_branch_template` values. This initialization logic is implemented in `get-shit-done/bin/gsd-tools.cjs` at lines 199-202.

### The Handle Branching Step

Inside [`get-shit-done/workflows/execute-phase.md`](https://github.com/gsd-build/get-shit-done/blob/main/get-shit-done/workflows/execute-phase.md), the `handle_branching` step executes the following logic:

1. **Strategy Check**: If `branching_strategy` is set to `"none"`, the step skips branch handling and remains on the current branch.
2. **Branch Name Computation**: For `"phase"` or `"milestone"` strategies, the system computes the `branch_name` using the appropriate template.
3. **Branch Creation**: Executes `git checkout -b $branch_name` or `git switch -c $branch_name` if the branch does not yet exist.

```bash

# Conceptual implementation from handle_branching

if [ -n "$BRANCH_NAME" ]; then
  git switch -c "$BRANCH_NAME"
fi

# Subsequent commits target $BRANCH_NAME

```

### Commit Phase Work

Once the branch is created and checked out, all plan and documentation commits generated during that phase execution are applied to this branch rather than the default branch.

### Milestone Completion Handling

When `gsd complete-milestone` runs, the `handle_branches` step in [`get-shit-done/workflows/complete-milestone.md`](https://github.com/gsd-build/get-shit-done/blob/main/get-shit-done/workflows/complete-milestone.md) inspects the strategy, lists created branches using `git branch --list "${BRANCH_PREFIX}*"`, and presents merge options to the user:

- **Squash merge**: Consolidates all branch commits into a single commit
- **Merge with history**: Preserves the complete commit history
- **Delete**: Removes the branch after merging
- **Keep**: Retains the branch without merging

```bash

# Example squash merge from complete-milestone.md

git merge --squash "$branch"
git commit -m "feat: $branch for v${VERSION}"

```

## Branch Lifecycle by Strategy

The branch lifecycle varies significantly based on the chosen strategy:

**`none`**: No branch lifecycle exists. All work commits directly to the current branch.

**`phase`**: One branch per phase lifecycle. Created at the start of each phase via `execute-phase`, optionally merged or deleted when `complete-milestone` runs.

**`milestone`**: Single branch per milestone lifecycle. Created at the first phase of the milestone, reused for subsequent phases, and handled collectively at milestone completion.

## Configuration Examples

To configure the `phase` branching strategy in your project settings:

```json
{
  "git": {
    "branching_strategy": "phase",
    "phase_branch_template": "gsd/phase-{phase}-{slug}",
    "milestone_branch_template": "gsd/{milestone}-{slug}"
  }
}

```

The branch name generation logic extracted from `gsd-tools.cjs` works as follows:

```javascript
function getBranchName({ phaseInfo, milestoneInfo, config }) {
  if (config.branching_strategy === 'phase' && phaseInfo) {
    return config.phase_branch_template
      .replace('{phase}', String(phaseInfo.number).padStart(2, '0'))
      .replace('{slug}', phaseInfo.slug);
  }
  if (config.branching_strategy === 'milestone' && milestoneInfo) {
    return config.milestone_branch_template
      .replace('{milestone}', milestoneInfo.version)
      .replace('{slug}', milestoneInfo.slug);
  }
  return null; // "none" strategy
}

```

## Summary

- GSD-Build offers three branching strategies configured via `git.branching_strategy`: `none`, `phase`, and `milestone`.
- Default values are defined in `get-shit-done/bin/gsd-tools.cjs`, with `none` as the default strategy.
- Branches are created during the `handle_branching` step of `execute-phase` workflows, not during planning or configuration.
- Branch names follow configurable templates using `{phase}`, `{milestone}`, and `{slug}` placeholders.
- The `complete-milestone` command handles branch cleanup through squash merges, standard merges, or deletion based on user selection.

## Frequently Asked Questions

### What is the default branching strategy in GSD-Build?

The default branching strategy is `none`, meaning all commits are made directly to the current branch without creating additional Git branches. This default is explicitly set in `get-shit-done/bin/gsd-tools.cjs` within the defaults configuration object.

### How does the phase strategy differ from the milestone strategy?

The `phase` strategy creates a new branch for every individual phase within a milestone (e.g., `gsd/phase-03-authentication`), while the `milestone` strategy creates one branch shared across all phases in a milestone (e.g., `gsd/v1.0-mvp`). The phase strategy provides granular isolation per phase, whereas the milestone strategy groups related work together.

### Can I customize branch naming templates?

Yes, you can customize branch naming by modifying the `phase_branch_template` and `milestone_branch_template` settings in your configuration file. These templates support the placeholders `{phase}`, `{milestone}`, and `{slug}`, which are dynamically replaced during execution based on the current milestone and phase metadata.

### When exactly are branches created during execution?

Branches are created at the beginning of phase execution, specifically within the `handle_branching` step documented in [`get-shit-done/workflows/execute-phase.md`](https://github.com/gsd-build/get-shit-done/blob/main/get-shit-done/workflows/execute-phase.md). If the branch already exists, the CLI switches to it; otherwise, it creates the branch using `git switch -c` before any plan-execution commits occur.