Skip to content

Support relative worktree paths (git 2.48+ worktree.useRelativePaths)#2151

Draft
elovelan wants to merge 2 commits into
gitpython-developers:mainfrom
elovelan:relative_worktree_support
Draft

Support relative worktree paths (git 2.48+ worktree.useRelativePaths)#2151
elovelan wants to merge 2 commits into
gitpython-developers:mainfrom
elovelan:relative_worktree_support

Conversation

@elovelan
Copy link
Copy Markdown

@elovelan elovelan commented May 12, 2026

Summary

Git 2.48 introduced the worktree.useRelativePaths config option. When enabled, git worktree add writes a relative gitdir: into the worktree's .git file — relative to the directory containing that .git file.

GitPython's Repo.__init__ previously passed the value of that gitdir: line straight through expand_path, which calls os.path.abspath against the process's current working directory rather than against the worktree. Using the library when the cwd was not the worktree root therefore failed.

This change resolves the relative gitdir against curpath (the directory containing the .git file) before expanding. Absolute paths — i.e. the pre-2.48 default — are unaffected, because os.path.join ignores its first argument when the second is absolute.

This change also includes a minor doc fix that I came across when trying to better understand how git is called.

Test plan

  • New test TestRepo.test_git_work_tree_dotgit_relative, which delegates to test_git_work_tree_dotgit but runs git worktree add --relative-paths. I verified that the test failed before implementation and now passes.
  • Existing test_git_work_tree_dotgit still passes, confirming absolute-path worktrees are unaffected.

AI disclosure

Per CONTRIBUTING.md: this PR description and the commit message were drafted by Claude Code on behalf of @elovelan; though the final versions were manually reworded for clarity. All code was written without AI (didn't start that way but I didn't like its test implementation, and the actual implementation was trivial).

elovelan added 2 commits May 12, 2026 16:08
Git 2.48 introduced the `worktree.useRelativePaths` config option,
which causes `git worktree add` to write a relative `gitdir` into the
worktree's `.git` file.

Resolve the relative `gitdir` against the worktree directory before
before expanding it. Absolute paths are unaffected because
`os.path.join` ignores the prefix when joined with an absolute path.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates GitPython’s worktree discovery to correctly resolve relative gitdir: paths written into worktree .git files when Git 2.48+ is configured with worktree.useRelativePaths.

Changes:

  • Resolve worktree .git file gitdir: entries relative to the directory containing the .git file before expanding/normalizing.
  • Add a new test that exercises git worktree add --relative-paths on Git 2.48+.
  • Fix a command-construction example in Git._call_process docstring.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
git/repo/base.py Resolves worktree gitdir: paths relative to the worktree directory to support Git 2.48+ relative paths.
test/test_repo.py Adds coverage for relative worktree gitdir: behavior via git worktree add --relative-paths.
git/cmd.py Corrects a docstring example of how kwargs map to CLI flags.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread git/repo/base.py
Comment on lines +298 to +299
# worktrees can use relative paths as of Git 2.48, so we join to curpath
git_dir = expand_path(osp.join(curpath, sm_gitpath), expand_vars)
Copy link
Copy Markdown
Author

@elovelan elovelan May 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fix won't work because it's doing the same thing as the original code (because expand_path calls osp.abspath). To do this properly, I'd have to create a copy of expand_path that doesn't call osp.abspath, or add a flag to the existing function.

@Byron, I was double checking how Git handles this and it turns out it doesn't do ~ and env var expansion, it only does the equivalent of osp.normpath via strbuf_realpath. I'm wondering if GitPython should match, which means my existing code will work by replacing the call to expand_path with osp.normpath. Or should I do what I mentioned above and use expand_path (without its call to osp.abspath) just in case Git decides to support expansions of the gitdir in the future?

Comment thread test/test_repo.py
Comment on lines +1131 to +1134
@skipIf(
Git().version_info[:3] < (2, 48, 0),
reason="relative worktree feature unsupported (needs git 2.48.0 or later)",
)
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a good suggestion. It's also done at test_index_mutation so I'll open a separate PR to fix that as well.

Copy link
Copy Markdown
Member

@Byron Byron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot, looks good to me!
Could you take a look at the co-pilot suggestions though?
Once resolved, this PR can be merged.

@Byron Byron marked this pull request as draft May 12, 2026 22:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants