From bcd7b30eefb5cc7001b97fe6e3fe5f5520addb3f Mon Sep 17 00:00:00 2001 From: LuoHui1 <3053763193@qq.com> Date: Thu, 18 Jun 2026 17:20:58 +0800 Subject: [PATCH 1/2] fix: count worktree branches in git extension numbering --- .../scripts/bash/create-new-feature-branch.sh | 2 +- .../powershell/create-new-feature-branch.ps1 | 2 +- tests/extensions/git/test_git_extension.py | 41 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/extensions/git/scripts/bash/create-new-feature-branch.sh b/extensions/git/scripts/bash/create-new-feature-branch.sh index 6fd3835659..8fb05369f6 100755 --- a/extensions/git/scripts/bash/create-new-feature-branch.sh +++ b/extensions/git/scripts/bash/create-new-feature-branch.sh @@ -127,7 +127,7 @@ get_highest_from_specs() { # Function to get highest number from git branches get_highest_from_branches() { - git branch -a 2>/dev/null | sed 's/^[* ]*//; s|^remotes/[^/]*/||' | _extract_highest_number + git branch -a 2>/dev/null | sed 's/^[+* ]*//; s|^remotes/[^/]*/||' | _extract_highest_number } # Extract the highest sequential feature number from a list of ref names (one per line). diff --git a/extensions/git/scripts/powershell/create-new-feature-branch.ps1 b/extensions/git/scripts/powershell/create-new-feature-branch.ps1 index 90ea51d19b..47f93e1866 100644 --- a/extensions/git/scripts/powershell/create-new-feature-branch.ps1 +++ b/extensions/git/scripts/powershell/create-new-feature-branch.ps1 @@ -88,7 +88,7 @@ function Get-HighestNumberFromBranches { $branches = git branch -a 2>$null if ($LASTEXITCODE -eq 0 -and $branches) { $cleanNames = $branches | ForEach-Object { - $_.Trim() -replace '^\*?\s+', '' -replace '^remotes/[^/]+/', '' + $_.Trim() -replace '^[+*]?\s+', '' -replace '^remotes/[^/]+/', '' } return Get-HighestNumberFromNames -Names $cleanNames } diff --git a/tests/extensions/git/test_git_extension.py b/tests/extensions/git/test_git_extension.py index 142463683c..950b7da371 100644 --- a/tests/extensions/git/test_git_extension.py +++ b/tests/extensions/git/test_git_extension.py @@ -89,6 +89,17 @@ def _write_config(project: Path, content: str) -> Path: return config_path +def _add_sibling_worktree(project: Path, path: Path, branch: str) -> None: + """Add a sibling worktree so `git branch -a` marks it with `+`.""" + subprocess.run( + ["git", "worktree", "add", "-q", "-b", branch, str(path), "HEAD"], + cwd=project, + check=True, + capture_output=True, + text=True, + ) + + # Git identity env vars for CI runners without global git config _GIT_ENV = { "GIT_AUTHOR_NAME": "Test User", @@ -312,6 +323,21 @@ def test_increments_from_existing_specs(self, tmp_path: Path): data = json.loads(result.stdout) assert data["FEATURE_NUM"] == "003" + def test_dry_run_counts_branches_checked_out_in_worktrees(self, tmp_path: Path): + """Branches checked out in sibling worktrees still reserve their prefix.""" + project = _setup_project(tmp_path / "project") + _add_sibling_worktree(project, tmp_path / "sibling-worktree", "007-worktree-feature") + + result = _run_bash( + "create-new-feature-branch.sh", project, + "--json", "--dry-run", "--short-name", "next", "Next feature", + ) + + assert result.returncode == 0, result.stderr + data = json.loads(result.stdout) + assert data["BRANCH_NAME"] == "008-next" + assert data["FEATURE_NUM"] == "008" + def test_no_git_graceful_degradation(self, tmp_path: Path): """create-new-feature-branch.sh works without git (outputs branch name, skips branch creation).""" project = _setup_project(tmp_path, git=False) @@ -351,6 +377,21 @@ def test_creates_branch_sequential(self, tmp_path: Path): data = json.loads(result.stdout) assert data["BRANCH_NAME"] == "001-user-auth" + def test_dry_run_counts_branches_checked_out_in_worktrees(self, tmp_path: Path): + """Branches checked out in sibling worktrees still reserve their prefix.""" + project = _setup_project(tmp_path / "project") + _add_sibling_worktree(project, tmp_path / "sibling-worktree", "007-worktree-feature") + + result = _run_pwsh( + "create-new-feature-branch.ps1", project, + "-Json", "-DryRun", "-ShortName", "next", "Next feature", + ) + + assert result.returncode == 0, result.stderr + data = json.loads(result.stdout) + assert data["BRANCH_NAME"] == "008-next" + assert data["FEATURE_NUM"] == "008" + def test_creates_branch_timestamp(self, tmp_path: Path): """Extension create-new-feature-branch.ps1 creates timestamp branch.""" project = _setup_project(tmp_path) From 2b0859fa976065b108a2e149a9fe8bf421d8f665 Mon Sep 17 00:00:00 2001 From: LuoHui1 <3053763193@qq.com> Date: Thu, 18 Jun 2026 22:14:27 +0800 Subject: [PATCH 2/2] fix: preserve literal plus branch prefixes --- .../scripts/bash/create-new-feature-branch.sh | 2 +- tests/extensions/git/test_git_extension.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/extensions/git/scripts/bash/create-new-feature-branch.sh b/extensions/git/scripts/bash/create-new-feature-branch.sh index 8fb05369f6..b6480f40fe 100755 --- a/extensions/git/scripts/bash/create-new-feature-branch.sh +++ b/extensions/git/scripts/bash/create-new-feature-branch.sh @@ -127,7 +127,7 @@ get_highest_from_specs() { # Function to get highest number from git branches get_highest_from_branches() { - git branch -a 2>/dev/null | sed 's/^[+* ]*//; s|^remotes/[^/]*/||' | _extract_highest_number + git branch -a 2>/dev/null | sed -E 's/^[+*][[:space:]]+//; s/^[[:space:]]+//; s|^remotes/[^/]*/||' | _extract_highest_number } # Extract the highest sequential feature number from a list of ref names (one per line). diff --git a/tests/extensions/git/test_git_extension.py b/tests/extensions/git/test_git_extension.py index 950b7da371..431af6df10 100644 --- a/tests/extensions/git/test_git_extension.py +++ b/tests/extensions/git/test_git_extension.py @@ -338,6 +338,25 @@ def test_dry_run_counts_branches_checked_out_in_worktrees(self, tmp_path: Path): assert data["BRANCH_NAME"] == "008-next" assert data["FEATURE_NUM"] == "008" + def test_dry_run_preserves_literal_plus_branch_prefix(self, tmp_path: Path): + """A literal leading plus in a branch name is not a git worktree marker.""" + project = _setup_project(tmp_path) + subprocess.run( + ["git", "branch", "+007-plus-prefix"], + cwd=project, + check=True, + ) + + result = _run_bash( + "create-new-feature-branch.sh", project, + "--json", "--dry-run", "--short-name", "next", "Next feature", + ) + + assert result.returncode == 0, result.stderr + data = json.loads(result.stdout) + assert data["BRANCH_NAME"] == "001-next" + assert data["FEATURE_NUM"] == "001" + def test_no_git_graceful_degradation(self, tmp_path: Path): """create-new-feature-branch.sh works without git (outputs branch name, skips branch creation).""" project = _setup_project(tmp_path, git=False)