Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion git/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -1595,7 +1595,7 @@ def _call_process(
turns into::
git rev-list --max-count=10 --header=master
git rev-list --max-count=10 --header master
:return:
Same as :meth:`execute`. If no args are given, used :meth:`execute`'s
Expand Down
3 changes: 2 additions & 1 deletion git/repo/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,8 @@ def __init__(
sm_gitpath = find_worktree_git_dir(dotgit)

if sm_gitpath is not None:
git_dir = expand_path(sm_gitpath, expand_vars)
# 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)
Comment on lines +298 to +299
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?

self._working_tree_dir = curpath
break

Expand Down
22 changes: 19 additions & 3 deletions test/test_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
from git.repo.fun import touch
from git.util import bin_to_hex, cwd, cygpath, join_path_native, rmfile, rmtree

from test.lib import TestBase, fixture, with_rw_directory, with_rw_repo, PathLikeMock
from test.lib import TestBase, fixture, with_rw_directory, with_rw_repo, PathLikeMock, skipIf


def iter_flatten(lol):
Expand Down Expand Up @@ -1094,7 +1094,7 @@ def test_is_valid_object(self):
self.assertFalse(repo.is_valid_object(tag_sha, "commit"))

@with_rw_directory
def test_git_work_tree_dotgit(self, rw_dir):
def test_git_work_tree_dotgit(self, rw_dir, use_relative_paths=False):
"""Check that we find .git as a worktree file and find the worktree
based on it."""
git = Git(rw_dir)
Expand All @@ -1106,7 +1106,11 @@ def test_git_work_tree_dotgit(self, rw_dir):
worktree_path = join_path_native(rw_dir, "worktree_repo")
if Git.is_cygwin():
worktree_path = cygpath(worktree_path)
rw_master.git.worktree("add", worktree_path, branch.name)
wt_add_kwargs = {"insert_kwargs_after": "add"}
# relative worktree paths introduced in git 2.48.0
if use_relative_paths and git.version_info[:3] >= (2, 48, 0):
wt_add_kwargs["relative_paths"] = True
rw_master.git.worktree("add", worktree_path, branch.name, **wt_add_kwargs)

# This ensures that we can read the repo's gitdir correctly.
repo = Repo(worktree_path)
Expand All @@ -1124,6 +1128,18 @@ def test_git_work_tree_dotgit(self, rw_dir):

self.assertIsInstance(repo.heads["aaaaaaaa"], Head)

@skipIf(
Git().version_info[:3] < (2, 48, 0),
reason="relative worktree feature unsupported (needs git 2.48.0 or later)",
)
Comment on lines +1131 to +1134
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.

def test_git_work_tree_dotgit_relative(self):
"""Check that we find .git as a worktree file containing a relative path
and find the worktree based on it."""

# this class inherits from TestCase so we can't use pytest.mark.parametrize on
# test_git_work_tree_dotgit; delegate instead
self.test_git_work_tree_dotgit(use_relative_paths=True)

@with_rw_directory
def test_git_work_tree_env(self, rw_dir):
"""Check that we yield to GIT_WORK_TREE."""
Expand Down
Loading