Skip to content

Commit 964d73a

Browse files
committed
Handle git worktrees without relying on --show-superproject-working-tree
Dan James's changes in 8584858 made git-pre-commit-format work with worktrees, but only if using a recent enough git which has --show-superproject-working-tree. Unfortunately, git 2.7.4 doesn't have it and is quite widespread (due to being in Ubuntu 16.04). This is based on an initial patch by Charles Baylis (who also helped with understanding why his original patch was failing some tests).
1 parent 24eed49 commit 964d73a

File tree

1 file changed

+20
-24
lines changed

1 file changed

+20
-24
lines changed

git-pre-commit-format

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -82,39 +82,35 @@ declare git_test_dir=.
8282
declare top_dir
8383

8484
while true; do
85-
top_dir=$(cd "$git_test_dir" && git rev-parse --show-toplevel) || \
85+
top_dir=$(git -C "$git_test_dir" rev-parse --show-toplevel) || \
8686
error_exit "You need to be in the git repository to run this script."
8787

88+
# Try to handle git worktree.
89+
# The best way to deal both with git submodules and worktrees would be to
90+
# use --show-superproject-working-tree, but it's not supported in git 2.7.4
91+
# which is shipped in Ubuntu 16.04.
92+
declare git_common_dir
93+
if git_common_dir=$(git -C "$git_test_dir" rev-parse --git-common-dir 2>/dev/null); then
94+
# The common dir could be relative, so we make it absolute.
95+
git_common_dir=$(cd "$git_test_dir" && realpath "$git_common_dir")
96+
declare maybe_top_dir
97+
maybe_top_dir=$(realpath "$git_common_dir/..")
98+
if [ -e "$maybe_top_dir/.git" ]; then
99+
# We are not in a submodules, otherwise common dir would have been
100+
# something like PROJ/.git/modules/SUBMODULE and there would not be
101+
# a .git directory in PROJ/.git/modules/.
102+
top_dir="$maybe_top_dir"
103+
fi
104+
fi
105+
88106
[ -e "$top_dir/.git" ] || \
89107
error_exit "No .git directory in $top_dir."
90108

91109
if [ -d "$top_dir/.git" ]; then
92110
# We are done! top_dir is the root git directory.
93111
break
94112
elif [ -f "$top_dir/.git" ]; then
95-
# We are in a submodule or git work-tree if .git is a file!
96-
if [ -z "$(cd "$git_test_dir" && git rev-parse --show-superproject-working-tree)" ]; then
97-
# The --show-superproject-working-tree option is available and we
98-
# are in a work tree.
99-
gitdir=$(<"$top_dir/.git")
100-
gitdir=${gitdir#gitdir: }
101-
topdir_basename=${gitdir##*/}
102-
git_test_dir=${gitdir%/worktrees/$topdir_basename}
103-
break
104-
fi
105-
# If show-superproject-working-tree returns non-empty string, either:
106-
#
107-
# 1) --show-superproject-working-tree is not defined for this version of git
108-
#
109-
# 2) --show-superproject-working-tree is defined and we are in a submodule
110-
#
111-
# In the first case we will assume it is not a work tree because people
112-
# using that advanced technology will be using a recent version of git.
113-
#
114-
# In second case, we could use the value returned by
115-
# --show-superproject-working-tree directly but we do not here because
116-
# that would require extra work.
117-
#
113+
# We are in a submodule.
118114
git_test_dir="$git_test_dir/.."
119115
fi
120116
done

0 commit comments

Comments
 (0)