-
Notifications
You must be signed in to change notification settings - Fork 509
refactor: replace git command for branch retrieval #371
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Updated multiple route handlers to use 'git symbolic-ref --short HEAD' instead of 'git rev-parse --abbrev-ref HEAD' for retrieving the current branch name, improving consistency and clarity in branch management across the application.
📝 WalkthroughWalkthroughReplaced the Git command for retrieving the current branch name across ten worktree routes. All instances of Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello @SuperComboGamer, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request refactors the application's approach to retrieving the current Git branch name. By standardizing the command used from Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request consistently refactors multiple route handlers to use git symbolic-ref --short HEAD instead of git rev-parse --abbrev-ref HEAD for retrieving the current branch name. This is a positive change that improves consistency and robustness, as symbolic-ref is generally the more appropriate command for this purpose and fails explicitly in detached HEAD states. The change is well-implemented across all relevant files. I have one minor suggestion to remove some unnecessary code.
|
|
||
| // Get current branch | ||
| const { stdout: currentBranch } = await execAsync('git rev-parse --abbrev-ref HEAD', { | ||
| const { stdout: currentBranch } = await execAsync('git symbolic-ref --short HEAD', { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🤖 Fix all issues with AI Agents
In @apps/server/src/routes/worktree/routes/checkout-branch.ts:
- Around line 50-53: The git symbolic-ref call can throw in detached HEAD state;
wrap the execAsync('git symbolic-ref --short HEAD', { cwd: worktreePath })
invocation used to compute currentBranch in checkout-branch.ts in a try/catch
and, on failure, call execAsync('git rev-parse HEAD', { cwd: worktreePath }) to
set previousBranch/currentBranch to the commit SHA (or alternatively return a
clear 4xx error that explains the detached HEAD) so branch creation via checkout
(e.g., git checkout -b) still works and you avoid unhandled 500s; update the
variables currentBranch/currentBranchOutput/previousBranch accordingly and apply
the same pattern to other handlers that use git symbolic-ref.
In @apps/server/src/routes/worktree/routes/create-pr.ts:
- Line 46: The current use of execAsync('git symbolic-ref --short HEAD', ...)
assigns to branchOutput but doesn't explicitly detect a detached HEAD; when that
command fails the outer catch returns a generic 500 with raw git stderr. Update
the handler to explicitly validate the current HEAD: run the branch lookup (or
use 'git rev-parse --abbrev-ref HEAD') and if the result is 'HEAD' or empty (or
the command exits non-zero) return a clear 400/422 response like "repository is
in a detached HEAD; worktrees must be created from a branch", instead of letting
the outer try-catch return a generic 500; factor this logic into a shared helper
(e.g., getCurrentBranchOrThrow or validateBranchOnBranch) so the same explicit
detached-HEAD check can be reused across the other worktree route files that use
branchOutput.
In @apps/server/src/routes/worktree/routes/list-branches.ts:
- Around line 37-40: The current code calls execAsync('git symbolic-ref --short
HEAD') and assumes success; wrap that call (the section producing
currentBranchOutput/currentBranch) in a try/catch, and on failure call
execAsync('git rev-parse --short HEAD') to get the commit SHA (trimmed) or set
currentBranch to a sentinel like "HEAD (detached)"; ensure you reuse execAsync
and assign to currentBranch so downstream logic still works and keep errors
non-fatal for the list-branches endpoint.
In @apps/server/src/routes/worktree/routes/merge.ts:
- Around line 38-40: Remove the unused currentBranch retrieval that calls
execAsync('git symbolic-ref --short HEAD', { cwd: projectPath }) — this can
throw on detached HEAD and its result is never used; delete the const { stdout:
currentBranch } = await execAsync(...) statement (and any immediate unused
variable) from merge.ts so the merge logic no longer executes the git
symbolic-ref command or relies on currentBranch.
In @apps/server/src/routes/worktree/routes/switch-branch.ts:
- Around line 90-93: The code assumes `git symbolic-ref --short HEAD` always
succeeds; wrap the execAsync call in try/catch and handle detached HEADs by
falling back to obtaining the current commit (e.g., run `git rev-parse --short
HEAD` via execAsync) or set previousBranch to a stable sentinel like
`HEAD@{detached}` so downstream logic can still switch branches; update
references to previousBranch (the variable set from currentBranchOutput) so they
tolerate the fallback value and ensure errors are only thrown for unexpected
failures (rethrow other exec errors).
🧹 Nitpick comments (1)
apps/server/src/routes/worktree/routes/info.ts (1)
34-34: Usegit branch --show-currentfor consistency with list.ts and modern Git practices.This worktree route currently uses
git symbolic-ref --short HEAD, but list.ts already usesgit branch --show-current(available since Git 2.22.0). The latter is purpose-built for this use case, returns an empty string gracefully in detached HEAD scenarios rather than throwing an error, and simplifies error handling. Consolidating all worktree route branch retrieval ongit branch --show-currentwould improve consistency across the codebase.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
apps/server/src/routes/worktree/routes/checkout-branch.tsapps/server/src/routes/worktree/routes/commit.tsapps/server/src/routes/worktree/routes/create-pr.tsapps/server/src/routes/worktree/routes/delete.tsapps/server/src/routes/worktree/routes/info.tsapps/server/src/routes/worktree/routes/list-branches.tsapps/server/src/routes/worktree/routes/merge.tsapps/server/src/routes/worktree/routes/pull.tsapps/server/src/routes/worktree/routes/push.tsapps/server/src/routes/worktree/routes/switch-branch.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Always import from shared packages (@automaker/*), never from old relative paths
Files:
apps/server/src/routes/worktree/routes/switch-branch.tsapps/server/src/routes/worktree/routes/delete.tsapps/server/src/routes/worktree/routes/merge.tsapps/server/src/routes/worktree/routes/list-branches.tsapps/server/src/routes/worktree/routes/create-pr.tsapps/server/src/routes/worktree/routes/push.tsapps/server/src/routes/worktree/routes/checkout-branch.tsapps/server/src/routes/worktree/routes/pull.tsapps/server/src/routes/worktree/routes/info.tsapps/server/src/routes/worktree/routes/commit.ts
apps/server/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use
createEventEmitter()fromlib/events.tsfor all server operations to emit events that stream to frontend via WebSocket
Files:
apps/server/src/routes/worktree/routes/switch-branch.tsapps/server/src/routes/worktree/routes/delete.tsapps/server/src/routes/worktree/routes/merge.tsapps/server/src/routes/worktree/routes/list-branches.tsapps/server/src/routes/worktree/routes/create-pr.tsapps/server/src/routes/worktree/routes/push.tsapps/server/src/routes/worktree/routes/checkout-branch.tsapps/server/src/routes/worktree/routes/pull.tsapps/server/src/routes/worktree/routes/info.tsapps/server/src/routes/worktree/routes/commit.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use
resolveModelString()from @automaker/model-resolver to convert model aliases (haiku, sonnet, opus) to full model names
Files:
apps/server/src/routes/worktree/routes/switch-branch.tsapps/server/src/routes/worktree/routes/delete.tsapps/server/src/routes/worktree/routes/merge.tsapps/server/src/routes/worktree/routes/list-branches.tsapps/server/src/routes/worktree/routes/create-pr.tsapps/server/src/routes/worktree/routes/push.tsapps/server/src/routes/worktree/routes/checkout-branch.tsapps/server/src/routes/worktree/routes/pull.tsapps/server/src/routes/worktree/routes/info.tsapps/server/src/routes/worktree/routes/commit.ts
🧠 Learnings (1)
📚 Learning: 2025-12-28T05:07:48.147Z
Learnt from: CR
Repo: AutoMaker-Org/automaker PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-28T05:07:48.147Z
Learning: Each feature executes in an isolated git worktree created via automaker/git-utils to protect the main branch during AI agent execution
Applied to files:
apps/server/src/routes/worktree/routes/merge.tsapps/server/src/routes/worktree/routes/info.ts
🧬 Code graph analysis (10)
apps/server/src/routes/worktree/routes/switch-branch.ts (1)
apps/server/src/routes/worktree/common.ts (1)
execAsync(13-13)
apps/server/src/routes/worktree/routes/delete.ts (1)
apps/server/src/routes/worktree/common.ts (1)
execAsync(13-13)
apps/server/src/routes/worktree/routes/merge.ts (1)
apps/server/src/routes/worktree/common.ts (1)
execAsync(13-13)
apps/server/src/routes/worktree/routes/list-branches.ts (1)
apps/server/src/routes/worktree/common.ts (1)
execAsync(13-13)
apps/server/src/routes/worktree/routes/create-pr.ts (2)
apps/server/src/routes/github/routes/common.ts (1)
execAsync(11-11)apps/server/src/routes/worktree/common.ts (1)
execAsync(13-13)
apps/server/src/routes/worktree/routes/push.ts (1)
apps/server/src/routes/worktree/common.ts (1)
execAsync(13-13)
apps/server/src/routes/worktree/routes/checkout-branch.ts (1)
apps/server/src/routes/worktree/common.ts (1)
execAsync(13-13)
apps/server/src/routes/worktree/routes/pull.ts (1)
apps/server/src/routes/worktree/common.ts (1)
execAsync(13-13)
apps/server/src/routes/worktree/routes/info.ts (1)
apps/server/src/routes/worktree/common.ts (1)
execAsync(13-13)
apps/server/src/routes/worktree/routes/commit.ts (1)
apps/server/src/routes/worktree/common.ts (1)
execAsync(13-13)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: e2e
🔇 Additional comments (2)
apps/server/src/routes/worktree/routes/delete.ts (1)
41-47: Proper error handling for detached HEAD scenarios.The command change is safely wrapped in a try-catch block. When a repo is in a detached HEAD state,
git symbolic-ref --short HEADwill fail with "fatal: ref HEAD is not a symbolic ref", so the fallback tonullappropriately handles this edge case.apps/server/src/routes/worktree/routes/info.ts (1)
34-44: Proper error handling for detached HEAD scenarios.The command is appropriately wrapped in error handling that falls back to
nullvalues when the branch name cannot be determined, which is the correct behavior for an info endpoint.
| const { stdout: currentBranchOutput } = await execAsync('git symbolic-ref --short HEAD', { | ||
| cwd: worktreePath, | ||
| }); | ||
| const currentBranch = currentBranchOutput.trim(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
wc -l apps/server/src/routes/worktree/routes/checkout-branch.tsRepository: AutoMaker-Org/automaker
Length of output: 190
🏁 Script executed:
cat -n apps/server/src/routes/worktree/routes/checkout-branch.tsRepository: AutoMaker-Org/automaker
Length of output: 3121
🏁 Script executed:
rg -n 'detached|symbolic-ref|previousBranch' apps/server/src/routes/worktree/ --type=tsRepository: AutoMaker-Org/automaker
Length of output: 1996
🏁 Script executed:
# Search for tests related to checkout-branch or detached HEAD
fd -t f '*.test.ts' -o '*.spec.ts' apps/server | xargs rg -l 'checkout.*branch|detached' 2>/dev/null || echo "No matching test files found"Repository: AutoMaker-Org/automaker
Length of output: 700
🏁 Script executed:
# Check the middleware mentioned in the file (requireValidWorktree)
rg -n 'requireValidWorktree' apps/server/src/routes/worktree/ --type=ts -A 5Repository: AutoMaker-Org/automaker
Length of output: 5583
🏁 Script executed:
# Check what happens with git symbolic-ref on detached HEAD
# Look at the actual error message and understand the implications
rg -n 'symbolic-ref' apps/server/src/ --type=ts | head -20Repository: AutoMaker-Org/automaker
Length of output: 1503
🏁 Script executed:
# Check if there's any documentation or TODOs about this
rg -n 'TODO|FIXME|detached|HEAD' apps/server/src/routes/worktree/ --type=tsRepository: AutoMaker-Org/automaker
Length of output: 3028
🏁 Script executed:
cat -n apps/server/src/routes/worktree/middleware.ts | head -100Repository: AutoMaker-Org/automaker
Length of output: 2746
🏁 Script executed:
# Check what the middleware validation does
rg -n 'isGitRepo\|hasCommits' apps/server/src/routes/worktree/ --type=ts -B 2 -A 5Repository: AutoMaker-Org/automaker
Length of output: 49
🏁 Script executed:
# Check if there are any existing tests for worktree operations
find apps/server -type f -name '*.test.*' -o -name '*.spec.*' | head -10Repository: AutoMaker-Org/automaker
Length of output: 613
🏁 Script executed:
cat -n apps/server/tests/integration/routes/worktree/create.integration.test.ts | head -150Repository: AutoMaker-Org/automaker
Length of output: 2489
🏁 Script executed:
# Check if there are any tests for checkout-branch, switch-branch, or detached HEAD scenarios
rg -n 'checkout.*branch|switch.*branch|detached' apps/server/tests/ --type=tsRepository: AutoMaker-Org/automaker
Length of output: 49
🏁 Script executed:
# Understand what git symbolic-ref error looks like and what the implications are
# Let's check the common.ts to see how errors are handled
cat -n apps/server/src/routes/worktree/common.tsRepository: AutoMaker-Org/automaker
Length of output: 7421
🏁 Script executed:
# Verify what error message git symbolic-ref produces in detached HEAD
# Check if there are any related issues or PRs mentioned in the codebase
rg -n 'detached.*HEAD|symbolic.*ref' docs/ CONTRIBUTING.md README.md 2>/dev/null || echo "No docs mention detached HEAD"Repository: AutoMaker-Org/automaker
Length of output: 96
🏁 Script executed:
# Confirm the systematic nature by checking all files that use symbolic-ref without error handling
rg -l 'symbolic-ref.*HEAD' apps/server/src/routes/worktree/routes/ --type=ts | wc -lRepository: AutoMaker-Org/automaker
Length of output: 69
Handle detached HEAD state across symbolic-ref calls.
The git symbolic-ref --short HEAD call will fail when the repository is in a detached HEAD state, even though the repository passes all middleware validation (which only checks that commits exist via git rev-parse --verify HEAD). This affects 10 files in the worktree routes and causes ungraceful 500 errors with generic messages instead of informative feedback.
For checkout-branch.ts specifically: creating a branch from detached HEAD is a valid Git operation (git checkout -b works fine), but retrieving the previous branch state fails. Consider wrapping the git symbolic-ref call in a try-catch to either:
- Set
previousBranchto the commit SHA (viagit rev-parse HEAD) when detached - Return a clear error message explaining detached HEAD state
This pattern should be addressed consistently across all symbolic-ref calls in the worktree route handlers.
🤖 Prompt for AI Agents
In @apps/server/src/routes/worktree/routes/checkout-branch.ts around lines
50-53, The git symbolic-ref call can throw in detached HEAD state; wrap the
execAsync('git symbolic-ref --short HEAD', { cwd: worktreePath }) invocation
used to compute currentBranch in checkout-branch.ts in a try/catch and, on
failure, call execAsync('git rev-parse HEAD', { cwd: worktreePath }) to set
previousBranch/currentBranch to the commit SHA (or alternatively return a clear
4xx error that explains the detached HEAD) so branch creation via checkout
(e.g., git checkout -b) still works and you avoid unhandled 500s; update the
variables currentBranch/currentBranchOutput/previousBranch accordingly and apply
the same pattern to other handlers that use git symbolic-ref.
| const { stdout: branchOutput } = await execAsync('git symbolic-ref --short HEAD', { | ||
| cwd: worktreePath, | ||
| }); | ||
| const branchName = branchOutput.trim(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing error handling for detached HEAD state.
In a detached HEAD state, git symbolic-ref --short HEAD will fail with an error, causing the entire handler to return a 500 error even though the commit operation itself (line 51) succeeded. This could confuse users and lose context about the successful commit.
🔎 Proposed fix to add error handling
- // Get branch name
- const { stdout: branchOutput } = await execAsync('git symbolic-ref --short HEAD', {
- cwd: worktreePath,
- });
- const branchName = branchOutput.trim();
+ // Get branch name (may be null in detached HEAD state)
+ let branchName: string | null = null;
+ try {
+ const { stdout: branchOutput } = await execAsync('git symbolic-ref --short HEAD', {
+ cwd: worktreePath,
+ });
+ branchName = branchOutput.trim();
+ } catch {
+ // Detached HEAD state - branch name unavailable
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const { stdout: branchOutput } = await execAsync('git symbolic-ref --short HEAD', { | |
| cwd: worktreePath, | |
| }); | |
| const branchName = branchOutput.trim(); | |
| // Get branch name (may be null in detached HEAD state) | |
| let branchName: string | null = null; | |
| try { | |
| const { stdout: branchOutput } = await execAsync('git symbolic-ref --short HEAD', { | |
| cwd: worktreePath, | |
| }); | |
| branchName = branchOutput.trim(); | |
| } catch { | |
| // Detached HEAD state - branch name unavailable | |
| } |
|
|
||
| // Get current branch name | ||
| const { stdout: branchOutput } = await execAsync('git rev-parse --abbrev-ref HEAD', { | ||
| const { stdout: branchOutput } = await execAsync('git symbolic-ref --short HEAD', { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let's examine the file and context around line 46
cat -n apps/server/src/routes/worktree/routes/create-pr.ts | sed -n '30,60p'Repository: AutoMaker-Org/automaker
Length of output: 1204
🏁 Script executed:
# Run the provided search for detached HEAD handling
rg -n -C3 'detached.HEAD|HEAD detached' --type=tsRepository: AutoMaker-Org/automaker
Length of output: 49
🏁 Script executed:
# Also search for git symbolic-ref usage in the codebase
rg -n 'git symbolic-ref' --type=tsRepository: AutoMaker-Org/automaker
Length of output: 1503
🏁 Script executed:
# Search for error handling around the git command in the file
cat -n apps/server/src/routes/worktree/routes/create-pr.ts | head -100Repository: AutoMaker-Org/automaker
Length of output: 4097
🏁 Script executed:
# View the rest of the create-pr.ts file to see error handling
cat -n apps/server/src/routes/worktree/routes/create-pr.ts | sed -n '100,150p'Repository: AutoMaker-Org/automaker
Length of output: 2128
🏁 Script executed:
# Check the common.ts to understand execAsync error behavior
cat -n apps/server/src/routes/worktree/routes/common.ts | head -80Repository: AutoMaker-Org/automaker
Length of output: 147
🏁 Script executed:
# Check if there's worktree initialization that ensures non-detached HEAD
rg -n -C5 'worktree create|worktree add' --type=tsRepository: AutoMaker-Org/automaker
Length of output: 4737
🏁 Script executed:
# Find common.ts in the worktree routes
find apps/server/src/routes/worktree -name "common.ts"Repository: AutoMaker-Org/automaker
Length of output: 108
🏁 Script executed:
# Check the error handling wrapper that execAsync would trigger
cat -n apps/server/src/routes/worktree/common.ts | head -100Repository: AutoMaker-Org/automaker
Length of output: 4136
🏁 Script executed:
# Look at the try-catch block in create-pr.ts to see what happens when execAsync throws
cat -n apps/server/src/routes/worktree/routes/create-pr.ts | sed -n '150,200p'Repository: AutoMaker-Org/automaker
Length of output: 2516
🏁 Script executed:
# Check the final catch block of the create-pr.ts handler to see generic error handling
cat -n apps/server/src/routes/worktree/routes/create-pr.ts | tail -50Repository: AutoMaker-Org/automaker
Length of output: 2008
Add explicit detached HEAD error handling.
The git symbolic-ref --short HEAD command fails in detached HEAD state and lacks explicit error handling. While the outer try-catch (line 397) catches this failure, it returns a generic 500 error with raw git stderr. Since worktrees are created on branches and this pattern is used consistently across 10 worktree route files, either:
- Add explicit detached HEAD validation that returns a clear error message, or
- Document the assumption that worktrees are always on branches (and validate accordingly)
The current implicit error handling via the generic catch block is insufficient for user guidance.
🤖 Prompt for AI Agents
In @apps/server/src/routes/worktree/routes/create-pr.ts around line 46, The
current use of execAsync('git symbolic-ref --short HEAD', ...) assigns to
branchOutput but doesn't explicitly detect a detached HEAD; when that command
fails the outer catch returns a generic 500 with raw git stderr. Update the
handler to explicitly validate the current HEAD: run the branch lookup (or use
'git rev-parse --abbrev-ref HEAD') and if the result is 'HEAD' or empty (or the
command exits non-zero) return a clear 400/422 response like "repository is in a
detached HEAD; worktrees must be created from a branch", instead of letting the
outer try-catch return a generic 500; factor this logic into a shared helper
(e.g., getCurrentBranchOrThrow or validateBranchOnBranch) so the same explicit
detached-HEAD check can be reused across the other worktree route files that use
branchOutput.
| const { stdout: currentBranchOutput } = await execAsync('git symbolic-ref --short HEAD', { | ||
| cwd: worktreePath, | ||
| }); | ||
| const currentBranch = currentBranchOutput.trim(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# Check if the file exists and examine the relevant lines
if [ -f "apps/server/src/routes/worktree/routes/list-branches.ts" ]; then
echo "=== File exists, showing context around lines 37-40 ==="
wc -l apps/server/src/routes/worktree/routes/list-branches.ts
echo ""
echo "=== Lines 30-50 ==="
sed -n '30,50p' apps/server/src/routes/worktree/routes/list-branches.ts
else
echo "File not found at specified path"
fiRepository: AutoMaker-Org/automaker
Length of output: 938
🏁 Script executed:
# Search for similar git symbolic-ref patterns in the codebase
echo "=== Searching for git symbolic-ref usage ==="
rg "git symbolic-ref" --type ts --type tsx -nRepository: AutoMaker-Org/automaker
Length of output: 156
🏁 Script executed:
# Search for git rev-parse usage to understand common patterns
echo "=== Searching for git rev-parse usage ==="
rg "git rev-parse" --type ts --type tsx -n -A 2Repository: AutoMaker-Org/automaker
Length of output: 153
🏁 Script executed:
# Search for git symbolic-ref and git rev-parse with correct syntax
echo "=== Searching for git symbolic-ref usage ==="
rg "git symbolic-ref" --type ts -n
echo ""
echo "=== Searching for git rev-parse usage ==="
rg "git rev-parse" --type ts -n -A 2Repository: AutoMaker-Org/automaker
Length of output: 4748
🏁 Script executed:
# Examine the full function to understand its purpose and callers
echo "=== Full function context (lines 1-60) ==="
sed -n '1,60p' apps/server/src/routes/worktree/routes/list-branches.tsRepository: AutoMaker-Org/automaker
Length of output: 1977
🏁 Script executed:
# Check if there are error handlers elsewhere in the codebase for execAsync
echo "=== Searching for execAsync error handling patterns ==="
rg "execAsync" --type ts -A 3 | head -50Repository: AutoMaker-Org/automaker
Length of output: 2952
Add graceful handling for detached HEAD state.
The git symbolic-ref --short HEAD command fails when the worktree is in a detached HEAD state, causing the entire list-branches endpoint to fail. For a read-only list operation, this significantly degrades UX. Catch the error and fall back to git rev-parse --short HEAD to display the commit SHA, or use a sentinel value like "HEAD (detached)".
Proposed fix
- const { stdout: currentBranchOutput } = await execAsync('git symbolic-ref --short HEAD', {
- cwd: worktreePath,
- });
- const currentBranch = currentBranchOutput.trim();
+ let currentBranch: string;
+ try {
+ const { stdout: currentBranchOutput } = await execAsync('git symbolic-ref --short HEAD', {
+ cwd: worktreePath,
+ });
+ currentBranch = currentBranchOutput.trim();
+ } catch {
+ // Detached HEAD state - use commit SHA
+ const { stdout: commitSha } = await execAsync('git rev-parse --short HEAD', {
+ cwd: worktreePath,
+ });
+ currentBranch = `HEAD (detached at ${commitSha.trim()})`;
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const { stdout: currentBranchOutput } = await execAsync('git symbolic-ref --short HEAD', { | |
| cwd: worktreePath, | |
| }); | |
| const currentBranch = currentBranchOutput.trim(); | |
| let currentBranch: string; | |
| try { | |
| const { stdout: currentBranchOutput } = await execAsync('git symbolic-ref --short HEAD', { | |
| cwd: worktreePath, | |
| }); | |
| currentBranch = currentBranchOutput.trim(); | |
| } catch { | |
| // Detached HEAD state - use commit SHA | |
| const { stdout: commitSha } = await execAsync('git rev-parse --short HEAD', { | |
| cwd: worktreePath, | |
| }); | |
| currentBranch = `HEAD (detached at ${commitSha.trim()})`; | |
| } |
🤖 Prompt for AI Agents
In @apps/server/src/routes/worktree/routes/list-branches.ts around lines 37-40,
The current code calls execAsync('git symbolic-ref --short HEAD') and assumes
success; wrap that call (the section producing
currentBranchOutput/currentBranch) in a try/catch, and on failure call
execAsync('git rev-parse --short HEAD') to get the commit SHA (trimmed) or set
currentBranch to a sentinel like "HEAD (detached)"; ensure you reuse execAsync
and assign to currentBranch so downstream logic still works and keep errors
non-fatal for the list-branches endpoint.
| const { stdout: currentBranch } = await execAsync('git symbolic-ref --short HEAD', { | ||
| cwd: projectPath, | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
cat -n apps/server/src/routes/worktree/routes/merge.tsRepository: AutoMaker-Org/automaker
Length of output: 2860
Remove unused currentBranch variable—the git symbolic-ref command will fail in detached HEAD state and is never used.
Lines 38-40 fetch the current branch name but never reference it in the merge logic. The command will throw an error if the repository is in a detached HEAD state, with no error handling. Delete these lines entirely since the merge operation does not depend on knowing the current branch.
🤖 Prompt for AI Agents
In @apps/server/src/routes/worktree/routes/merge.ts around lines 38-40, Remove
the unused currentBranch retrieval that calls execAsync('git symbolic-ref
--short HEAD', { cwd: projectPath }) — this can throw on detached HEAD and its
result is never used; delete the const { stdout: currentBranch } = await
execAsync(...) statement (and any immediate unused variable) from merge.ts so
the merge logic no longer executes the git symbolic-ref command or relies on
currentBranch.
| const { stdout: branchOutput } = await execAsync('git symbolic-ref --short HEAD', { | ||
| cwd: worktreePath, | ||
| }); | ||
| const branchName = branchOutput.trim(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing error handling for detached HEAD state.
When a repo is in a detached HEAD state, git symbolic-ref --short HEAD will fail, causing the handler to return a generic 500 error rather than a meaningful message about the detached HEAD state.
🔎 Proposed fix to add error handling
- // Get current branch name
- const { stdout: branchOutput } = await execAsync('git symbolic-ref --short HEAD', {
- cwd: worktreePath,
- });
- const branchName = branchOutput.trim();
+ // Get current branch name
+ let branchName: string;
+ try {
+ const { stdout: branchOutput } = await execAsync('git symbolic-ref --short HEAD', {
+ cwd: worktreePath,
+ });
+ branchName = branchOutput.trim();
+ } catch {
+ res.status(400).json({
+ success: false,
+ error: 'Cannot pull: worktree is in detached HEAD state',
+ });
+ return;
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const { stdout: branchOutput } = await execAsync('git symbolic-ref --short HEAD', { | |
| cwd: worktreePath, | |
| }); | |
| const branchName = branchOutput.trim(); | |
| // Get current branch name | |
| let branchName: string; | |
| try { | |
| const { stdout: branchOutput } = await execAsync('git symbolic-ref --short HEAD', { | |
| cwd: worktreePath, | |
| }); | |
| branchName = branchOutput.trim(); | |
| } catch { | |
| res.status(400).json({ | |
| success: false, | |
| error: 'Cannot pull: worktree is in detached HEAD state', | |
| }); | |
| return; | |
| } |
|
|
||
| // Get branch name | ||
| const { stdout: branchOutput } = await execAsync('git rev-parse --abbrev-ref HEAD', { | ||
| const { stdout: branchOutput } = await execAsync('git symbolic-ref --short HEAD', { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
cat -n apps/server/src/routes/worktree/routes/push.ts | head -80Repository: AutoMaker-Org/automaker
Length of output: 2256
🏁 Script executed:
#!/bin/bash
# Create a temporary test repository
TEST_DIR=$(mktemp -d)
cd "$TEST_DIR"
git init
# Create initial commit
echo "test" > file.txt
git add file.txt
git commit -m "initial"
# Get the commit hash
COMMIT_HASH=$(git rev-parse HEAD)
# Test 1: Normal branch state
echo "=== Test 1: Normal branch state ==="
echo "git symbolic-ref --short HEAD:"
git symbolic-ref --short HEAD
echo "git rev-parse --abbrev-ref HEAD:"
git rev-parse --abbrev-ref HEAD
# Test 2: Detached HEAD state
echo ""
echo "=== Test 2: Detached HEAD state ==="
git checkout "$COMMIT_HASH"
echo "git symbolic-ref --short HEAD:"
git symbolic-ref --short HEAD 2>&1 || echo "FAILED with exit code: $?"
echo "git rev-parse --abbrev-ref HEAD:"
git rev-parse --abbrev-ref HEAD 2>&1
# Cleanup
cd /
rm -rf "$TEST_DIR"Repository: AutoMaker-Org/automaker
Length of output: 1868
🏁 Script executed:
#!/bin/bash
# Create a temporary test repository
TEST_DIR=$(mktemp -d)
cd "$TEST_DIR"
git init
# Configure git
git config user.email "test@example.com"
git config user.name "Test User"
# Create initial commit
echo "test" > file.txt
git add file.txt
git commit -m "initial"
# Get the commit hash
COMMIT_HASH=$(git rev-parse HEAD)
# Test 1: Normal branch state
echo "=== Test 1: Normal branch state ==="
echo "git symbolic-ref --short HEAD:"
git symbolic-ref --short HEAD
echo "Exit code: $?"
echo ""
echo "git rev-parse --abbrev-ref HEAD:"
git rev-parse --abbrev-ref HEAD
echo "Exit code: $?"
# Test 2: Detached HEAD state
echo ""
echo "=== Test 2: Detached HEAD state ==="
echo "Checking out commit: $COMMIT_HASH"
git checkout "$COMMIT_HASH"
echo ""
echo "Verifying detached HEAD:"
git symbolic-ref -q HEAD && echo "Still on branch" || echo "In detached HEAD state"
echo ""
echo "git symbolic-ref --short HEAD:"
git symbolic-ref --short HEAD 2>&1
echo "Exit code: $?"
echo ""
echo "git rev-parse --abbrev-ref HEAD:"
git rev-parse --abbrev-ref HEAD 2>&1
echo "Exit code: $?"
# Cleanup
cd /
rm -rf "$TEST_DIR"Repository: AutoMaker-Org/automaker
Length of output: 1829
Add error handling for detached HEAD state.
git symbolic-ref --short HEAD fails with exit code 128 in detached HEAD state (error: "ref HEAD is not a symbolic ref"). Since detached HEAD is a possible state in git worktrees, add specific error handling to gracefully inform the user instead of returning a generic 500 error.
Note: git rev-parse --abbrev-ref HEAD returns the string "HEAD" in detached state, not a commit SHA, so it's not a suitable alternative for this use case.
| const { stdout: currentBranchOutput } = await execAsync('git symbolic-ref --short HEAD', { | ||
| cwd: worktreePath, | ||
| }); | ||
| const previousBranch = currentBranchOutput.trim(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing error handling for detached HEAD state.
When in a detached HEAD state, git symbolic-ref --short HEAD will fail, causing a generic 500 error. However, switching branches from a detached HEAD is a valid operation that should be supported with better error handling.
🔎 Proposed fix to add error handling
- // Get current branch
- const { stdout: currentBranchOutput } = await execAsync('git symbolic-ref --short HEAD', {
- cwd: worktreePath,
- });
- const previousBranch = currentBranchOutput.trim();
+ // Get current branch (may be in detached HEAD state)
+ let previousBranch: string;
+ try {
+ const { stdout: currentBranchOutput } = await execAsync('git symbolic-ref --short HEAD', {
+ cwd: worktreePath,
+ });
+ previousBranch = currentBranchOutput.trim();
+ } catch {
+ previousBranch = 'detached HEAD';
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const { stdout: currentBranchOutput } = await execAsync('git symbolic-ref --short HEAD', { | |
| cwd: worktreePath, | |
| }); | |
| const previousBranch = currentBranchOutput.trim(); | |
| // Get current branch (may be in detached HEAD state) | |
| let previousBranch: string; | |
| try { | |
| const { stdout: currentBranchOutput } = await execAsync('git symbolic-ref --short HEAD', { | |
| cwd: worktreePath, | |
| }); | |
| previousBranch = currentBranchOutput.trim(); | |
| } catch { | |
| previousBranch = 'detached HEAD'; | |
| } |
🤖 Prompt for AI Agents
In @apps/server/src/routes/worktree/routes/switch-branch.ts around lines 90-93,
The code assumes `git symbolic-ref --short HEAD` always succeeds; wrap the
execAsync call in try/catch and handle detached HEADs by falling back to
obtaining the current commit (e.g., run `git rev-parse --short HEAD` via
execAsync) or set previousBranch to a stable sentinel like `HEAD@{detached}` so
downstream logic can still switch branches; update references to previousBranch
(the variable set from currentBranchOutput) so they tolerate the fallback value
and ensure errors are only thrown for unexpected failures (rethrow other exec
errors).
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.