Thread (4 messages) flat view 4 messages, 1 author, 3h ago
DORMANTno replies

[RFC PATCH 3/3] setup: communicate why a directory is not a valid git directory

From: Kaartic Sivaraam <hidden>
Date: 2026-09-24 12:05:20
Subsystem: the rest · Maintainer: Linus Torvalds

At the moment, there are a few scenarios in which the error message
surrounding an invalid Git repository is a bit blunt:

  $ GIT_OBJECT_DIRECTORY=/does/not/exist git --git-dir repo.git rev-parse --is-bare-repository
  fatal: not a git repository: 'repo.git'

In this case, even though repo.git is a valid Git repository,
we get an output saying it is not since the GIT_OBJECT_DIRECTORY
does not point to a valid object directory. At the moment, the
user is on their own in figuring this out.

Instead, make it more easy for users to figure such issues
particularly in cases where they have explicitly specified
a Git directory. This intends to improve the error reporting UX
by clarifying why the specified repository is not considered valid.

We achieve this by means of using the new helper
is_git_directory_verbose() that has been introduced. With the
same, we get a more helpful error message as follows:

  $ GIT_OBJECT_DIRECTORY=/does/not/exist git --git-dir repo.git rev-parse --is-bare-repository
  fatal: not a git repository: 'repo.git'
  reason: cannot access object directory '/does/not/exist' set via $GIT_OBJECT_DIRECTORY

Signed-off-by: Kaartic Sivaraam <redacted>
---
 setup.c                       | 13 +++++++++++--
 t/t0009-git-dir-validation.sh | 10 ++++++----
 2 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/setup.c b/setup.c
index b3b53a1cfc..3e99141474 100644
--- a/setup.c
+++ b/setup.c
@@ -1225,6 +1225,7 @@ static void repo_discover_explicit_gitdir(struct repo_discovery *discovery,
 					  int *nongit_ok)
 {
 	const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
+	struct strbuf invalid_gitdir_reason = STRBUF_INIT;
 	char *gitfile;
 	int offset;
 
@@ -1237,12 +1238,19 @@ static void repo_discover_explicit_gitdir(struct repo_discovery *discovery,
 		gitdirenv = gitfile;
 	}
 
-	if (!is_git_directory(gitdirenv)) {
+	if (!is_git_directory_verbose(gitdirenv, &invalid_gitdir_reason)) {
+		struct strbuf die_msg = STRBUF_INIT;
 		if (nongit_ok) {
 			*nongit_ok = 1;
 			goto out;
 		}
-		die(_("not a git repository: '%s'"), gitdirenv);
+
+		strbuf_addf(&die_msg, _("not a git repository: '%s'"), gitdirenv);
+		strbuf_addch(&die_msg, '\n');
+		strbuf_addf(&die_msg, _("reason: %s"), invalid_gitdir_reason.buf);
+		die("%s", die_msg.buf);
+
+		strbuf_release(&die_msg);
 	}
 
 	if (read_and_verify_repository_format(&discovery->format, gitdirenv, nongit_ok))
@@ -1304,6 +1312,7 @@ static void repo_discover_explicit_gitdir(struct repo_discovery *discovery,
 	repo_discovery_set_gitdir(discovery, gitdirenv, 0);
 
 out:
+	strbuf_release(&invalid_gitdir_reason);
 	free(gitfile);
 }
 
diff --git a/t/t0009-git-dir-validation.sh b/t/t0009-git-dir-validation.sh
index 244dc07c0e..411aac1d9e 100755
--- a/t/t0009-git-dir-validation.sh
+++ b/t/t0009-git-dir-validation.sh
@@ -79,7 +79,8 @@ test_expect_success 'setup: custom git directory with missing HEAD is rejected'
 	mkdir -p parent/empty-dir &&
 	(
 		test_must_fail git --git-dir parent/empty-dir rev-parse --is-bare-repository 2>stderr &&
-		test_grep "not a git repository" stderr
+		test_grep "not a git repository" stderr &&
+		test_grep "reason: could not stat HEAD at" stderr
 	)
 '
 
@@ -93,7 +94,8 @@ test_expect_success 'setup: custom git directory with HEAD as a symlink outside
 		rm real-repo/HEAD &&
 		ln -s ../garbage real-repo/HEAD &&
 		test_must_fail git --git-dir real-repo rev-parse --is-bare-repository 2>stderr &&
-		test_grep "not a git repository" stderr
+		test_grep "not a git repository" stderr &&
+		test_grep "reason: HEAD is a symlink .* but target lives outside refs" stderr
 	)
 '
 
@@ -105,9 +107,9 @@ test_expect_success 'setup: custom git directory with invalid GIT_OBJECT_DIRECTO
 		git init --bare real-repo &&
 		test_must_fail env GIT_OBJECT_DIRECTORY="$(pwd)/does-not-exist" \
 			git --git-dir real-repo rev-parse --is-bare-repository 2>stderr &&
-		test_grep "not a git repository" stderr
+		test_grep "not a git repository" stderr &&
+		test_grep "reason: cannot access object directory .* set via \$GIT_OBJECT_DIRECTORY"   stderr
 	)
 '
 
-
 test_done
-- 
2.56.0.rc1.12.g2c9c8d64bb
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help