Skip to content

storage: filesystem/dotgit, fixing issue where absolute paths to commonDotGitFs ended up in dotGitFs#1801

Draft
Soph wants to merge 1 commit intogo-git:mainfrom
Soph:soph/fix-worktree
Draft

storage: filesystem/dotgit, fixing issue where absolute paths to commonDotGitFs ended up in dotGitFs#1801
Soph wants to merge 1 commit intogo-git:mainfrom
Soph:soph/fix-worktree

Conversation

@Soph
Copy link
Contributor

@Soph Soph commented Dec 13, 2025

When using the v6 implementation with worktree repos we got this error:

Add failed: "/tmp/gogit-worktree-test/main-repo/.git/objects/pack/tmp_obj_847737165": path outside base dir "/tmp/gogit-worktree-test/main-repo/.git/worktrees/worktree": file does not exist

The current implementation assumes path are relativ but for tmp files (in combination with worktree!?) they are absolute. So the current logic that decides which filesystem should be returned isn't working at all and always returns dotGitFs but it should return commonDotGitFs instead.

This came out of a debugging session with Claude Code first on our code base and then on go-git main branch. I reviewed the code and I'm pretty confident it's a good approach but still wanted to flag it for transparency. Especially the amount of comments is a bit on the verbose side, so happy to remove/reduce if that's too much.

Here is a script to replicate this:

open for source
package main

  import (
      "fmt"
      "os"
      "os/exec"
      "path/filepath"
      "time"

      "github.com/go-git/go-git/v6"
      "github.com/go-git/go-git/v6/plumbing/object"
  )

  func main() {
      // Create test structure
      tmpDir := "/tmp/gogit-worktree-test"
      os.RemoveAll(tmpDir)
      os.MkdirAll(tmpDir, 0755)

      mainRepoDir := filepath.Join(tmpDir, "main-repo")
      worktreeDir := filepath.Join(tmpDir, "worktree")

      // Init main repo
      exec.Command("git", "init", mainRepoDir).Run()

      // Create initial commit
      os.WriteFile(filepath.Join(mainRepoDir, "file.txt"), []byte("test"), 0644)
      exec.Command("git", "-C", mainRepoDir, "add", ".").Run()
      exec.Command("git", "-C", mainRepoDir, "commit", "-m", "initial").Run()

      // Create worktree
      exec.Command("git", "-C", mainRepoDir, "worktree", "add", worktreeDir, "-b", "test-branch").Run()

      // Change to worktree directory
      os.Chdir(worktreeDir)

      // Open with go-git v6
      repo, err := git.PlainOpenWithOptions(".", &git.PlainOpenOptions{
          EnableDotGitCommonDir: true,
      })
      if err != nil {
          fmt.Printf("Open failed: %v\n", err)
          return
      }

      wt, _ := repo.Worktree()

      // Create a new file
      os.WriteFile(filepath.Join(worktreeDir, "newfile.txt"), []byte("content"), 0644)

      // Try to add it - THIS FAILS
      _, err = wt.Add("newfile.txt")
      if err != nil {
          fmt.Printf("Add failed: %v\n", err)
          return
      }

      // Try to commit
      _, err = wt.Commit("test commit", &git.CommitOptions{
          Author: &object.Signature{Name: "Test", Email: "[email protected]", When: time.Now()},
      })
      if err != nil {
          fmt.Printf("Commit failed: %v\n", err)
          return
      }

      fmt.Println("Success!")
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants