Skip to content

Commit b40b41c

Browse files
committed
fix: improve branch number detection to check all sources
- Use git ls-remote for more reliable remote branch detection - Check remote branches, local branches, AND specs directories - Match exact short-name pattern to avoid false positives - Ensures no duplicate numbers across all sources
1 parent 1f3d9b5 commit b40b41c

File tree

3 files changed

+61
-21
lines changed

3 files changed

+61
-21
lines changed

scripts/bash/create-new-feature.sh

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,21 @@ check_existing_branches() {
8787
# Fetch all remotes to get latest branch info (suppress errors if no remotes)
8888
git fetch --all --prune 2>/dev/null || true
8989

90-
# Find all branches matching the pattern (local and remote)
91-
local branches=$(git branch -a 2>/dev/null | grep -E "feature/[0-9]+-${short_name}$" | sed 's/.*feature\///' | sed "s/-${short_name}$//" | sort -n)
90+
# Find all branches matching the pattern using git ls-remote (more reliable)
91+
local remote_branches=$(git ls-remote --heads origin 2>/dev/null | grep -E "refs/heads/[0-9]+-${short_name}$" | sed 's/.*\/\([0-9]*\)-.*/\1/' | sort -n)
9292

93-
# Get the highest number
93+
# Also check local branches
94+
local local_branches=$(git branch 2>/dev/null | grep -E "^[* ]*[0-9]+-${short_name}$" | sed 's/^[* ]*//' | sed 's/-.*//' | sort -n)
95+
96+
# Check specs directory as well
97+
local spec_dirs=""
98+
if [ -d "$SPECS_DIR" ]; then
99+
spec_dirs=$(find "$SPECS_DIR" -maxdepth 1 -type d -name "[0-9]*-${short_name}" 2>/dev/null | xargs -n1 basename 2>/dev/null | sed 's/-.*//' | sort -n)
100+
fi
101+
102+
# Combine all sources and get the highest number
94103
local max_num=0
95-
for num in $branches; do
104+
for num in $remote_branches $local_branches $spec_dirs; do
96105
if [ "$num" -gt "$max_num" ]; then
97106
max_num=$num
98107
fi

scripts/powershell/create-new-feature.ps1

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ function Find-RepositoryRoot {
6161

6262
function Get-NextBranchNumber {
6363
param(
64-
[string]$ShortName
64+
[string]$ShortName,
65+
[string]$SpecsDir
6566
)
6667

6768
# Fetch all remotes to get latest branch info (suppress errors if no remotes)
@@ -71,13 +72,28 @@ function Get-NextBranchNumber {
7172
# Ignore fetch errors
7273
}
7374

74-
# Find all branches matching the pattern (local and remote)
75-
$branches = @()
75+
# Find remote branches matching the pattern using git ls-remote
76+
$remoteBranches = @()
7677
try {
77-
$allBranches = git branch -a 2>$null
78+
$remoteRefs = git ls-remote --heads origin 2>$null
79+
if ($remoteRefs) {
80+
$remoteBranches = $remoteRefs | Where-Object { $_ -match "refs/heads/(\d+)-$([regex]::Escape($ShortName))$" } | ForEach-Object {
81+
if ($_ -match "refs/heads/(\d+)-") {
82+
[int]$matches[1]
83+
}
84+
}
85+
}
86+
} catch {
87+
# Ignore errors
88+
}
89+
90+
# Check local branches
91+
$localBranches = @()
92+
try {
93+
$allBranches = git branch 2>$null
7894
if ($allBranches) {
79-
$branches = $allBranches | Where-Object { $_ -match "feature/(\d+)-$([regex]::Escape($ShortName))$" } | ForEach-Object {
80-
if ($_ -match "feature/(\d+)-") {
95+
$localBranches = $allBranches | Where-Object { $_ -match "^\*?\s*(\d+)-$([regex]::Escape($ShortName))$" } | ForEach-Object {
96+
if ($_ -match "(\d+)-") {
8197
[int]$matches[1]
8298
}
8399
}
@@ -86,9 +102,23 @@ function Get-NextBranchNumber {
86102
# Ignore errors
87103
}
88104

89-
# Get the highest number
105+
# Check specs directory
106+
$specDirs = @()
107+
if (Test-Path $SpecsDir) {
108+
try {
109+
$specDirs = Get-ChildItem -Path $SpecsDir -Directory | Where-Object { $_.Name -match "^(\d+)-$([regex]::Escape($ShortName))$" } | ForEach-Object {
110+
if ($_.Name -match "^(\d+)-") {
111+
[int]$matches[1]
112+
}
113+
}
114+
} catch {
115+
# Ignore errors
116+
}
117+
}
118+
119+
# Combine all sources and get the highest number
90120
$maxNum = 0
91-
foreach ($num in $branches) {
121+
foreach ($num in ($remoteBranches + $localBranches + $specDirs)) {
92122
if ($num -gt $maxNum) {
93123
$maxNum = $num
94124
}
@@ -178,7 +208,7 @@ if ($ShortName) {
178208
if ($Number -eq 0) {
179209
if ($hasGit) {
180210
# Check existing branches on remotes
181-
$Number = Get-NextBranchNumber -ShortName $branchSuffix
211+
$Number = Get-NextBranchNumber -ShortName $branchSuffix -SpecsDir $specsDir
182212
} else {
183213
# Fall back to local directory check
184214
$highest = 0

templates/commands/specify.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ Given that feature description, do this:
3838
git fetch --all --prune
3939
```
4040

41-
b. List all branches (local and remote) that match the short-name pattern:
42-
```bash
43-
git branch -a | grep -E "feature/[0-9]+-<short-name>$"
44-
```
41+
b. Find the highest feature number across all sources for the short-name:
42+
- Remote branches: `git ls-remote --heads origin | grep -E 'refs/heads/[0-9]+-<short-name>$'`
43+
- Local branches: `git branch | grep -E '^[* ]*[0-9]+-<short-name>$'`
44+
- Specs directories: Check for directories matching `specs/[0-9]+-<short-name>`
4545

4646
c. Determine the next available number:
47-
- Extract all numbers from existing branches (both local and remote)
48-
- Find the highest number N from branches that exist
47+
- Extract all numbers from all three sources
48+
- Find the highest number N
4949
- Use N+1 for the new branch number
5050

5151
d. Run the script `{SCRIPT}` with the calculated number and short-name:
@@ -54,8 +54,9 @@ Given that feature description, do this:
5454
- PowerShell example: `{SCRIPT} -Json -Number 5 -ShortName "user-auth" "Add user authentication"`
5555

5656
**IMPORTANT**:
57-
- Only consider branches that still exist (local or remote)
58-
- If no existing branches found with this short-name, start with number 1
57+
- Check all three sources (remote branches, local branches, specs directories) to find the highest number
58+
- Only match branches/directories with the exact short-name pattern
59+
- If no existing branches/directories found with this short-name, start with number 1
5960
- The JSON output will contain BRANCH_NAME and SPEC_FILE paths
6061
- You must only ever run this script once per feature
6162
- For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot")

0 commit comments

Comments
 (0)