Skip to content

Feature/support branch prefix#2541

Open
leoxiao2012 wants to merge 6 commits into
github:mainfrom
leoxiao2012:feature/support-branch-prefix
Open

Feature/support branch prefix#2541
leoxiao2012 wants to merge 6 commits into
github:mainfrom
leoxiao2012:feature/support-branch-prefix

Conversation

@leoxiao2012
Copy link
Copy Markdown

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:

  • Add --prefix argument to 4 scripts (Bash × 2 + PowerShell × 2)
  • Auto-append / if missing, producing deterministic {prefix}/{number}-{short-name} format (e.g., --prefix "feature" → feature/001-auth)
  • Fix _extract_highest_number / Get-HighestNumberFromNames to correctly extract numbers from prefixed branch names (e.g., feature/003-name), preventing duplicate numbering
  • Update branch name construction and 244-byte truncation logic to account for prefix length
  • Update speckit.git.feature.md command instructions to guide agents on prefix selection
  • Update extensions/git/README.md with --prefix usage documentation

Backward compatible: omitting --prefix produces identical behavior to before.

Testing

  • bash create-new-feature.sh --dry-run --json --prefix "feature" --short-name "auth" "test" → {"BRANCH_NAME":"feature/001-auth","FEATURE_NUM":"001","DRY_RUN":true}
  • Without prefix — backward compatible → {"BRANCH_NAME":"001-auth","FEATURE_NUM":"001","DRY_RUN":true}
  • --help output includes new option

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (describe below)

Code generated by Claude Code (Opus 4.6), reviewed and verified manually.

leoxiao2012 and others added 4 commits May 13, 2026 17:59
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>
@leoxiao2012 leoxiao2012 requested a review from mnriem as a code owner May 13, 2026 10:22
@mnriem mnriem requested a review from Copilot May 13, 2026 13:15
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-name formats and adjust 244-char truncation logic for prefix length.
  • Document prefix selection/usage in the git extension README and speckit.git.feature command 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

Comment thread extensions/git/scripts/bash/create-new-feature.sh Outdated
Comment thread scripts/powershell/create-new-feature.ps1
Comment thread extensions/git/scripts/powershell/create-new-feature.ps1
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>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 7

Comment thread scripts/bash/create-new-feature.sh
Comment thread scripts/bash/create-new-feature.sh Outdated
Comment thread scripts/powershell/create-new-feature.ps1
Comment thread scripts/powershell/create-new-feature.ps1 Outdated
Comment thread extensions/git/scripts/bash/create-new-feature.sh
Comment thread extensions/git/scripts/bash/create-new-feature.sh Outdated
Comment thread extensions/git/scripts/powershell/create-new-feature.ps1 Outdated
Copy link
Copy Markdown
Collaborator

@mnriem mnriem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 7/7 changed files
  • Comments generated: 9

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()

@mnriem
Copy link
Copy Markdown
Collaborator

mnriem commented May 14, 2026

Please address Copilot feedback. If not applicable, please explain why

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants