feat(mage): support existing branches in dev:prepare-worktree

Detect local and remote branches by name and check them out instead of
always creating a new one.
This commit is contained in:
kolaente 2026-04-16 13:40:18 +02:00
parent 3120c2b12c
commit 56a7db5a0d
No known key found for this signature in database
GPG Key ID: F40E70337AB24C9B
1 changed files with 33 additions and 2 deletions

View File

@ -1892,8 +1892,19 @@ func (Generate) ConfigYAML(commented bool) {
generateConfigYAMLFromJSON(DefaultConfigYAMLSamplePath, commented) generateConfigYAMLFromJSON(DefaultConfigYAMLSamplePath, commented)
} }
func localBranchExists(ctx context.Context, name string) bool {
return exec.CommandContext(ctx, "git", "show-ref", "--verify", "--quiet", "refs/heads/"+name).Run() == nil
}
func remoteBranchExists(ctx context.Context, name string) bool {
return exec.CommandContext(ctx, "git", "show-ref", "--verify", "--quiet", "refs/remotes/"+name).Run() == nil
}
// PrepareWorktree creates a new git worktree for development. // PrepareWorktree creates a new git worktree for development.
// The first argument is the name, which becomes both the folder name and branch name. // The first argument is the name, which becomes both the folder name and branch name.
// If a local branch with that name exists, it is checked out.
// If a remote branch origin/<name> exists, a local tracking branch is created.
// Otherwise a new branch is created.
// The second argument is a path to a plan file that will be moved to the new worktree (pass "" to skip). // The second argument is a path to a plan file that will be moved to the new worktree (pass "" to skip).
// The worktree is created in the parent directory (../). // The worktree is created in the parent directory (../).
// It also copies the current config.yml with an updated rootpath, and initializes the frontend. // It also copies the current config.yml with an updated rootpath, and initializes the frontend.
@ -1907,8 +1918,28 @@ func (Dev) PrepareWorktree(ctx context.Context, name string, planPath string) er
fmt.Printf("Creating worktree at %s with branch %s...\n", worktreePath, name) fmt.Printf("Creating worktree at %s with branch %s...\n", worktreePath, name)
// Create the git worktree // Refresh remote refs so remote-branch detection is reliable.
cmd := exec.CommandContext(ctx, "git", "worktree", "add", worktreePath, "-b", name) fetchCmd := exec.CommandContext(ctx, "git", "fetch", "origin")
fetchCmd.Stdout = os.Stdout
fetchCmd.Stderr = os.Stderr
if err := fetchCmd.Run(); err != nil {
fmt.Printf("Warning: git fetch failed: %v\n", err)
}
var worktreeArgs []string
switch {
case localBranchExists(ctx, name):
fmt.Printf("Local branch %s exists, checking it out.\n", name)
worktreeArgs = []string{"worktree", "add", worktreePath, name}
case remoteBranchExists(ctx, "origin/"+name):
fmt.Printf("Remote branch origin/%s exists, creating tracking branch.\n", name)
worktreeArgs = []string{"worktree", "add", "--track", "-b", name, worktreePath, "origin/" + name}
default:
fmt.Printf("Creating new branch %s.\n", name)
worktreeArgs = []string{"worktree", "add", worktreePath, "-b", name}
}
cmd := exec.CommandContext(ctx, "git", worktreeArgs...)
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {