Skip to content

Commit 0993e2e

Browse files
fix(git): support git clone --bare-backed worktrees (#738)
## Summary - Detect linked worktrees whose common git directory is a bare repository. - Resolve those workspaces to the current checkout root so `roborev init` can register Middleman-style worktrees. - Keep existing behavior for normal linked worktrees and submodule worktrees. ## Validation - `go fmt ./...` - `go vet ./...` - `go test ./...` - `go test ./internal/git -run 'TestGetMainRepoRootForBareBackedWorktree|TestGetMainRepoRoot' -count=1`\n- Verified `roborev init --no-daemon` from `/Users/mariusvniekerk/.config/middleman/worktrees/github.com/kenn-io/middleman/pr-365` against an isolated patched daemon successfully registers the repo. Co-authored-by: Marius van Niekerk <mariusvniekerk@users.noreply.github.com>
1 parent 5d85920 commit 0993e2e

2 files changed

Lines changed: 31 additions & 0 deletions

File tree

internal/git/git.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,16 @@ func GetMainRepoRoot(path string) (string, error) {
609609
// This is a worktree. For regular worktrees, commonDir ends with ".git"
610610
// and the main repo is its parent. For submodule worktrees, commonDir
611611
// is inside .git/modules/ and we need to read the core.worktree config.
612+
//
613+
// Some workspace managers create linked worktrees from a bare common
614+
// repository (for example, commonDir=/path/to/repo.git). In that layout
615+
// there is no main working tree, so the current checkout root is the
616+
// stable repo-local path to register and use for config resolution.
617+
bareCmd := exec.Command("git", "config", "--file", filepath.Join(commonDir, "config"), "--bool", "core.bare")
618+
if out, err := bareCmd.Output(); err == nil && strings.TrimSpace(string(out)) == "true" {
619+
return GetRepoRoot(path)
620+
}
621+
612622
if filepath.Base(commonDir) == ".git" {
613623
// Regular worktree - parent of .git is the repo root
614624
return filepath.Dir(commonDir), nil

internal/git/git_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,27 @@ func TestIsRebaseInProgress(t *testing.T) {
461461
})
462462
}
463463

464+
func TestGetMainRepoRootForBareBackedWorktree(t *testing.T) {
465+
bareRepo := NewBareTestRepo(t)
466+
seedRepo := NewTestRepoWithCommit(t)
467+
seedRepo.Run("remote", "add", "origin", bareRepo.Dir)
468+
seedRepo.Run("push", "origin", "HEAD:main")
469+
470+
worktreeDir := t.TempDir()
471+
bareRepo.Run("worktree", "add", worktreeDir, "main")
472+
t.Cleanup(func() {
473+
cmd := exec.Command("git", "-C", bareRepo.Dir, "worktree", "remove", worktreeDir)
474+
_ = cmd.Run()
475+
})
476+
477+
got, err := GetMainRepoRoot(worktreeDir)
478+
require.NoError(t, err)
479+
480+
want, err := GetRepoRoot(worktreeDir)
481+
require.NoError(t, err)
482+
assert.Equal(t, want, got)
483+
}
484+
464485
func TestGetCommitInfo(t *testing.T) {
465486
t.Run("commit with subject only", func(t *testing.T) {
466487
repo := NewTestRepoWithAuthor(t, "Test Author")

0 commit comments

Comments
 (0)