Feature/support branch prefix#2541
Open
leoxiao2012 wants to merge 6 commits into
Open
Conversation
Support custom branch prefixes (e.g. feature/, bugfix/, hotfix/) in auto-generated git branches. The agent chooses the prefix based on context and passes --branch-prefix to the script. Number extraction now handles prefixed branch names correctly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ensures consistent {prefix}/{number}-{suffix} format even when the
user omits the trailing slash (e.g. --branch-prefix "feature" becomes
"feature/").
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update command file and README to show prefixes without trailing slash and explain the auto-append behavior and final format. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shorter flag name consistent with --short-name and --number style. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds support for custom branch name prefixes (e.g., feature/, bugfix/, hotfix/) to the core and git-extension create-new-feature scripts, ensuring sequential number detection works correctly even when branches are prefixed. This aligns Spec Kit’s auto-generated branch naming with workflows like GitFlow while keeping prefix-less behavior backward compatible.
Changes:
- Add
--prefix(Bash) /-Prefix(PowerShell) options and normalize prefixes to end with/. - Update sequential number extraction to handle
prefix/003-nameformats and adjust 244-char truncation logic for prefix length. - Document prefix selection/usage in the git extension README and
speckit.git.featurecommand instructions.
Show a summary per file
| File | Description |
|---|---|
| scripts/powershell/create-new-feature.ps1 | Adds -Prefix, normalizes it, and includes it in branch construction and truncation math. |
| scripts/bash/create-new-feature.sh | Adds --prefix, normalizes it, and includes it in branch construction and truncation math. |
| extensions/git/scripts/powershell/create-new-feature.ps1 | Mirrors core PowerShell script changes for the git extension. |
| extensions/git/scripts/bash/create-new-feature.sh | Mirrors core Bash script changes for the git extension. |
| extensions/git/README.md | Documents optional branch prefixes and the resulting naming format. |
| extensions/git/commands/speckit.git.feature.md | Instructs agents how to choose prefixes and how to pass them to scripts. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 6/6 changed files
- Comments generated: 3
The rename from --branch-prefix to --prefix missed the error-path usage messages in three scripts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
mnriem
requested changes
May 13, 2026
Collaborator
mnriem
left a comment
There was a problem hiding this comment.
Please address Copilot feedback
Separate BRANCH_NAME (git ref, may include prefix like feature/) from FEATURE_DIR_NAME (directory-safe, no prefix) so that specs/ paths and sequential-number detection remain correct when a branch prefix is used. Also adds prefix validation (reject embedded slashes, trim whitespace) and 31 new pytest tests covering --prefix behavior across bash, ps1, and extension scripts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment on lines
+96
to
+110
| # Validate and normalize branch prefix | ||
| if [ -n "$BRANCH_PREFIX" ]; then | ||
| BRANCH_PREFIX=$(echo "$BRANCH_PREFIX" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') | ||
| if [ -z "$BRANCH_PREFIX" ]; then | ||
| echo 'Error: --prefix cannot be empty or whitespace' >&2 | ||
| exit 1 | ||
| fi | ||
| # Strip optional trailing '/' before checking for embedded slashes | ||
| _check_prefix="${BRANCH_PREFIX%/}" | ||
| if [[ "$_check_prefix" == */* ]]; then | ||
| echo 'Error: --prefix must be a single segment (no embedded slashes); e.g. "feature", "bugfix"' >&2 | ||
| exit 1 | ||
| fi | ||
| BRANCH_PREFIX="$_check_prefix/" | ||
| fi |
Comment on lines
+48
to
+61
| # Validate and normalize branch prefix | ||
| if ($Prefix) { | ||
| $Prefix = $Prefix.Trim() | ||
| if ([string]::IsNullOrWhiteSpace($Prefix)) { | ||
| Write-Error "Error: -Prefix cannot be empty or whitespace" | ||
| exit 1 | ||
| } | ||
| $checkPrefix = $Prefix.TrimEnd('/') | ||
| if ($checkPrefix.Contains('/')) { | ||
| Write-Error "Error: -Prefix must be a single segment (no embedded slashes); e.g. 'feature', 'bugfix'" | ||
| exit 1 | ||
| } | ||
| $Prefix = "$checkPrefix/" | ||
| } |
Comment on lines
+106
to
+120
| # Validate and normalize branch prefix | ||
| if [ -n "$BRANCH_PREFIX" ]; then | ||
| BRANCH_PREFIX=$(echo "$BRANCH_PREFIX" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') | ||
| if [ -z "$BRANCH_PREFIX" ]; then | ||
| echo 'Error: --prefix cannot be empty or whitespace' >&2 | ||
| exit 1 | ||
| fi | ||
| # Strip optional trailing '/' before checking for embedded slashes | ||
| _check_prefix="${BRANCH_PREFIX%/}" | ||
| if [[ "$_check_prefix" == */* ]]; then | ||
| echo 'Error: --prefix must be a single segment (no embedded slashes); e.g. "feature", "bugfix"' >&2 | ||
| exit 1 | ||
| fi | ||
| BRANCH_PREFIX="$_check_prefix/" | ||
| fi |
Comment on lines
+48
to
+61
| # Validate and normalize branch prefix | ||
| if ($Prefix) { | ||
| $Prefix = $Prefix.Trim() | ||
| if ([string]::IsNullOrWhiteSpace($Prefix)) { | ||
| Write-Error "Error: -Prefix cannot be empty or whitespace" | ||
| exit 1 | ||
| } | ||
| $checkPrefix = $Prefix.TrimEnd('/') | ||
| if ($checkPrefix.Contains('/')) { | ||
| Write-Error "Error: -Prefix must be a single segment (no embedded slashes); e.g. 'feature', 'bugfix'" | ||
| exit 1 | ||
| } | ||
| $Prefix = "$checkPrefix/" | ||
| } |
Comment on lines
342
to
349
| # GitHub enforces a 244-byte limit on branch names | ||
| # Validate and truncate if necessary | ||
| MAX_BRANCH_LENGTH=244 | ||
| if [ ${#BRANCH_NAME} -gt $MAX_BRANCH_LENGTH ]; then | ||
| # Calculate how much we need to trim from suffix | ||
| # Account for prefix length: timestamp (15) + hyphen (1) = 16, or sequential (3) + hyphen (1) = 4 | ||
| PREFIX_LENGTH=$(( ${#FEATURE_NUM} + 1 )) | ||
| PREFIX_LENGTH=$(( ${#BRANCH_PREFIX} + ${#FEATURE_NUM} + 1 )) | ||
| MAX_SUFFIX_LENGTH=$((MAX_BRANCH_LENGTH - PREFIX_LENGTH)) |
Comment on lines
292
to
299
| # GitHub enforces a 244-byte limit on branch names | ||
| # Validate and truncate if necessary | ||
| $maxBranchLength = 244 | ||
| if ($branchName.Length -gt $maxBranchLength) { | ||
| # Calculate how much we need to trim from suffix | ||
| # Account for prefix length: timestamp (15) + hyphen (1) = 16, or sequential (3) + hyphen (1) = 4 | ||
| $prefixLength = $featureNum.Length + 1 | ||
| $prefixLength = $Prefix.Length + $featureNum.Length + 1 | ||
| $maxSuffixLength = $maxBranchLength - $prefixLength |
Comment on lines
393
to
409
| # GitHub enforces a 244-byte limit on branch names | ||
| MAX_BRANCH_LENGTH=244 | ||
| _byte_length() { printf '%s' "$1" | LC_ALL=C wc -c | tr -d ' '; } | ||
| BRANCH_BYTE_LEN=$(_byte_length "$BRANCH_NAME") | ||
| if [ -n "${GIT_BRANCH_NAME:-}" ] && [ "$BRANCH_BYTE_LEN" -gt $MAX_BRANCH_LENGTH ]; then | ||
| >&2 echo "Error: GIT_BRANCH_NAME must be 244 bytes or fewer in UTF-8. Provided value is ${BRANCH_BYTE_LEN} bytes." | ||
| exit 1 | ||
| elif [ "$BRANCH_BYTE_LEN" -gt $MAX_BRANCH_LENGTH ]; then | ||
| PREFIX_LENGTH=$(( ${#FEATURE_NUM} + 1 )) | ||
| PREFIX_LENGTH=$(( ${#BRANCH_PREFIX} + ${#FEATURE_NUM} + 1 )) | ||
| MAX_SUFFIX_LENGTH=$((MAX_BRANCH_LENGTH - PREFIX_LENGTH)) | ||
|
|
||
| TRUNCATED_SUFFIX=$(echo "$BRANCH_SUFFIX" | cut -c1-$MAX_SUFFIX_LENGTH) | ||
| TRUNCATED_SUFFIX=$(echo "$TRUNCATED_SUFFIX" | sed 's/-$//') | ||
|
|
||
| ORIGINAL_BRANCH_NAME="$BRANCH_NAME" | ||
| BRANCH_NAME="${FEATURE_NUM}-${TRUNCATED_SUFFIX}" | ||
| BRANCH_NAME="${BRANCH_PREFIX}${FEATURE_NUM}-${TRUNCATED_SUFFIX}" | ||
|
|
Comment on lines
332
to
+341
| $maxBranchLength = 244 | ||
| if ($branchName.Length -gt $maxBranchLength) { | ||
| $prefixLength = $featureNum.Length + 1 | ||
| $prefixLength = $Prefix.Length + $featureNum.Length + 1 | ||
| $maxSuffixLength = $maxBranchLength - $prefixLength | ||
|
|
||
| $truncatedSuffix = $branchSuffix.Substring(0, [Math]::Min($branchSuffix.Length, $maxSuffixLength)) | ||
| $truncatedSuffix = $truncatedSuffix -replace '-$', '' | ||
|
|
||
| $originalBranchName = $branchName | ||
| $branchName = "$featureNum-$truncatedSuffix" | ||
| $branchName = "$Prefix$featureNum-$truncatedSuffix" |
| ) | ||
| assert result.returncode != 0 | ||
| assert "empty" in result.stderr.lower() or "whitespace" in result.stderr.lower() | ||
|
|
Collaborator
|
Please address Copilot feedback. If not applicable, please explain why |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Support custom branch prefixes (e.g. feature/, bugfix/, hotfix/) in auto-generated git branches. The agent chooses the prefix based on context and passes --prefix to the script. Number extraction now handles prefixed branch names correctly.
Description
Add --prefix (Bash) / -Prefix (PowerShell) option to create-new-feature scripts, enabling custom branch name prefixes such as feature, bugfix, or hotfix.
Motivation: Auto-generated branch names have a fixed format like 001-user-auth, which doesn't fit workflows like GitFlow that require category prefixes. Since the prefix varies by context (feature/bugfix/hotfix), it is not suitable as a fixed
config — the agent decides the appropriate prefix based on the nature of the work.
Changes:
Backward compatible: omitting --prefix produces identical behavior to before.
Testing
AI Disclosure
Code generated by Claude Code (Opus 4.6), reviewed and verified manually.