GitPython icon indicating copy to clipboard operation
GitPython copied to clipboard

`Repo()` fails in Git Worktree when `GIT_DIR` environment variable is set

Open Leokap opened this issue 8 months ago • 2 comments

The git.Repo() constructor in GitPython fails to correctly initialize a repository when called without a path from within a Git worktree and the GIT_DIR environment variable is set to that worktree. This variable is often automatically set by Git when executing an alias to point to the current repo or worktree git_dir. While Repo(os.getcwd()) finds the worktree correctly, calling Repo() with GIT_DIR set to Repo(os.getcwd()).git_dir raises an InvalidGitRepositoryError.

Minimal Reproducing Example:

  1. Set up a main Git repository:

    mkdir main_repo
    cd main_repo
    git init
    touch initial_file.txt
    git add initial_file.txt
    git commit -m "Initial commit"
    
  2. Create a Git worktree:

    git worktree add worktree_a
    cd worktree_a
    
  3. Create a simple Python script (e.g., test_repo.py) to initialize a Repo object:

import os
from git import Repo, InvalidGitRepositoryError

print(f"Current working directory: {os.getcwd()}")
print(f"GIT_DIR environment variable: {os.getenv('GIT_DIR')}")

try:
    repo = Repo()
    print(f"Repo initialized successfully: {repo.working_dir}")
except InvalidGitRepositoryError as e:
    print(f"Error initializing Repo(): {e}")

try:
    repo_with_cwd = Repo(os.getcwd())
    print(f"Repo initialized with cwd successfully: {repo_with_cwd.working_dir}")
    print(f"Repo(os.getcwd()).git_dir: {Repo(os.getcwd()).git_dir}")
except InvalidGitRepositoryError as e:
    print(f"Error initializing Repo(os.getcwd()): {e}")
  1. Create a Git alias to run the Python script (e.g., in .git/config or using git config --local alias.test-repo '!python /path/to/test_repo.py'):

    Replace /path/to/test_repo.py with the actual path to your script.

  2. Run the Git alias from within the worktree:

    git test-repo
    

Expected Behavior:

Repo() should successfully initialize the repository, recognizing the worktree's context and linking back to the main repository's .git directory.

Observed Behavior:

Raises an InvalidGitRepositoryError when Repo() is called without a path, while Repo(os.getcwd()) succeeds. The output will also show that the GIT_DIR environment variable is set within the worktree's context.

Additional Information:

  • GitPython Version: 3.1.44
  • Python Version: 3.10.14
  • Operating System: Linux

Maybe one should also check if such happens for submodules since they also have the repo dir in a different place than the normal .git dir.

Workaround:

Explicitly passing os.getcwd() to the Repo() constructor or unsetting the GIT_DIR environment variable before calling Repo() seems to work.

Leokap avatar Apr 08 '25 14:04 Leokap

Thanks a lot!

There are probably a lot of subtleties around 'active' Git environment variables and GitPython or Git not doing the right thing.

Byron avatar Apr 08 '25 15:04 Byron