fix: merge worktree handler now uses correct branch name and path

The merge handler previously hardcoded branch names as `feature/${featureId}`
and worktree paths as `.worktrees/${featureId}`, which failed for auto-generated
branches (e.g., `feature/v0.11.0rc-1768413895104-31pa`) and custom worktrees.

Changes:
- Server handler now accepts branchName and worktreePath directly from the UI
- Added branch existence validation before attempting merge
- Updated merge dialog with 2-step confirmation (type "merge" to confirm)
- Removed feature branch naming restriction - any branch can now be merged
- Updated API types and client to pass correct parameters

Closes #408

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Shirone
2026-01-14 20:49:17 +01:00
parent ca3286a374
commit ee0d0c6c59
10 changed files with 335 additions and 22 deletions

View File

@@ -8,7 +8,6 @@
import type { Request, Response } from 'express';
import { exec } from 'child_process';
import { promisify } from 'util';
import path from 'path';
import { getErrorMessage, logError } from '../common.js';
const execAsync = promisify(exec);
@@ -16,28 +15,31 @@ const execAsync = promisify(exec);
export function createMergeHandler() {
return async (req: Request, res: Response): Promise<void> => {
try {
const { projectPath, featureId, options } = req.body as {
const { projectPath, branchName, worktreePath, options } = req.body as {
projectPath: string;
featureId: string;
branchName: string;
worktreePath: string;
options?: { squash?: boolean; message?: string };
};
if (!projectPath || !featureId) {
if (!projectPath || !branchName || !worktreePath) {
res.status(400).json({
success: false,
error: 'projectPath and featureId required',
error: 'projectPath, branchName, and worktreePath are required',
});
return;
}
const branchName = `feature/${featureId}`;
// Git worktrees are stored in project directory
const worktreePath = path.join(projectPath, '.worktrees', featureId);
// Get current branch
const { stdout: currentBranch } = await execAsync('git rev-parse --abbrev-ref HEAD', {
cwd: projectPath,
});
// Validate branch exists
try {
await execAsync(`git rev-parse --verify ${branchName}`, { cwd: projectPath });
} catch {
res.status(400).json({
success: false,
error: `Branch "${branchName}" does not exist`,
});
return;
}
// Merge the feature branch
const mergeCmd = options?.squash