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

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:

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, 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.

# 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 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

# 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:

{
  "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:

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. 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →