fix: use commondir to resolve git directory in worktrees (#13045)

This PR fixes git revision detection in worktrees where the worktree's
gitdir path passes through another git repository.

The vendored `GetGitRevisionDescription.cmake` module detects worktrees
and then calls `_git_find_closest_git_dir` to find the shared git
directory by walking up the filesystem looking for a `.git` entry. This
fails when the worktree's gitdir is stored inside another git repository
(e.g. when the project is a git submodule whose objects live at
`~/.git/modules/...` and `~` is itself a git repo) — the walk finds the
wrong `.git`.

The fix reads the `commondir` file that git places in every worktree's
gitdir, which directly points to the shared git object directory. Falls
back to the old filesystem walk if `commondir` doesn't exist (shouldn't
happen with any modern git, but safe to keep).

🤖 Prepared with Claude Code

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kim Morrison 2026-04-11 16:45:02 +10:00 committed by GitHub
parent d53b46a0f3
commit 790d294e50
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -134,7 +134,16 @@ function(get_git_head_revision _refspecvar _hashvar)
#
string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir ${worktree_ref})
string(STRIP ${git_worktree_dir} git_worktree_dir)
_git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR)
# Use the commondir file to find the shared git directory, rather than
# walking up the filesystem (which can find the wrong .git if the
# worktree gitdir is inside another git repository).
if(EXISTS "${git_worktree_dir}/commondir")
file(READ "${git_worktree_dir}/commondir" commondir_ref)
string(STRIP "${commondir_ref}" commondir_ref)
get_filename_component(GIT_DIR "${git_worktree_dir}/${commondir_ref}" ABSOLUTE)
else()
_git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR)
endif()
set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD")
endif()
else()