Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion extensions/git/scripts/bash/create-new-feature.sh
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,11 @@ if [ "$DRY_RUN" != true ]; then
if [ "$ALLOW_EXISTING" = true ]; then
if [ "$current_branch" = "$BRANCH_NAME" ]; then
:
elif ! git checkout "$BRANCH_NAME" 2>/dev/null; then
elif ! switch_branch_error=$(git checkout -q "$BRANCH_NAME" 2>&1); then
>&2 echo "Error: Failed to switch to existing branch '$BRANCH_NAME'. Please resolve any local changes or conflicts and try again."
if [ -n "$switch_branch_error" ]; then
>&2 printf '%s\n' "$switch_branch_error"
fi
exit 1
fi
elif [ "$USE_TIMESTAMP" = true ]; then
Expand Down
8 changes: 6 additions & 2 deletions extensions/git/scripts/powershell/create-new-feature.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -327,9 +327,13 @@ if (-not $DryRun) {
if ($currentBranch -eq $branchName) {
# Already on the target branch
} else {
git checkout -q $branchName 2>$null | Out-Null
$switchBranchError = git checkout -q $branchName 2>&1 | Out-String
if ($LASTEXITCODE -ne 0) {
Write-Error "Error: Branch '$branchName' exists but could not be checked out. Resolve any uncommitted changes or conflicts and try again."
if ($switchBranchError) {
Write-Error "Error: Branch '$branchName' exists but could not be checked out.`n$($switchBranchError.Trim())"
} else {
Write-Error "Error: Branch '$branchName' exists but could not be checked out. Resolve any uncommitted changes or conflicts and try again."
}
exit 1
}
}
Expand Down
5 changes: 4 additions & 1 deletion scripts/bash/create-new-feature.sh
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,11 @@ if [ "$DRY_RUN" != true ]; then
if [ "$current_branch" = "$BRANCH_NAME" ]; then
:
# Otherwise switch to the existing branch instead of failing.
elif ! git checkout "$BRANCH_NAME" 2>/dev/null; then
elif ! switch_branch_error=$(git checkout -q "$BRANCH_NAME" 2>&1); then
>&2 echo "Error: Failed to switch to existing branch '$BRANCH_NAME'. Please resolve any local changes or conflicts and try again."
if [ -n "$switch_branch_error" ]; then
>&2 printf '%s\n' "$switch_branch_error"
fi
exit 1
fi
elif [ "$USE_TIMESTAMP" = true ]; then
Expand Down
8 changes: 6 additions & 2 deletions scripts/powershell/create-new-feature.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -315,9 +315,13 @@ if (-not $DryRun) {
# Already on the target branch — nothing to do
} else {
# Otherwise switch to the existing branch instead of failing.
git checkout -q $branchName 2>$null | Out-Null
$switchBranchError = git checkout -q $branchName 2>&1 | Out-String
if ($LASTEXITCODE -ne 0) {
Write-Error "Error: Branch '$branchName' exists but could not be checked out. Resolve any uncommitted changes or conflicts and try again."
if ($switchBranchError) {
Write-Error "Error: Branch '$branchName' exists but could not be checked out.`n$($switchBranchError.Trim())"
} else {
Write-Error "Error: Branch '$branchName' exists but could not be checked out. Resolve any uncommitted changes or conflicts and try again."
}
exit 1
}
}
Expand Down
63 changes: 63 additions & 0 deletions tests/test_timestamp_branches.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
PROJECT_ROOT = Path(__file__).resolve().parent.parent
CREATE_FEATURE = PROJECT_ROOT / "scripts" / "bash" / "create-new-feature.sh"
CREATE_FEATURE_PS = PROJECT_ROOT / "scripts" / "powershell" / "create-new-feature.ps1"
EXT_CREATE_FEATURE = (
PROJECT_ROOT / "extensions" / "git" / "scripts" / "bash" / "create-new-feature.sh"
)
EXT_CREATE_FEATURE_PS = (
PROJECT_ROOT / "extensions" / "git" / "scripts" / "powershell" / "create-new-feature.ps1"
)
COMMON_SH = PROJECT_ROOT / "scripts" / "bash" / "common.sh"


Expand Down Expand Up @@ -428,6 +434,43 @@ def test_allow_existing_no_git(self, no_git_dir: Path):
)
assert result.returncode == 0, result.stderr

def test_allow_existing_surfaces_checkout_error(self, git_repo: Path):
"""Checkout failures on an existing branch should include Git's stderr."""
shared_file = git_repo / "shared.txt"
shared_file.write_text("base\n")
subprocess.run(
["git", "add", "shared.txt"],
cwd=git_repo, check=True, capture_output=True,
)
subprocess.run(
["git", "commit", "-m", "add shared file", "-q"],
cwd=git_repo, check=True, capture_output=True,
)
subprocess.run(
["git", "checkout", "-b", "010-checkout-failure"],
cwd=git_repo, check=True, capture_output=True,
)
shared_file.write_text("branch version\n")
subprocess.run(
["git", "commit", "-am", "branch change", "-q"],
cwd=git_repo, check=True, capture_output=True,
)
subprocess.run(
["git", "checkout", "-"],
cwd=git_repo, check=True, capture_output=True,
)
shared_file.write_text("uncommitted main change\n")

result = run_script(
git_repo, "--allow-existing-branch", "--short-name", "checkout-failure",
"--number", "10", "Checkout failure",
)

assert result.returncode != 0, "checkout should fail with conflicting local changes"
assert "Failed to switch to existing branch '010-checkout-failure'" in result.stderr
assert "would be overwritten by checkout" in result.stderr
assert "shared.txt" in result.stderr


class TestAllowExistingBranchPowerShell:
def test_powershell_supports_allow_existing_branch_flag(self):
Expand All @@ -437,6 +480,26 @@ def test_powershell_supports_allow_existing_branch_flag(self):
# Ensure the flag is referenced in script logic, not just declared
assert "AllowExistingBranch" in contents.replace("-AllowExistingBranch", "")

def test_powershell_surfaces_checkout_errors(self):
"""Static guard: PS script preserves checkout stderr on existing-branch failures."""
contents = CREATE_FEATURE_PS.read_text(encoding="utf-8")
assert "$switchBranchError = git checkout -q $branchName 2>&1 | Out-String" in contents
assert "exists but could not be checked out.`n$($switchBranchError.Trim())" in contents


class TestGitExtensionParity:
def test_bash_extension_surfaces_checkout_errors(self):
"""Static guard: git extension bash script preserves checkout stderr."""
contents = EXT_CREATE_FEATURE.read_text(encoding="utf-8")
assert 'switch_branch_error=$(git checkout -q "$BRANCH_NAME" 2>&1)' in contents
assert "Failed to switch to existing branch '$BRANCH_NAME'" in contents

def test_powershell_extension_surfaces_checkout_errors(self):
"""Static guard: git extension PowerShell script preserves checkout stderr."""
contents = EXT_CREATE_FEATURE_PS.read_text(encoding="utf-8")
assert "$switchBranchError = git checkout -q $branchName 2>&1 | Out-String" in contents
assert "exists but could not be checked out.`n$($switchBranchError.Trim())" in contents


# ── Dry-Run Tests ────────────────────────────────────────────────────────────

Expand Down
Loading