diff --git a/commands/gsd/settings.md b/commands/gsd/settings.md
index b4b14aa1c..f508e6066 100644
--- a/commands/gsd/settings.md
+++ b/commands/gsd/settings.md
@@ -34,6 +34,7 @@ Parse current values (default to `true` if not present):
- `workflow.plan_check` — spawn plan checker during plan-phase
- `workflow.verifier` — spawn verifier during execute-phase
- `model_profile` — which model each agent uses (default: `balanced`)
+- `git.branching_strategy` — branching approach (default: `"none"`)
## 3. Present Settings
@@ -77,6 +78,16 @@ AskUserQuestion([
{ label: "Yes", description: "Verify must-haves after execution" },
{ label: "No", description: "Skip post-execution verification" }
]
+ },
+ {
+ question: "Git branching strategy?",
+ header: "Branching",
+ multiSelect: false,
+ options: [
+ { label: "None (Recommended)", description: "Commit directly to current branch" },
+ { label: "Per Phase", description: "Create branch for each phase (gsd/phase-{N}-{name})" },
+ { label: "Per Milestone", description: "Create branch for entire milestone (gsd/{version}-{name})" }
+ ]
}
])
```
@@ -95,6 +106,9 @@ Merge new settings into existing config.json:
"research": true/false,
"plan_check": true/false,
"verifier": true/false
+ },
+ "git": {
+ "branching_strategy": "none" | "phase" | "milestone"
}
}
```
@@ -116,6 +130,7 @@ Display:
| Plan Researcher | {On/Off} |
| Plan Checker | {On/Off} |
| Execution Verifier | {On/Off} |
+| Git Branching | {None/Per Phase/Per Milestone} |
These settings apply to future /gsd:plan-phase and /gsd:execute-phase runs.
@@ -130,7 +145,7 @@ Quick commands:
- [ ] Current config read
-- [ ] User presented with 4 settings (profile + 3 toggles)
-- [ ] Config updated with model_profile and workflow section
+- [ ] User presented with 5 settings (profile + 3 workflow toggles + git branching)
+- [ ] Config updated with model_profile, workflow, and git sections
- [ ] Changes confirmed to user
diff --git a/get-shit-done/references/planning-config.md b/get-shit-done/references/planning-config.md
index f55995b98..b0c65de88 100644
--- a/get-shit-done/references/planning-config.md
+++ b/get-shit-done/references/planning-config.md
@@ -7,6 +7,11 @@ Configuration options for `.planning/` directory behavior.
"planning": {
"commit_docs": true,
"search_gitignored": false
+},
+"git": {
+ "branching_strategy": "none",
+ "phase_branch_template": "gsd/phase-{phase}-{slug}",
+ "milestone_branch_template": "gsd/{milestone}-{slug}"
}
```
@@ -14,6 +19,9 @@ Configuration options for `.planning/` directory behavior.
|--------|---------|-------------|
| `commit_docs` | `true` | Whether to commit planning artifacts to git |
| `search_gitignored` | `false` | Add `--no-ignore` to broad rg searches |
+| `git.branching_strategy` | `"none"` | Git branching approach: `"none"`, `"phase"`, or `"milestone"` |
+| `git.phase_branch_template` | `"gsd/phase-{phase}-{slug}"` | Branch template for phase strategy |
+| `git.milestone_branch_template` | `"gsd/{milestone}-{slug}"` | Branch template for milestone strategy |
@@ -91,4 +99,80 @@ To use uncommitted mode:
+
+
+**Branching Strategies:**
+
+| Strategy | When branch created | Branch scope | Merge point |
+|----------|---------------------|--------------|-------------|
+| `none` | Never | N/A | N/A |
+| `phase` | At `execute-phase` start | Single phase | User merges after phase |
+| `milestone` | At first `execute-phase` of milestone | Entire milestone | At `complete-milestone` |
+
+**When `git.branching_strategy: "none"` (default):**
+- All work commits to current branch
+- Standard GSD behavior
+
+**When `git.branching_strategy: "phase"`:**
+- `execute-phase` creates/switches to a branch before execution
+- Branch name from `phase_branch_template` (e.g., `gsd/phase-03-authentication`)
+- All plan commits go to that branch
+- User merges branches manually after phase completion
+- `complete-milestone` offers to merge all phase branches
+
+**When `git.branching_strategy: "milestone"`:**
+- First `execute-phase` of milestone creates the milestone branch
+- Branch name from `milestone_branch_template` (e.g., `gsd/v1.0-mvp`)
+- All phases in milestone commit to same branch
+- `complete-milestone` offers to merge milestone branch to main
+
+**Template variables:**
+
+| Variable | Available in | Description |
+|----------|--------------|-------------|
+| `{phase}` | phase_branch_template | Zero-padded phase number (e.g., "03") |
+| `{slug}` | Both | Lowercase, hyphenated name |
+| `{milestone}` | milestone_branch_template | Milestone version (e.g., "v1.0") |
+
+**Checking the config:**
+
+```bash
+# Get branching strategy (default: none)
+BRANCHING_STRATEGY=$(cat .planning/config.json 2>/dev/null | grep -o '"branching_strategy"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*:.*"\([^"]*\)"/\1/' || echo "none")
+
+# Get phase branch template
+PHASE_BRANCH_TEMPLATE=$(cat .planning/config.json 2>/dev/null | grep -o '"phase_branch_template"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*:.*"\([^"]*\)"/\1/' || echo "gsd/phase-{phase}-{slug}")
+
+# Get milestone branch template
+MILESTONE_BRANCH_TEMPLATE=$(cat .planning/config.json 2>/dev/null | grep -o '"milestone_branch_template"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*:.*"\([^"]*\)"/\1/' || echo "gsd/{milestone}-{slug}")
+```
+
+**Branch creation:**
+
+```bash
+# For phase strategy
+if [ "$BRANCHING_STRATEGY" = "phase" ]; then
+ PHASE_SLUG=$(echo "$PHASE_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//')
+ BRANCH_NAME=$(echo "$PHASE_BRANCH_TEMPLATE" | sed "s/{phase}/$PADDED_PHASE/g" | sed "s/{slug}/$PHASE_SLUG/g")
+ git checkout -b "$BRANCH_NAME" 2>/dev/null || git checkout "$BRANCH_NAME"
+fi
+
+# For milestone strategy
+if [ "$BRANCHING_STRATEGY" = "milestone" ]; then
+ MILESTONE_SLUG=$(echo "$MILESTONE_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//')
+ BRANCH_NAME=$(echo "$MILESTONE_BRANCH_TEMPLATE" | sed "s/{milestone}/$MILESTONE_VERSION/g" | sed "s/{slug}/$MILESTONE_SLUG/g")
+ git checkout -b "$BRANCH_NAME" 2>/dev/null || git checkout "$BRANCH_NAME"
+fi
+```
+
+**Use cases:**
+
+| Strategy | Best for |
+|----------|----------|
+| `none` | Solo development, simple projects |
+| `phase` | Code review per phase, granular rollback, team collaboration |
+| `milestone` | Release branches, staging environments, PR per version |
+
+
+
diff --git a/get-shit-done/workflows/complete-milestone.md b/get-shit-done/workflows/complete-milestone.md
index 6a4d38ead..5f2d1a035 100644
--- a/get-shit-done/workflows/complete-milestone.md
+++ b/get-shit-done/workflows/complete-milestone.md
@@ -579,6 +579,125 @@ Progress: [updated progress bar]
+
+
+Check if branching was used and offer merge options.
+
+**Check branching strategy:**
+
+```bash
+# Get branching strategy from config
+BRANCHING_STRATEGY=$(cat .planning/config.json 2>/dev/null | grep -o '"branching_strategy"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*:.*"\([^"]*\)"/\1/' || echo "none")
+```
+
+**If strategy is "none":** Skip to git_tag step.
+
+**For "phase" strategy — find phase branches:**
+
+```bash
+PHASE_BRANCH_TEMPLATE=$(cat .planning/config.json 2>/dev/null | grep -o '"phase_branch_template"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*:.*"\([^"]*\)"/\1/' || echo "gsd/phase-{phase}-{slug}")
+
+# Extract prefix from template (before first variable)
+BRANCH_PREFIX=$(echo "$PHASE_BRANCH_TEMPLATE" | sed 's/{.*//')
+
+# Find all phase branches for this milestone
+PHASE_BRANCHES=$(git branch --list "${BRANCH_PREFIX}*" 2>/dev/null | sed 's/^\*//' | tr -d ' ')
+```
+
+**For "milestone" strategy — find milestone branch:**
+
+```bash
+MILESTONE_BRANCH_TEMPLATE=$(cat .planning/config.json 2>/dev/null | grep -o '"milestone_branch_template"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*:.*"\([^"]*\)"/\1/' || echo "gsd/{milestone}-{slug}")
+
+# Extract prefix from template
+BRANCH_PREFIX=$(echo "$MILESTONE_BRANCH_TEMPLATE" | sed 's/{.*//')
+
+# Find milestone branch
+MILESTONE_BRANCH=$(git branch --list "${BRANCH_PREFIX}*" 2>/dev/null | sed 's/^\*//' | tr -d ' ' | head -1)
+```
+
+**If no branches found:** Skip to git_tag step.
+
+**If branches exist — present merge options:**
+
+```
+## Git Branches Detected
+
+Branching strategy: {phase/milestone}
+
+Branches found:
+{list of branches}
+
+Options:
+1. **Merge to main** — Merge branch(es) to main
+2. **Delete without merging** — Branches already merged or not needed
+3. **Keep branches** — Leave for manual handling
+```
+
+Use AskUserQuestion:
+
+```
+AskUserQuestion([
+ {
+ question: "How should branches be handled?",
+ header: "Branches",
+ multiSelect: false,
+ options: [
+ { label: "Merge to main", description: "Merge all branches to main sequentially" },
+ { label: "Delete without merging", description: "Branches already merged or not needed" },
+ { label: "Keep branches", description: "Leave branches for manual handling later" }
+ ]
+ }
+])
+```
+
+**If "Merge to main":**
+
+```bash
+CURRENT_BRANCH=$(git branch --show-current)
+git checkout main
+
+# For phase strategy - merge each phase branch
+if [ "$BRANCHING_STRATEGY" = "phase" ]; then
+ for branch in $PHASE_BRANCHES; do
+ echo "Merging $branch..."
+ git merge --no-ff "$branch" -m "Merge branch '$branch' for v[X.Y]"
+ done
+fi
+
+# For milestone strategy - merge milestone branch
+if [ "$BRANCHING_STRATEGY" = "milestone" ]; then
+ echo "Merging $MILESTONE_BRANCH..."
+ git merge --no-ff "$MILESTONE_BRANCH" -m "Merge branch '$MILESTONE_BRANCH' for v[X.Y]"
+fi
+
+git checkout "$CURRENT_BRANCH"
+```
+
+Report: "Merged branches to main"
+
+**If "Delete without merging":**
+
+```bash
+if [ "$BRANCHING_STRATEGY" = "phase" ]; then
+ for branch in $PHASE_BRANCHES; do
+ git branch -d "$branch" 2>/dev/null || git branch -D "$branch"
+ done
+fi
+
+if [ "$BRANCHING_STRATEGY" = "milestone" ]; then
+ git branch -d "$MILESTONE_BRANCH" 2>/dev/null || git branch -D "$MILESTONE_BRANCH"
+fi
+```
+
+Report: "Deleted branches"
+
+**If "Keep branches":**
+
+Report: "Branches preserved for manual handling"
+
+
+
Create git tag for milestone:
diff --git a/get-shit-done/workflows/execute-phase.md b/get-shit-done/workflows/execute-phase.md
index 13aea74ba..f648aa9d8 100644
--- a/get-shit-done/workflows/execute-phase.md
+++ b/get-shit-done/workflows/execute-phase.md
@@ -65,6 +65,81 @@ git check-ignore -q .planning 2>/dev/null && COMMIT_PLANNING_DOCS=false
```
Store `COMMIT_PLANNING_DOCS` for use in git operations.
+
+**Load git branching config:**
+
+```bash
+# Get branching strategy (default: none)
+BRANCHING_STRATEGY=$(cat .planning/config.json 2>/dev/null | grep -o '"branching_strategy"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*:.*"\([^"]*\)"/\1/' || echo "none")
+
+# Get templates
+PHASE_BRANCH_TEMPLATE=$(cat .planning/config.json 2>/dev/null | grep -o '"phase_branch_template"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*:.*"\([^"]*\)"/\1/' || echo "gsd/phase-{phase}-{slug}")
+MILESTONE_BRANCH_TEMPLATE=$(cat .planning/config.json 2>/dev/null | grep -o '"milestone_branch_template"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*:.*"\([^"]*\)"/\1/' || echo "gsd/{milestone}-{slug}")
+```
+
+Store `BRANCHING_STRATEGY` and templates for use in branch creation step.
+
+
+
+Create or switch to appropriate branch based on branching strategy.
+
+**Skip if strategy is "none":**
+
+```bash
+if [ "$BRANCHING_STRATEGY" = "none" ]; then
+ # No branching, continue on current branch
+ exit 0
+fi
+```
+
+**For "phase" strategy — create phase branch:**
+
+```bash
+if [ "$BRANCHING_STRATEGY" = "phase" ]; then
+ # Get phase name from directory (e.g., "03-authentication" → "authentication")
+ PHASE_NAME=$(basename "$PHASE_DIR" | sed 's/^[0-9]*-//')
+
+ # Create slug from phase name
+ PHASE_SLUG=$(echo "$PHASE_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//')
+
+ # Apply template
+ BRANCH_NAME=$(echo "$PHASE_BRANCH_TEMPLATE" | sed "s/{phase}/$PADDED_PHASE/g" | sed "s/{slug}/$PHASE_SLUG/g")
+
+ # Create or switch to branch
+ git checkout -b "$BRANCH_NAME" 2>/dev/null || git checkout "$BRANCH_NAME"
+
+ echo "Branch: $BRANCH_NAME (phase branching)"
+fi
+```
+
+**For "milestone" strategy — create/switch to milestone branch:**
+
+```bash
+if [ "$BRANCHING_STRATEGY" = "milestone" ]; then
+ # Get current milestone info from ROADMAP.md
+ MILESTONE_VERSION=$(grep -oE 'v[0-9]+\.[0-9]+' .planning/ROADMAP.md | head -1 || echo "v1.0")
+ MILESTONE_NAME=$(grep -A1 "## .*$MILESTONE_VERSION" .planning/ROADMAP.md | tail -1 | sed 's/.*- //' | cut -d'(' -f1 | tr -d ' ' || echo "milestone")
+
+ # Create slug
+ MILESTONE_SLUG=$(echo "$MILESTONE_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//')
+
+ # Apply template
+ BRANCH_NAME=$(echo "$MILESTONE_BRANCH_TEMPLATE" | sed "s/{milestone}/$MILESTONE_VERSION/g" | sed "s/{slug}/$MILESTONE_SLUG/g")
+
+ # Create or switch to branch (same branch for all phases in milestone)
+ git checkout -b "$BRANCH_NAME" 2>/dev/null || git checkout "$BRANCH_NAME"
+
+ echo "Branch: $BRANCH_NAME (milestone branching)"
+fi
+```
+
+**Report branch status:**
+
+```
+Branching: {strategy} → {branch_name}
+```
+
+**Note:** All subsequent plan commits go to this branch. User handles merging based on their workflow.