feat: add Git worktree compatibility (PR #478)
Adds comprehensive Git worktree support for beads issue tracking: Core changes: - New internal/git/gitdir.go package for worktree detection - GetGitDir() returns proper .git location (main repo, not worktree) - Updated all hooks to use git.GetGitDir() instead of local helper - BeadsDir() now prioritizes main repository's .beads directory Features: - Hooks auto-install in main repo when run from worktree - Shared .beads directory across all worktrees - Config option no-install-hooks to disable auto-install - New bd worktree subcommand for diagnostics Documentation: - New docs/WORKTREES.md with setup instructions - Updated CHANGELOG.md and AGENT_INSTRUCTIONS.md Testing: - Updated tests to use exported git.GetGitDir() - Added worktree detection tests Co-authored-by: Claude <noreply@anthropic.com> Closes: #478
This commit is contained in:
@@ -738,11 +738,41 @@ func getRemoteForBranch(ctx context.Context, worktreePath, branch string) string
|
||||
}
|
||||
|
||||
// GetRepoRoot returns the git repository root directory
|
||||
// For worktrees, this returns the main repository root (not the worktree root)
|
||||
func GetRepoRoot(ctx context.Context) (string, error) {
|
||||
// Check if .git is a file (worktree) or directory (regular repo)
|
||||
gitPath := ".git"
|
||||
if info, err := os.Stat(gitPath); err == nil {
|
||||
if info.Mode().IsRegular() {
|
||||
// Worktree: read .git file
|
||||
content, err := os.ReadFile(gitPath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read .git file: %w", err)
|
||||
}
|
||||
line := strings.TrimSpace(string(content))
|
||||
if strings.HasPrefix(line, "gitdir: ") {
|
||||
gitDir := strings.TrimPrefix(line, "gitdir: ")
|
||||
// Remove /worktrees/* part
|
||||
if idx := strings.Index(gitDir, "/worktrees/"); idx > 0 {
|
||||
gitDir = gitDir[:idx]
|
||||
}
|
||||
return filepath.Dir(gitDir), nil
|
||||
}
|
||||
} else if info.IsDir() {
|
||||
// Regular repo: .git is a directory
|
||||
absGitPath, err := filepath.Abs(gitPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Dir(absGitPath), nil
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to git command
|
||||
cmd := exec.CommandContext(ctx, "git", "rev-parse", "--show-toplevel")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get git root: %w", err)
|
||||
return "", fmt.Errorf("not a git repository: %w", err)
|
||||
}
|
||||
return strings.TrimSpace(string(output)), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user