* [GSoC Patch 1/7] repo: add path.toplevel with absolute and relative suffix formatting
2026-07-16 1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
@ 2026-07-16 1:21 ` K Jayatheerth
2026-07-16 1:21 ` [GSoC Patch 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes K Jayatheerth
` (6 subsequent siblings)
7 siblings, 0 replies; 21+ messages in thread
From: K Jayatheerth @ 2026-07-16 1:21 UTC (permalink / raw)
To: git; +Cc: jltobler, lucasseikioshiro, K Jayatheerth
Scripts frequently need to find the root directory of a repository's
working tree. Currently, this requires using `git rev-parse --show-toplevel`
or inferring it from other path components.
Introduce `path.toplevel.absolute` and `path.toplevel.relative` keys
to `git repo info`. This allows scripts to retrieve the top-level
working tree path in a predictable, strictly formatted manner without
relying on `rev-parse`.
If requested in a bare repository where no working tree exists, the
command returns an empty string.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Documentation/git-repo.adoc | 10 ++++++++++
builtin/repo.c | 28 ++++++++++++++++++++++++++++
t/t1900-repo-info.sh | 30 ++++++++++++++++++++++++++++++
3 files changed, 68 insertions(+)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index ed7d80c690..e34abe5fea 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,16 @@ values that they return:
`path.gitdir.relative`::
The path to the Git repository directory relative to the current working directory.
+`path.toplevel.absolute`::
+ The canonical absolute path to the top-level directory of the
+ repository's working tree. Outputs an empty string if the repository
+ is bare.
+
+`path.toplevel.relative`::
+ The path to the top-level directory of the repository's working
+ tree relative to the current working directory. Outputs an empty
+ string if the repository is bare.
+
`references.format`::
The reference storage format. The valid values are:
+
diff --git a/builtin/repo.c b/builtin/repo.c
index 042d6de558..194757eb18 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -121,6 +121,32 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
return 0;
}
+static int get_path_toplevel_absolute(struct repository *repo, struct strbuf *buf)
+{
+ const char *work_tree = repo_get_work_tree(repo);
+
+ if (!work_tree) {
+ strbuf_addstr(buf, "");
+ return 0;
+ }
+
+ format_path(buf, work_tree, startup_info->prefix, PATH_FORMAT_CANONICAL);
+ return 0;
+}
+
+static int get_path_toplevel_relative(struct repository *repo, struct strbuf *buf)
+{
+ const char *work_tree = repo_get_work_tree(repo);
+
+ if (!work_tree) {
+ strbuf_addstr(buf, "");
+ return 0;
+ }
+
+ format_path(buf, work_tree, startup_info->prefix, PATH_FORMAT_RELATIVE);
+ return 0;
+}
+
static int get_references_format(struct repository *repo, struct strbuf *buf)
{
strbuf_addstr(buf,
@@ -137,6 +163,8 @@ static const struct repo_info_field repo_info_field[] = {
{ "path.commondir.relative", get_path_commondir_relative },
{ "path.gitdir.absolute", get_path_gitdir_absolute },
{ "path.gitdir.relative", get_path_gitdir_relative },
+ { "path.toplevel.absolute", get_path_toplevel_absolute },
+ { "path.toplevel.relative", get_path_toplevel_relative },
{ "references.format", get_references_format },
};
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index ae8c22c817..fbb9063ee5 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,4 +213,34 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
'.git' \
'GIT_DIR="../.git" && export GIT_DIR'
+test_expect_success 'path.toplevel absolute and relative' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ mkdir -p repo/sub &&
+ cd repo/sub &&
+
+ ROOT="$(test-tool path-utils real_path ..)" &&
+
+ echo "path.toplevel.absolute=$ROOT" >expect.abs &&
+ git repo info path.toplevel.absolute >actual.abs &&
+ test_cmp expect.abs actual.abs &&
+
+ echo "path.toplevel.relative=../" >expect.rel &&
+ git repo info path.toplevel.relative >actual.rel &&
+ test_cmp expect.rel actual.rel
+ )
+'
+
+test_expect_success 'path.toplevel returns empty in a bare repository' '
+ test_when_finished "rm -rf bare.git" &&
+ git init --bare bare.git &&
+ (
+ cd bare.git &&
+ echo "path.toplevel.absolute=" >expect &&
+ git repo info path.toplevel.absolute >actual &&
+ test_cmp expect actual
+ )
+'
+
test_done
--
2.55.GIT
^ permalink raw reply related [flat|nested] 21+ messages in thread* [GSoC Patch 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes
2026-07-16 1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
2026-07-16 1:21 ` [GSoC Patch 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
@ 2026-07-16 1:21 ` K Jayatheerth
2026-07-16 1:21 ` [GSoC Patch 3/7] repo: add path.objects with absolute and relative suffix formatting K Jayatheerth
` (5 subsequent siblings)
7 siblings, 0 replies; 21+ messages in thread
From: K Jayatheerth @ 2026-07-16 1:21 UTC (permalink / raw)
To: git; +Cc: jltobler, lucasseikioshiro, K Jayatheerth
Scripts working in multi-repository setups often need to identify the
top-level working tree of a superproject from within a submodule.
Currently, this is only exposed via `git rev-parse
--show-superproject-working-tree`.
Introduce `path.superproject-working-tree.absolute` and
`path.superproject-working-tree.relative` keys to `git repo info`.
This exposes the core submodule context via a scriptable config-like key
using standard format rules.
If requested when not inside a submodule, the command returns an empty
string.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Documentation/git-repo.adoc | 10 ++++++++++
builtin/repo.c | 33 +++++++++++++++++++++++++++++++++
t/t1900-repo-info.sh | 34 ++++++++++++++++++++++++++++++++++
3 files changed, 77 insertions(+)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index e34abe5fea..03aa57942f 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,16 @@ values that they return:
`path.gitdir.relative`::
The path to the Git repository directory relative to the current working directory.
+`path.superproject-working-tree.absolute`::
+ The canonical absolute path to the working tree root of the superproject
+ if the current repository is an initialized submodule. Outputs an empty
+ string if not in a submodule.
+
+`path.superproject-working-tree.relative`::
+ The path to the working tree root of the superproject relative to the
+ current working directory if the current repository is an initialized
+ submodule. Outputs an empty string if not in a submodule.
+
`path.toplevel.absolute`::
The canonical absolute path to the top-level directory of the
repository's working tree. Outputs an empty string if the repository
diff --git a/builtin/repo.c b/builtin/repo.c
index 194757eb18..82359473e9 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -18,6 +18,7 @@
#include "strbuf.h"
#include "string-list.h"
#include "shallow.h"
+#include "submodule.h"
#include "tree.h"
#include "tree-walk.h"
#include "utf8.h"
@@ -121,6 +122,36 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
return 0;
}
+static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
+{
+ struct strbuf superproject = STRBUF_INIT;
+
+ if (!get_superproject_working_tree(&superproject)) {
+ strbuf_release(&superproject);
+ strbuf_addstr(buf, "");
+ return 0;
+ }
+
+ format_path(buf, superproject.buf, startup_info->prefix, PATH_FORMAT_CANONICAL);
+ strbuf_release(&superproject);
+ return 0;
+}
+
+static int get_path_superproject_relative(struct repository *repo UNUSED, struct strbuf *buf)
+{
+ struct strbuf superproject = STRBUF_INIT;
+
+ if (!get_superproject_working_tree(&superproject)) {
+ strbuf_release(&superproject);
+ strbuf_addstr(buf, "");
+ return 0;
+ }
+
+ format_path(buf, superproject.buf, startup_info->prefix, PATH_FORMAT_RELATIVE);
+ strbuf_release(&superproject);
+ return 0;
+}
+
static int get_path_toplevel_absolute(struct repository *repo, struct strbuf *buf)
{
const char *work_tree = repo_get_work_tree(repo);
@@ -163,6 +194,8 @@ static const struct repo_info_field repo_info_field[] = {
{ "path.commondir.relative", get_path_commondir_relative },
{ "path.gitdir.absolute", get_path_gitdir_absolute },
{ "path.gitdir.relative", get_path_gitdir_relative },
+ { "path.superproject-working-tree.absolute", get_path_superproject_absolute },
+ { "path.superproject-working-tree.relative", get_path_superproject_relative },
{ "path.toplevel.absolute", get_path_toplevel_absolute },
{ "path.toplevel.relative", get_path_toplevel_relative },
{ "references.format", get_references_format },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index fbb9063ee5..220b3d4d3d 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,40 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
'.git' \
'GIT_DIR="../.git" && export GIT_DIR'
+test_expect_success 'path.superproject-working-tree absolute and relative' '
+ test_when_finished "rm -rf sub super" &&
+ git init sub &&
+ test_commit -C sub initial &&
+ git init super &&
+ (
+ cd super &&
+ git -c protocol.file.allow=always submodule add "../sub" sub &&
+ git commit -m "add submodule" &&
+
+ cd sub &&
+ ROOT="$(test-tool path-utils real_path ..)" &&
+
+ echo "path.superproject-working-tree.absolute=$ROOT" >expect.abs &&
+ git repo info path.superproject-working-tree.absolute >actual.abs &&
+ test_cmp expect.abs actual.abs &&
+
+ echo "path.superproject-working-tree.relative=../" >expect.rel &&
+ git repo info path.superproject-working-tree.relative >actual.rel &&
+ test_cmp expect.rel actual.rel
+ )
+'
+
+test_expect_success 'path.superproject-working-tree returns empty when not in a submodule' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ echo "path.superproject-working-tree.absolute=" >expect &&
+ git repo info path.superproject-working-tree.absolute >actual &&
+ test_cmp expect actual
+ )
+'
+
test_expect_success 'path.toplevel absolute and relative' '
test_when_finished "rm -rf repo" &&
git init repo &&
--
2.55.GIT
^ permalink raw reply related [flat|nested] 21+ messages in thread* [GSoC Patch 3/7] repo: add path.objects with absolute and relative suffix formatting
2026-07-16 1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
2026-07-16 1:21 ` [GSoC Patch 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
2026-07-16 1:21 ` [GSoC Patch 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes K Jayatheerth
@ 2026-07-16 1:21 ` K Jayatheerth
2026-07-16 1:21 ` [GSoC Patch 4/7] repo: add path.hooks " K Jayatheerth
` (4 subsequent siblings)
7 siblings, 0 replies; 21+ messages in thread
From: K Jayatheerth @ 2026-07-16 1:21 UTC (permalink / raw)
To: git; +Cc: jltobler, lucasseikioshiro, K Jayatheerth
Tools and deployment hooks frequently query the location of the object
database directory. Currently, this relies on legacy parsing methods or
manually inspecting `git rev-parse --git-path objects`.
Introduce `path.objects.absolute` and `path.objects.relative` keys to
`git repo info`. This allows tools to discover the object database
location safely while natively adhering to active `GIT_OBJECT_DIRECTORY`
environment variable overrides.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Documentation/git-repo.adoc | 9 +++++++++
builtin/repo.c | 24 ++++++++++++++++++++++++
t/t1900-repo-info.sh | 7 +++++++
3 files changed, 40 insertions(+)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 03aa57942f..8429a44b43 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,15 @@ values that they return:
`path.gitdir.relative`::
The path to the Git repository directory relative to the current working directory.
+`path.objects.absolute`::
+ The canonical absolute path to the repository's object database directory.
+ Respects the `GIT_OBJECT_DIRECTORY` environment override.
+
+`path.objects.relative`::
+ The path to the repository's object database directory relative to the
+ current working directory. Respects the `GIT_OBJECT_DIRECTORY`
+ environment override.
+
`path.superproject-working-tree.absolute`::
The canonical absolute path to the working tree root of the superproject
if the current repository is an initialized submodule. Outputs an empty
diff --git a/builtin/repo.c b/builtin/repo.c
index 82359473e9..d6bdd5bcfa 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,28 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
return 0;
}
+static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
+{
+ const char *obj_dir = repo_get_object_directory(repo);
+
+ if (!obj_dir)
+ return error(_("unable to get object directory"));
+
+ format_path(buf, obj_dir, startup_info->prefix, PATH_FORMAT_CANONICAL);
+ return 0;
+}
+
+static int get_path_objects_relative(struct repository *repo, struct strbuf *buf)
+{
+ const char *obj_dir = repo_get_object_directory(repo);
+
+ if (!obj_dir)
+ return error(_("unable to get object directory"));
+
+ format_path(buf, obj_dir, startup_info->prefix, PATH_FORMAT_RELATIVE);
+ return 0;
+}
+
static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
{
struct strbuf superproject = STRBUF_INIT;
@@ -194,6 +216,8 @@ static const struct repo_info_field repo_info_field[] = {
{ "path.commondir.relative", get_path_commondir_relative },
{ "path.gitdir.absolute", get_path_gitdir_absolute },
{ "path.gitdir.relative", get_path_gitdir_relative },
+ { "path.objects.absolute", get_path_objects_absolute },
+ { "path.objects.relative", get_path_objects_relative },
{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
{ "path.superproject-working-tree.relative", get_path_superproject_relative },
{ "path.toplevel.absolute", get_path_toplevel_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 220b3d4d3d..260f4fde43 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,13 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
'.git' \
'GIT_DIR="../.git" && export GIT_DIR'
+test_repo_info_path 'objects standard' 'objects' '.git/objects'
+
+test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
+ 'custom-objects' \
+ 'GIT_OBJECT_DIRECTORY="$ROOT/custom-objects" && export GIT_OBJECT_DIRECTORY &&
+ mkdir -p "$ROOT/custom-objects"'
+
test_expect_success 'path.superproject-working-tree absolute and relative' '
test_when_finished "rm -rf sub super" &&
git init sub &&
--
2.55.GIT
^ permalink raw reply related [flat|nested] 21+ messages in thread* [GSoC Patch 4/7] repo: add path.hooks with absolute and relative suffix formatting
2026-07-16 1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
` (2 preceding siblings ...)
2026-07-16 1:21 ` [GSoC Patch 3/7] repo: add path.objects with absolute and relative suffix formatting K Jayatheerth
@ 2026-07-16 1:21 ` K Jayatheerth
2026-07-16 1:21 ` [GSoC Patch 5/7] repo: add path.index " K Jayatheerth
` (3 subsequent siblings)
7 siblings, 0 replies; 21+ messages in thread
From: K Jayatheerth @ 2026-07-16 1:21 UTC (permalink / raw)
To: git; +Cc: jltobler, lucasseikioshiro, K Jayatheerth
External tool integrations and validation systems need a stable way to
identify where the repository hooks are stored. Currently, this involves
relying on `git rev-parse --git-path hooks` or querying `core.hooksPath`
manually.
Introduce `path.hooks.absolute` and `path.hooks.relative` keys to
`git repo info`. This allows tools to discover the active hooks location
natively, ensuring proper resolution regardless of whether Git is using
the standard `.git/hooks` structure or a custom `core.hooksPath` setup.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Documentation/git-repo.adoc | 8 ++++++++
builtin/repo.c | 22 ++++++++++++++++++++++
t/t1900-repo-info.sh | 6 ++++++
3 files changed, 36 insertions(+)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 8429a44b43..7bc1c51310 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,14 @@ values that they return:
`path.gitdir.relative`::
The path to the Git repository directory relative to the current working directory.
+`path.hooks.absolute`::
+ The canonical absolute path to the repository's hooks directory.
+ Respects `core.hooksPath` configuration adjustments.
+
+`path.hooks.relative`::
+ The path to the repository's hooks directory relative to the current
+ working directory. Respects `core.hooksPath` configuration adjustments.
+
`path.objects.absolute`::
The canonical absolute path to the repository's object database directory.
Respects the `GIT_OBJECT_DIRECTORY` environment override.
diff --git a/builtin/repo.c b/builtin/repo.c
index d6bdd5bcfa..c921de222d 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,26 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
return 0;
}
+static int get_path_hooks_absolute(struct repository *repo, struct strbuf *buf)
+{
+ struct strbuf hooks_path = STRBUF_INIT;
+
+ repo_git_path_replace(repo, &hooks_path, "hooks");
+ format_path(buf, hooks_path.buf, startup_info->prefix, PATH_FORMAT_CANONICAL);
+ strbuf_release(&hooks_path);
+ return 0;
+}
+
+static int get_path_hooks_relative(struct repository *repo, struct strbuf *buf)
+{
+ struct strbuf hooks_path = STRBUF_INIT;
+
+ repo_git_path_replace(repo, &hooks_path, "hooks");
+ format_path(buf, hooks_path.buf, startup_info->prefix, PATH_FORMAT_RELATIVE);
+ strbuf_release(&hooks_path);
+ return 0;
+}
+
static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
{
const char *obj_dir = repo_get_object_directory(repo);
@@ -216,6 +236,8 @@ static const struct repo_info_field repo_info_field[] = {
{ "path.commondir.relative", get_path_commondir_relative },
{ "path.gitdir.absolute", get_path_gitdir_absolute },
{ "path.gitdir.relative", get_path_gitdir_relative },
+ { "path.hooks.absolute", get_path_hooks_absolute },
+ { "path.hooks.relative", get_path_hooks_relative },
{ "path.objects.absolute", get_path_objects_absolute },
{ "path.objects.relative", get_path_objects_relative },
{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 260f4fde43..cd3f856d04 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,12 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
'.git' \
'GIT_DIR="../.git" && export GIT_DIR'
+test_repo_info_path 'hooks standard fallback' 'hooks' '.git/hooks'
+
+test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
+ 'custom-hooks' \
+ 'git config core.hooksPath "$ROOT/custom-hooks" && mkdir -p "$ROOT/custom-hooks"'
+
test_repo_info_path 'objects standard' 'objects' '.git/objects'
test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
--
2.55.GIT
^ permalink raw reply related [flat|nested] 21+ messages in thread* [GSoC Patch 5/7] repo: add path.index with absolute and relative suffix formatting
2026-07-16 1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
` (3 preceding siblings ...)
2026-07-16 1:21 ` [GSoC Patch 4/7] repo: add path.hooks " K Jayatheerth
@ 2026-07-16 1:21 ` K Jayatheerth
2026-07-16 1:21 ` [GSoC Patch 6/7] repo: add path.grafts " K Jayatheerth
` (2 subsequent siblings)
7 siblings, 0 replies; 21+ messages in thread
From: K Jayatheerth @ 2026-07-16 1:21 UTC (permalink / raw)
To: git; +Cc: jltobler, lucasseikioshiro, K Jayatheerth
External script workflows and formatting layers require straightforward
access to the location of the index staging file. Currently, tracking
this necessitates a legacy call to `git rev-parse --git-path index` or
`--show-toplevel` logic abstractions.
Introduce `path.index.absolute` and `path.index.relative` keys to
`git repo info`. This allows tooling utilities to discover the active
index context cleanly while scaling transparently with localized
`GIT_INDEX_FILE` environment overrides.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Documentation/git-repo.adoc | 8 ++++++++
builtin/repo.c | 24 ++++++++++++++++++++++++
t/t1900-repo-info.sh | 6 ++++++
3 files changed, 38 insertions(+)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 7bc1c51310..3a837c573e 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -127,6 +127,14 @@ values that they return:
The path to the repository's hooks directory relative to the current
working directory. Respects `core.hooksPath` configuration adjustments.
+`path.index.absolute`::
+ The canonical absolute path to the repository's current index file.
+ Respects the `GIT_INDEX_FILE` environment override.
+
+`path.index.relative`::
+ The path to the repository's current index file relative to the current
+ working directory. Respects the `GIT_INDEX_FILE` environment override.
+
`path.objects.absolute`::
The canonical absolute path to the repository's object database directory.
Respects the `GIT_OBJECT_DIRECTORY` environment override.
diff --git a/builtin/repo.c b/builtin/repo.c
index c921de222d..66bf4c67cc 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -142,6 +142,28 @@ static int get_path_hooks_relative(struct repository *repo, struct strbuf *buf)
return 0;
}
+static int get_path_index_absolute(struct repository *repo, struct strbuf *buf)
+{
+ const char *index_file = repo_get_index_file(repo);
+
+ if (!index_file)
+ return error(_("unable to get index file"));
+
+ format_path(buf, index_file, startup_info->prefix, PATH_FORMAT_CANONICAL);
+ return 0;
+}
+
+static int get_path_index_relative(struct repository *repo, struct strbuf *buf)
+{
+ const char *index_file = repo_get_index_file(repo);
+
+ if (!index_file)
+ return error(_("unable to get index file"));
+
+ format_path(buf, index_file, startup_info->prefix, PATH_FORMAT_RELATIVE);
+ return 0;
+}
+
static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
{
const char *obj_dir = repo_get_object_directory(repo);
@@ -238,6 +260,8 @@ static const struct repo_info_field repo_info_field[] = {
{ "path.gitdir.relative", get_path_gitdir_relative },
{ "path.hooks.absolute", get_path_hooks_absolute },
{ "path.hooks.relative", get_path_hooks_relative },
+ { "path.index.absolute", get_path_index_absolute },
+ { "path.index.relative", get_path_index_relative },
{ "path.objects.absolute", get_path_objects_absolute },
{ "path.objects.relative", get_path_objects_relative },
{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index cd3f856d04..04e6b8553c 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -219,6 +219,12 @@ test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
'custom-hooks' \
'git config core.hooksPath "$ROOT/custom-hooks" && mkdir -p "$ROOT/custom-hooks"'
+test_repo_info_path 'index standard' 'index' '.git/index'
+
+test_repo_info_path 'index with GIT_INDEX_FILE override' 'index' \
+ 'custom-index-file' \
+ 'GIT_INDEX_FILE="$ROOT/custom-index-file" && export GIT_INDEX_FILE'
+
test_repo_info_path 'objects standard' 'objects' '.git/objects'
test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
--
2.55.GIT
^ permalink raw reply related [flat|nested] 21+ messages in thread* [GSoC Patch 6/7] repo: add path.grafts with absolute and relative suffix formatting
2026-07-16 1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
` (4 preceding siblings ...)
2026-07-16 1:21 ` [GSoC Patch 5/7] repo: add path.index " K Jayatheerth
@ 2026-07-16 1:21 ` K Jayatheerth
2026-07-16 1:21 ` [GSoC Patch 7/7] repo: add path.git-prefix path key validation K Jayatheerth
2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
7 siblings, 0 replies; 21+ messages in thread
From: K Jayatheerth @ 2026-07-16 1:21 UTC (permalink / raw)
To: git; +Cc: jltobler, lucasseikioshiro, K Jayatheerth
External toolchains managing specialized history rewrites or legacy
history splices require access to the location of the repository grafts
file. Currently, this requires a legacy call to `git rev-parse --git-path info/grafts`.
Introduce `path.grafts.absolute` and `path.grafts.relative` keys to
`git repo info`. This allows scripting layers to query the active grafts
context cleanly while scaling transparently with active `GIT_GRAFT_FILE`
environment variable overrides.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Documentation/git-repo.adoc | 8 ++++++++
builtin/repo.c | 24 ++++++++++++++++++++++++
t/t1900-repo-info.sh | 6 ++++++
3 files changed, 38 insertions(+)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 3a837c573e..6c962620ec 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,14 @@ values that they return:
`path.gitdir.relative`::
The path to the Git repository directory relative to the current working directory.
+`path.grafts.absolute`::
+ The canonical absolute path to the repository grafts file.
+ Respects the `GIT_GRAFT_FILE` environment override.
+
+`path.grafts.relative`::
+ The path to the repository grafts file relative to the current working
+ directory. Respects the `GIT_GRAFT_FILE` environment override.
+
`path.hooks.absolute`::
The canonical absolute path to the repository's hooks directory.
Respects `core.hooksPath` configuration adjustments.
diff --git a/builtin/repo.c b/builtin/repo.c
index 66bf4c67cc..a97ad71649 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,28 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
return 0;
}
+static int get_path_grafts_absolute(struct repository *repo, struct strbuf *buf)
+{
+ const char *graft_file = repo_get_graft_file(repo);
+
+ if (!graft_file)
+ return error(_("unable to get graft file"));
+
+ format_path(buf, graft_file, startup_info->prefix, PATH_FORMAT_CANONICAL);
+ return 0;
+}
+
+static int get_path_grafts_relative(struct repository *repo, struct strbuf *buf)
+{
+ const char *graft_file = repo_get_graft_file(repo);
+
+ if (!graft_file)
+ return error(_("unable to get graft file"));
+
+ format_path(buf, graft_file, startup_info->prefix, PATH_FORMAT_RELATIVE);
+ return 0;
+}
+
static int get_path_hooks_absolute(struct repository *repo, struct strbuf *buf)
{
struct strbuf hooks_path = STRBUF_INIT;
@@ -258,6 +280,8 @@ static const struct repo_info_field repo_info_field[] = {
{ "path.commondir.relative", get_path_commondir_relative },
{ "path.gitdir.absolute", get_path_gitdir_absolute },
{ "path.gitdir.relative", get_path_gitdir_relative },
+ { "path.grafts.absolute", get_path_grafts_absolute },
+ { "path.grafts.relative", get_path_grafts_relative },
{ "path.hooks.absolute", get_path_hooks_absolute },
{ "path.hooks.relative", get_path_hooks_relative },
{ "path.index.absolute", get_path_index_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 04e6b8553c..6c47989df7 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,12 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
'.git' \
'GIT_DIR="../.git" && export GIT_DIR'
+test_repo_info_path 'grafts standard' 'grafts' '.git/info/grafts'
+
+test_repo_info_path 'grafts with GIT_GRAFT_FILE override' 'grafts' \
+ 'custom-graft-file' \
+ 'GIT_GRAFT_FILE="$ROOT/custom-graft-file" && export GIT_GRAFT_FILE'
+
test_repo_info_path 'hooks standard fallback' 'hooks' '.git/hooks'
test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
--
2.55.GIT
^ permalink raw reply related [flat|nested] 21+ messages in thread* [GSoC Patch 7/7] repo: add path.git-prefix path key validation
2026-07-16 1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
` (5 preceding siblings ...)
2026-07-16 1:21 ` [GSoC Patch 6/7] repo: add path.grafts " K Jayatheerth
@ 2026-07-16 1:21 ` K Jayatheerth
2026-07-16 3:23 ` Junio C Hamano
2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
7 siblings, 1 reply; 21+ messages in thread
From: K Jayatheerth @ 2026-07-16 1:21 UTC (permalink / raw)
To: git; +Cc: jltobler, lucasseikioshiro, K Jayatheerth
Scripts and command-line prompt integrations frequently need to know their
relative depth inside a repository working tree layout. Currently, this
is retrieved using `git rev-parse --show-prefix`.
Introduce the `path.git-prefix` key to `git repo info`. This mirrors the
prefix location tracking framework as a standalone key, returning the
exact relative path offset complete with a trailing slash, or an empty
string if run directly at the repository working tree root.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Documentation/git-repo.adoc | 5 +++++
builtin/repo.c | 12 ++++++++++++
t/t1900-repo-info.sh | 19 +++++++++++++++++++
3 files changed, 36 insertions(+)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 6c962620ec..5ba2ab1612 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -113,6 +113,11 @@ values that they return:
The path to the Git repository's common directory relative to
the current working directory.
+`path.git-prefix`::
+ The relative path from the top-level directory of the working tree to
+ the current working directory (including a trailing slash). Outputs an
+ empty string if executed at the root of the working tree.
+
`path.gitdir.absolute`::
The canonical absolute path to the Git repository directory (the `.git` directory).
diff --git a/builtin/repo.c b/builtin/repo.c
index a97ad71649..00d5064281 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -1,3 +1,4 @@
+#include "compat/posix.h"
#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
@@ -100,6 +101,16 @@ static int get_path_commondir_relative(struct repository *repo, struct strbuf *b
return 0;
}
+static int get_path_git_prefix(struct repository *repo UNUSED, struct strbuf *buf)
+{
+ /*
+ * startup_info->prefix is NULL if we are at the working tree root.
+ * We add an empty string to ensure the buffer is cleanly initialized.
+ */
+ strbuf_addstr(buf, startup_info->prefix ? startup_info->prefix : "");
+ return 0;
+}
+
static int get_path_gitdir_absolute(struct repository *repo, struct strbuf *buf)
{
const char *git_dir = repo_get_git_dir(repo);
@@ -278,6 +289,7 @@ static const struct repo_info_field repo_info_field[] = {
{ "object.format", get_object_format },
{ "path.commondir.absolute", get_path_commondir_absolute },
{ "path.commondir.relative", get_path_commondir_relative },
+ { "path.git-prefix", get_path_git_prefix },
{ "path.gitdir.absolute", get_path_gitdir_absolute },
{ "path.gitdir.relative", get_path_gitdir_relative },
{ "path.grafts.absolute", get_path_grafts_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 6c47989df7..3e5e42f6d3 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -207,6 +207,25 @@ test_repo_info_path 'commondir with only GIT_DIR' 'commondir' \
'.git' \
'GIT_DIR="../.git" && export GIT_DIR'
+test_expect_success 'path.git-prefix at root and in a subdirectory' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ echo "path.git-prefix=" >expect.root &&
+ git repo info path.git-prefix >actual.root &&
+ test_cmp expect.root actual.root &&
+
+ mkdir -p sub/dir &&
+ cd sub/dir &&
+
+ echo "path.git-prefix=sub/dir/" >expect.sub &&
+ git repo info path.git-prefix >actual.sub &&
+ test_cmp expect.sub actual.sub
+ )
+'
+
test_repo_info_path 'gitdir standard' 'gitdir' '.git'
test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
--
2.55.GIT
^ permalink raw reply related [flat|nested] 21+ messages in thread* Re: [GSoC Patch 7/7] repo: add path.git-prefix path key validation
2026-07-16 1:21 ` [GSoC Patch 7/7] repo: add path.git-prefix path key validation K Jayatheerth
@ 2026-07-16 3:23 ` Junio C Hamano
2026-07-16 15:36 ` K Jayatheerth
0 siblings, 1 reply; 21+ messages in thread
From: Junio C Hamano @ 2026-07-16 3:23 UTC (permalink / raw)
To: K Jayatheerth; +Cc: git, jltobler, lucasseikioshiro
K Jayatheerth <jayatheerthkulkarni2005@gmail.com> writes:
> diff --git a/builtin/repo.c b/builtin/repo.c
> index a97ad71649..00d5064281 100644
> --- a/builtin/repo.c
> +++ b/builtin/repo.c
> @@ -1,3 +1,4 @@
> +#include "compat/posix.h"
> #define USE_THE_REPOSITORY_VARIABLE
> #include "builtin.h"
The first include must be <git-compat-util.h> or common include
files that include <git-compat-util.h> as the first thing, like
<builtin.h>.
As the file already includes <builtin.h>, extra inclusion of
<compat/posix.h> before everything else is an absolute no-no.
By the way, I do not see any "validation" in the patch as the title
claims. Perhaps retitle it to "repo: add path.git-prefix key" or
something simpler like that?
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [GSoC Patch 7/7] repo: add path.git-prefix path key validation
2026-07-16 3:23 ` Junio C Hamano
@ 2026-07-16 15:36 ` K Jayatheerth
0 siblings, 0 replies; 21+ messages in thread
From: K Jayatheerth @ 2026-07-16 15:36 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, jltobler, lucasseikioshiro
Hey Junio,
On Thu, Jul 16, 2026 at 8:53 AM Junio C Hamano <gitster@pobox.com> wrote:
>
> K Jayatheerth <jayatheerthkulkarni2005@gmail.com> writes:
>
> > diff --git a/builtin/repo.c b/builtin/repo.c
> > index a97ad71649..00d5064281 100644
> > --- a/builtin/repo.c
> > +++ b/builtin/repo.c
> > @@ -1,3 +1,4 @@
> > +#include "compat/posix.h"
> > #define USE_THE_REPOSITORY_VARIABLE
> > #include "builtin.h"
>
> The first include must be <git-compat-util.h> or common include
> files that include <git-compat-util.h> as the first thing, like
> <builtin.h>.
>
> As the file already includes <builtin.h>, extra inclusion of
> <compat/posix.h> before everything else is an absolute no-no.
>
Oh no, that's just my editor adding headers automatically.
Thanks for pointing this out, I will fix it.
> By the way, I do not see any "validation" in the patch as the title
> claims. Perhaps retitle it to "repo: add path.git-prefix key" or
> something simpler like that?
>
True, I will correct that as well.
Regards,
- K Jayatheerth
^ permalink raw reply [flat|nested] 21+ messages in thread
* [GSoC Patch v2 0/7] repo: add more path keys to git repo info
2026-07-16 1:21 [GSoC Patch 0/7] repo: add more path keys to git repo info K Jayatheerth
` (6 preceding siblings ...)
2026-07-16 1:21 ` [GSoC Patch 7/7] repo: add path.git-prefix path key validation K Jayatheerth
@ 2026-07-17 13:30 ` K Jayatheerth
2026-07-17 13:30 ` [GSoC Patch v2 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
` (6 more replies)
7 siblings, 7 replies; 21+ messages in thread
From: K Jayatheerth @ 2026-07-17 13:30 UTC (permalink / raw)
To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro
Series adds keys to git repo info.
Keys output paths of repository components:
* path.toplevel: repository tree.
* path.superproject-working-tree: superproject tree from submodules.
* path.objects: repository objects.
* path.hooks: repository hooks.
* path.index: repository index.
* path.grafts: repository grafts.
* path.git-prefix: prefix offset.
Keys support suffixes for format.
Commits contain documentation and tests.
K Jayatheerth (7):
repo: add path.toplevel with absolute and relative suffix formatting
repo: add path.superproject-working-tree with absolute and relative
suffixes
repo: add path.objects with absolute and relative suffix formatting
repo: add path.hooks with absolute and relative suffix formatting
repo: add path.index with absolute and relative suffix formatting
repo: add path.grafts with absolute and relative suffix formatting
repo: add path.git-prefix path key
Documentation/git-repo.adoc | 58 +++++++++++++
builtin/repo.c | 166 ++++++++++++++++++++++++++++++++++++
t/t1900-repo-info.sh | 108 +++++++++++++++++++++++
3 files changed, 332 insertions(+)
--
2.55.GIT
^ permalink raw reply [flat|nested] 21+ messages in thread* [GSoC Patch v2 1/7] repo: add path.toplevel with absolute and relative suffix formatting
2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
@ 2026-07-17 13:30 ` K Jayatheerth
2026-07-17 13:30 ` [GSoC Patch v2 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes K Jayatheerth
` (5 subsequent siblings)
6 siblings, 0 replies; 21+ messages in thread
From: K Jayatheerth @ 2026-07-17 13:30 UTC (permalink / raw)
To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro
Scripts frequently need to find the root directory of a repository's
working tree. Currently, this requires using `git rev-parse --show-toplevel`
or inferring it from other path components.
Introduce `path.toplevel.absolute` and `path.toplevel.relative` keys
to `git repo info`. This allows scripts to retrieve the top-level
working tree path in a predictable, strictly formatted manner without
relying on `rev-parse`.
If requested in a bare repository where no working tree exists, the
command returns an empty string.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Documentation/git-repo.adoc | 10 ++++++++++
builtin/repo.c | 28 ++++++++++++++++++++++++++++
t/t1900-repo-info.sh | 30 ++++++++++++++++++++++++++++++
3 files changed, 68 insertions(+)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index ed7d80c690..e34abe5fea 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,16 @@ values that they return:
`path.gitdir.relative`::
The path to the Git repository directory relative to the current working directory.
+`path.toplevel.absolute`::
+ The canonical absolute path to the top-level directory of the
+ repository's working tree. Outputs an empty string if the repository
+ is bare.
+
+`path.toplevel.relative`::
+ The path to the top-level directory of the repository's working
+ tree relative to the current working directory. Outputs an empty
+ string if the repository is bare.
+
`references.format`::
The reference storage format. The valid values are:
+
diff --git a/builtin/repo.c b/builtin/repo.c
index 042d6de558..194757eb18 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -121,6 +121,32 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
return 0;
}
+static int get_path_toplevel_absolute(struct repository *repo, struct strbuf *buf)
+{
+ const char *work_tree = repo_get_work_tree(repo);
+
+ if (!work_tree) {
+ strbuf_addstr(buf, "");
+ return 0;
+ }
+
+ format_path(buf, work_tree, startup_info->prefix, PATH_FORMAT_CANONICAL);
+ return 0;
+}
+
+static int get_path_toplevel_relative(struct repository *repo, struct strbuf *buf)
+{
+ const char *work_tree = repo_get_work_tree(repo);
+
+ if (!work_tree) {
+ strbuf_addstr(buf, "");
+ return 0;
+ }
+
+ format_path(buf, work_tree, startup_info->prefix, PATH_FORMAT_RELATIVE);
+ return 0;
+}
+
static int get_references_format(struct repository *repo, struct strbuf *buf)
{
strbuf_addstr(buf,
@@ -137,6 +163,8 @@ static const struct repo_info_field repo_info_field[] = {
{ "path.commondir.relative", get_path_commondir_relative },
{ "path.gitdir.absolute", get_path_gitdir_absolute },
{ "path.gitdir.relative", get_path_gitdir_relative },
+ { "path.toplevel.absolute", get_path_toplevel_absolute },
+ { "path.toplevel.relative", get_path_toplevel_relative },
{ "references.format", get_references_format },
};
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index ae8c22c817..fbb9063ee5 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,4 +213,34 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
'.git' \
'GIT_DIR="../.git" && export GIT_DIR'
+test_expect_success 'path.toplevel absolute and relative' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ mkdir -p repo/sub &&
+ cd repo/sub &&
+
+ ROOT="$(test-tool path-utils real_path ..)" &&
+
+ echo "path.toplevel.absolute=$ROOT" >expect.abs &&
+ git repo info path.toplevel.absolute >actual.abs &&
+ test_cmp expect.abs actual.abs &&
+
+ echo "path.toplevel.relative=../" >expect.rel &&
+ git repo info path.toplevel.relative >actual.rel &&
+ test_cmp expect.rel actual.rel
+ )
+'
+
+test_expect_success 'path.toplevel returns empty in a bare repository' '
+ test_when_finished "rm -rf bare.git" &&
+ git init --bare bare.git &&
+ (
+ cd bare.git &&
+ echo "path.toplevel.absolute=" >expect &&
+ git repo info path.toplevel.absolute >actual &&
+ test_cmp expect actual
+ )
+'
+
test_done
--
2.55.GIT
^ permalink raw reply related [flat|nested] 21+ messages in thread* [GSoC Patch v2 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes
2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
2026-07-17 13:30 ` [GSoC Patch v2 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
@ 2026-07-17 13:30 ` K Jayatheerth
2026-07-17 13:30 ` [GSoC Patch v2 3/7] repo: add path.objects with absolute and relative suffix formatting K Jayatheerth
` (4 subsequent siblings)
6 siblings, 0 replies; 21+ messages in thread
From: K Jayatheerth @ 2026-07-17 13:30 UTC (permalink / raw)
To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro
Scripts working in multi-repository setups often need to identify the
top-level working tree of a superproject from within a submodule.
Currently, this is only exposed via `git rev-parse
--show-superproject-working-tree`.
Introduce `path.superproject-working-tree.absolute` and
`path.superproject-working-tree.relative` keys to `git repo info`.
This exposes the core submodule context via a scriptable config-like key
using standard format rules.
If requested when not inside a submodule, the command returns an empty
string.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Documentation/git-repo.adoc | 10 ++++++++++
builtin/repo.c | 33 +++++++++++++++++++++++++++++++++
t/t1900-repo-info.sh | 34 ++++++++++++++++++++++++++++++++++
3 files changed, 77 insertions(+)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index e34abe5fea..03aa57942f 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,16 @@ values that they return:
`path.gitdir.relative`::
The path to the Git repository directory relative to the current working directory.
+`path.superproject-working-tree.absolute`::
+ The canonical absolute path to the working tree root of the superproject
+ if the current repository is an initialized submodule. Outputs an empty
+ string if not in a submodule.
+
+`path.superproject-working-tree.relative`::
+ The path to the working tree root of the superproject relative to the
+ current working directory if the current repository is an initialized
+ submodule. Outputs an empty string if not in a submodule.
+
`path.toplevel.absolute`::
The canonical absolute path to the top-level directory of the
repository's working tree. Outputs an empty string if the repository
diff --git a/builtin/repo.c b/builtin/repo.c
index 194757eb18..82359473e9 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -18,6 +18,7 @@
#include "strbuf.h"
#include "string-list.h"
#include "shallow.h"
+#include "submodule.h"
#include "tree.h"
#include "tree-walk.h"
#include "utf8.h"
@@ -121,6 +122,36 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
return 0;
}
+static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
+{
+ struct strbuf superproject = STRBUF_INIT;
+
+ if (!get_superproject_working_tree(&superproject)) {
+ strbuf_release(&superproject);
+ strbuf_addstr(buf, "");
+ return 0;
+ }
+
+ format_path(buf, superproject.buf, startup_info->prefix, PATH_FORMAT_CANONICAL);
+ strbuf_release(&superproject);
+ return 0;
+}
+
+static int get_path_superproject_relative(struct repository *repo UNUSED, struct strbuf *buf)
+{
+ struct strbuf superproject = STRBUF_INIT;
+
+ if (!get_superproject_working_tree(&superproject)) {
+ strbuf_release(&superproject);
+ strbuf_addstr(buf, "");
+ return 0;
+ }
+
+ format_path(buf, superproject.buf, startup_info->prefix, PATH_FORMAT_RELATIVE);
+ strbuf_release(&superproject);
+ return 0;
+}
+
static int get_path_toplevel_absolute(struct repository *repo, struct strbuf *buf)
{
const char *work_tree = repo_get_work_tree(repo);
@@ -163,6 +194,8 @@ static const struct repo_info_field repo_info_field[] = {
{ "path.commondir.relative", get_path_commondir_relative },
{ "path.gitdir.absolute", get_path_gitdir_absolute },
{ "path.gitdir.relative", get_path_gitdir_relative },
+ { "path.superproject-working-tree.absolute", get_path_superproject_absolute },
+ { "path.superproject-working-tree.relative", get_path_superproject_relative },
{ "path.toplevel.absolute", get_path_toplevel_absolute },
{ "path.toplevel.relative", get_path_toplevel_relative },
{ "references.format", get_references_format },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index fbb9063ee5..220b3d4d3d 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,40 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
'.git' \
'GIT_DIR="../.git" && export GIT_DIR'
+test_expect_success 'path.superproject-working-tree absolute and relative' '
+ test_when_finished "rm -rf sub super" &&
+ git init sub &&
+ test_commit -C sub initial &&
+ git init super &&
+ (
+ cd super &&
+ git -c protocol.file.allow=always submodule add "../sub" sub &&
+ git commit -m "add submodule" &&
+
+ cd sub &&
+ ROOT="$(test-tool path-utils real_path ..)" &&
+
+ echo "path.superproject-working-tree.absolute=$ROOT" >expect.abs &&
+ git repo info path.superproject-working-tree.absolute >actual.abs &&
+ test_cmp expect.abs actual.abs &&
+
+ echo "path.superproject-working-tree.relative=../" >expect.rel &&
+ git repo info path.superproject-working-tree.relative >actual.rel &&
+ test_cmp expect.rel actual.rel
+ )
+'
+
+test_expect_success 'path.superproject-working-tree returns empty when not in a submodule' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ echo "path.superproject-working-tree.absolute=" >expect &&
+ git repo info path.superproject-working-tree.absolute >actual &&
+ test_cmp expect actual
+ )
+'
+
test_expect_success 'path.toplevel absolute and relative' '
test_when_finished "rm -rf repo" &&
git init repo &&
--
2.55.GIT
^ permalink raw reply related [flat|nested] 21+ messages in thread* [GSoC Patch v2 3/7] repo: add path.objects with absolute and relative suffix formatting
2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
2026-07-17 13:30 ` [GSoC Patch v2 1/7] repo: add path.toplevel with absolute and relative suffix formatting K Jayatheerth
2026-07-17 13:30 ` [GSoC Patch v2 2/7] repo: add path.superproject-working-tree with absolute and relative suffixes K Jayatheerth
@ 2026-07-17 13:30 ` K Jayatheerth
2026-07-17 13:30 ` [GSoC Patch v2 4/7] repo: add path.hooks " K Jayatheerth
` (3 subsequent siblings)
6 siblings, 0 replies; 21+ messages in thread
From: K Jayatheerth @ 2026-07-17 13:30 UTC (permalink / raw)
To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro
Tools and deployment hooks frequently query the location of the object
database directory. Currently, this relies on legacy parsing methods or
manually inspecting `git rev-parse --git-path objects`.
Introduce `path.objects.absolute` and `path.objects.relative` keys to
`git repo info`. This allows tools to discover the object database
location safely while natively adhering to active `GIT_OBJECT_DIRECTORY`
environment variable overrides.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Documentation/git-repo.adoc | 9 +++++++++
builtin/repo.c | 24 ++++++++++++++++++++++++
t/t1900-repo-info.sh | 7 +++++++
3 files changed, 40 insertions(+)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 03aa57942f..8429a44b43 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,15 @@ values that they return:
`path.gitdir.relative`::
The path to the Git repository directory relative to the current working directory.
+`path.objects.absolute`::
+ The canonical absolute path to the repository's object database directory.
+ Respects the `GIT_OBJECT_DIRECTORY` environment override.
+
+`path.objects.relative`::
+ The path to the repository's object database directory relative to the
+ current working directory. Respects the `GIT_OBJECT_DIRECTORY`
+ environment override.
+
`path.superproject-working-tree.absolute`::
The canonical absolute path to the working tree root of the superproject
if the current repository is an initialized submodule. Outputs an empty
diff --git a/builtin/repo.c b/builtin/repo.c
index 82359473e9..d6bdd5bcfa 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,28 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
return 0;
}
+static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
+{
+ const char *obj_dir = repo_get_object_directory(repo);
+
+ if (!obj_dir)
+ return error(_("unable to get object directory"));
+
+ format_path(buf, obj_dir, startup_info->prefix, PATH_FORMAT_CANONICAL);
+ return 0;
+}
+
+static int get_path_objects_relative(struct repository *repo, struct strbuf *buf)
+{
+ const char *obj_dir = repo_get_object_directory(repo);
+
+ if (!obj_dir)
+ return error(_("unable to get object directory"));
+
+ format_path(buf, obj_dir, startup_info->prefix, PATH_FORMAT_RELATIVE);
+ return 0;
+}
+
static int get_path_superproject_absolute(struct repository *repo UNUSED, struct strbuf *buf)
{
struct strbuf superproject = STRBUF_INIT;
@@ -194,6 +216,8 @@ static const struct repo_info_field repo_info_field[] = {
{ "path.commondir.relative", get_path_commondir_relative },
{ "path.gitdir.absolute", get_path_gitdir_absolute },
{ "path.gitdir.relative", get_path_gitdir_relative },
+ { "path.objects.absolute", get_path_objects_absolute },
+ { "path.objects.relative", get_path_objects_relative },
{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
{ "path.superproject-working-tree.relative", get_path_superproject_relative },
{ "path.toplevel.absolute", get_path_toplevel_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 220b3d4d3d..260f4fde43 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,13 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
'.git' \
'GIT_DIR="../.git" && export GIT_DIR'
+test_repo_info_path 'objects standard' 'objects' '.git/objects'
+
+test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
+ 'custom-objects' \
+ 'GIT_OBJECT_DIRECTORY="$ROOT/custom-objects" && export GIT_OBJECT_DIRECTORY &&
+ mkdir -p "$ROOT/custom-objects"'
+
test_expect_success 'path.superproject-working-tree absolute and relative' '
test_when_finished "rm -rf sub super" &&
git init sub &&
--
2.55.GIT
^ permalink raw reply related [flat|nested] 21+ messages in thread* [GSoC Patch v2 4/7] repo: add path.hooks with absolute and relative suffix formatting
2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
` (2 preceding siblings ...)
2026-07-17 13:30 ` [GSoC Patch v2 3/7] repo: add path.objects with absolute and relative suffix formatting K Jayatheerth
@ 2026-07-17 13:30 ` K Jayatheerth
2026-07-17 13:30 ` [GSoC Patch v2 5/7] repo: add path.index " K Jayatheerth
` (2 subsequent siblings)
6 siblings, 0 replies; 21+ messages in thread
From: K Jayatheerth @ 2026-07-17 13:30 UTC (permalink / raw)
To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro
External tool integrations and validation systems need a stable way to
identify where the repository hooks are stored. Currently, this involves
relying on `git rev-parse --git-path hooks` or querying `core.hooksPath`
manually.
Introduce `path.hooks.absolute` and `path.hooks.relative` keys to
`git repo info`. This allows tools to discover the active hooks location
natively, ensuring proper resolution regardless of whether Git is using
the standard `.git/hooks` structure or a custom `core.hooksPath` setup.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Documentation/git-repo.adoc | 8 ++++++++
builtin/repo.c | 22 ++++++++++++++++++++++
t/t1900-repo-info.sh | 6 ++++++
3 files changed, 36 insertions(+)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 8429a44b43..7bc1c51310 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,14 @@ values that they return:
`path.gitdir.relative`::
The path to the Git repository directory relative to the current working directory.
+`path.hooks.absolute`::
+ The canonical absolute path to the repository's hooks directory.
+ Respects `core.hooksPath` configuration adjustments.
+
+`path.hooks.relative`::
+ The path to the repository's hooks directory relative to the current
+ working directory. Respects `core.hooksPath` configuration adjustments.
+
`path.objects.absolute`::
The canonical absolute path to the repository's object database directory.
Respects the `GIT_OBJECT_DIRECTORY` environment override.
diff --git a/builtin/repo.c b/builtin/repo.c
index d6bdd5bcfa..c921de222d 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,26 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
return 0;
}
+static int get_path_hooks_absolute(struct repository *repo, struct strbuf *buf)
+{
+ struct strbuf hooks_path = STRBUF_INIT;
+
+ repo_git_path_replace(repo, &hooks_path, "hooks");
+ format_path(buf, hooks_path.buf, startup_info->prefix, PATH_FORMAT_CANONICAL);
+ strbuf_release(&hooks_path);
+ return 0;
+}
+
+static int get_path_hooks_relative(struct repository *repo, struct strbuf *buf)
+{
+ struct strbuf hooks_path = STRBUF_INIT;
+
+ repo_git_path_replace(repo, &hooks_path, "hooks");
+ format_path(buf, hooks_path.buf, startup_info->prefix, PATH_FORMAT_RELATIVE);
+ strbuf_release(&hooks_path);
+ return 0;
+}
+
static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
{
const char *obj_dir = repo_get_object_directory(repo);
@@ -216,6 +236,8 @@ static const struct repo_info_field repo_info_field[] = {
{ "path.commondir.relative", get_path_commondir_relative },
{ "path.gitdir.absolute", get_path_gitdir_absolute },
{ "path.gitdir.relative", get_path_gitdir_relative },
+ { "path.hooks.absolute", get_path_hooks_absolute },
+ { "path.hooks.relative", get_path_hooks_relative },
{ "path.objects.absolute", get_path_objects_absolute },
{ "path.objects.relative", get_path_objects_relative },
{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 260f4fde43..cd3f856d04 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,12 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
'.git' \
'GIT_DIR="../.git" && export GIT_DIR'
+test_repo_info_path 'hooks standard fallback' 'hooks' '.git/hooks'
+
+test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
+ 'custom-hooks' \
+ 'git config core.hooksPath "$ROOT/custom-hooks" && mkdir -p "$ROOT/custom-hooks"'
+
test_repo_info_path 'objects standard' 'objects' '.git/objects'
test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
--
2.55.GIT
^ permalink raw reply related [flat|nested] 21+ messages in thread* [GSoC Patch v2 5/7] repo: add path.index with absolute and relative suffix formatting
2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
` (3 preceding siblings ...)
2026-07-17 13:30 ` [GSoC Patch v2 4/7] repo: add path.hooks " K Jayatheerth
@ 2026-07-17 13:30 ` K Jayatheerth
2026-07-20 0:35 ` Lucas Seiki Oshiro
2026-07-17 13:30 ` [GSoC Patch v2 6/7] repo: add path.grafts " K Jayatheerth
2026-07-17 13:30 ` [GSoC Patch v2 7/7] repo: add path.git-prefix path key K Jayatheerth
6 siblings, 1 reply; 21+ messages in thread
From: K Jayatheerth @ 2026-07-17 13:30 UTC (permalink / raw)
To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro
External script workflows and formatting layers require straightforward
access to the location of the index staging file. Currently, tracking
this necessitates a legacy call to `git rev-parse --git-path index` or
`--show-toplevel` logic abstractions.
Introduce `path.index.absolute` and `path.index.relative` keys to
`git repo info`. This allows tooling utilities to discover the active
index context cleanly while scaling transparently with localized
`GIT_INDEX_FILE` environment overrides.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Documentation/git-repo.adoc | 8 ++++++++
builtin/repo.c | 24 ++++++++++++++++++++++++
t/t1900-repo-info.sh | 6 ++++++
3 files changed, 38 insertions(+)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 7bc1c51310..3a837c573e 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -127,6 +127,14 @@ values that they return:
The path to the repository's hooks directory relative to the current
working directory. Respects `core.hooksPath` configuration adjustments.
+`path.index.absolute`::
+ The canonical absolute path to the repository's current index file.
+ Respects the `GIT_INDEX_FILE` environment override.
+
+`path.index.relative`::
+ The path to the repository's current index file relative to the current
+ working directory. Respects the `GIT_INDEX_FILE` environment override.
+
`path.objects.absolute`::
The canonical absolute path to the repository's object database directory.
Respects the `GIT_OBJECT_DIRECTORY` environment override.
diff --git a/builtin/repo.c b/builtin/repo.c
index c921de222d..66bf4c67cc 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -142,6 +142,28 @@ static int get_path_hooks_relative(struct repository *repo, struct strbuf *buf)
return 0;
}
+static int get_path_index_absolute(struct repository *repo, struct strbuf *buf)
+{
+ const char *index_file = repo_get_index_file(repo);
+
+ if (!index_file)
+ return error(_("unable to get index file"));
+
+ format_path(buf, index_file, startup_info->prefix, PATH_FORMAT_CANONICAL);
+ return 0;
+}
+
+static int get_path_index_relative(struct repository *repo, struct strbuf *buf)
+{
+ const char *index_file = repo_get_index_file(repo);
+
+ if (!index_file)
+ return error(_("unable to get index file"));
+
+ format_path(buf, index_file, startup_info->prefix, PATH_FORMAT_RELATIVE);
+ return 0;
+}
+
static int get_path_objects_absolute(struct repository *repo, struct strbuf *buf)
{
const char *obj_dir = repo_get_object_directory(repo);
@@ -238,6 +260,8 @@ static const struct repo_info_field repo_info_field[] = {
{ "path.gitdir.relative", get_path_gitdir_relative },
{ "path.hooks.absolute", get_path_hooks_absolute },
{ "path.hooks.relative", get_path_hooks_relative },
+ { "path.index.absolute", get_path_index_absolute },
+ { "path.index.relative", get_path_index_relative },
{ "path.objects.absolute", get_path_objects_absolute },
{ "path.objects.relative", get_path_objects_relative },
{ "path.superproject-working-tree.absolute", get_path_superproject_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index cd3f856d04..04e6b8553c 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -219,6 +219,12 @@ test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
'custom-hooks' \
'git config core.hooksPath "$ROOT/custom-hooks" && mkdir -p "$ROOT/custom-hooks"'
+test_repo_info_path 'index standard' 'index' '.git/index'
+
+test_repo_info_path 'index with GIT_INDEX_FILE override' 'index' \
+ 'custom-index-file' \
+ 'GIT_INDEX_FILE="$ROOT/custom-index-file" && export GIT_INDEX_FILE'
+
test_repo_info_path 'objects standard' 'objects' '.git/objects'
test_repo_info_path 'objects with GIT_OBJECT_DIRECTORY override' 'objects' \
--
2.55.GIT
^ permalink raw reply related [flat|nested] 21+ messages in thread* Re: [GSoC Patch v2 5/7] repo: add path.index with absolute and relative suffix formatting
2026-07-17 13:30 ` [GSoC Patch v2 5/7] repo: add path.index " K Jayatheerth
@ 2026-07-20 0:35 ` Lucas Seiki Oshiro
0 siblings, 0 replies; 21+ messages in thread
From: Lucas Seiki Oshiro @ 2026-07-20 0:35 UTC (permalink / raw)
To: K Jayatheerth; +Cc: git, jltobler, Junio C Hamano
> Introduce `path.index.absolute` and `path.index.relative` keys to
> `git repo info`. This allows tooling utilities to discover the active
> index context cleanly while scaling transparently with localized
> `GIT_INDEX_FILE` environment overrides.
Note that bare repositories doesn't need to have an index file. Maybe
it would be better if you return an empty value in those cases.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [GSoC Patch v2 6/7] repo: add path.grafts with absolute and relative suffix formatting
2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
` (4 preceding siblings ...)
2026-07-17 13:30 ` [GSoC Patch v2 5/7] repo: add path.index " K Jayatheerth
@ 2026-07-17 13:30 ` K Jayatheerth
2026-07-20 0:20 ` Lucas Seiki Oshiro
2026-07-17 13:30 ` [GSoC Patch v2 7/7] repo: add path.git-prefix path key K Jayatheerth
6 siblings, 1 reply; 21+ messages in thread
From: K Jayatheerth @ 2026-07-17 13:30 UTC (permalink / raw)
To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro
External toolchains managing specialized history rewrites or legacy
history splices require access to the location of the repository grafts
file. Currently, this requires a legacy call to `git rev-parse --git-path info/grafts`.
Introduce `path.grafts.absolute` and `path.grafts.relative` keys to
`git repo info`. This allows scripting layers to query the active grafts
context cleanly while scaling transparently with active `GIT_GRAFT_FILE`
environment variable overrides.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Documentation/git-repo.adoc | 8 ++++++++
builtin/repo.c | 24 ++++++++++++++++++++++++
t/t1900-repo-info.sh | 6 ++++++
3 files changed, 38 insertions(+)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 3a837c573e..6c962620ec 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -119,6 +119,14 @@ values that they return:
`path.gitdir.relative`::
The path to the Git repository directory relative to the current working directory.
+`path.grafts.absolute`::
+ The canonical absolute path to the repository grafts file.
+ Respects the `GIT_GRAFT_FILE` environment override.
+
+`path.grafts.relative`::
+ The path to the repository grafts file relative to the current working
+ directory. Respects the `GIT_GRAFT_FILE` environment override.
+
`path.hooks.absolute`::
The canonical absolute path to the repository's hooks directory.
Respects `core.hooksPath` configuration adjustments.
diff --git a/builtin/repo.c b/builtin/repo.c
index 66bf4c67cc..a97ad71649 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -122,6 +122,28 @@ static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
return 0;
}
+static int get_path_grafts_absolute(struct repository *repo, struct strbuf *buf)
+{
+ const char *graft_file = repo_get_graft_file(repo);
+
+ if (!graft_file)
+ return error(_("unable to get graft file"));
+
+ format_path(buf, graft_file, startup_info->prefix, PATH_FORMAT_CANONICAL);
+ return 0;
+}
+
+static int get_path_grafts_relative(struct repository *repo, struct strbuf *buf)
+{
+ const char *graft_file = repo_get_graft_file(repo);
+
+ if (!graft_file)
+ return error(_("unable to get graft file"));
+
+ format_path(buf, graft_file, startup_info->prefix, PATH_FORMAT_RELATIVE);
+ return 0;
+}
+
static int get_path_hooks_absolute(struct repository *repo, struct strbuf *buf)
{
struct strbuf hooks_path = STRBUF_INIT;
@@ -258,6 +280,8 @@ static const struct repo_info_field repo_info_field[] = {
{ "path.commondir.relative", get_path_commondir_relative },
{ "path.gitdir.absolute", get_path_gitdir_absolute },
{ "path.gitdir.relative", get_path_gitdir_relative },
+ { "path.grafts.absolute", get_path_grafts_absolute },
+ { "path.grafts.relative", get_path_grafts_relative },
{ "path.hooks.absolute", get_path_hooks_absolute },
{ "path.hooks.relative", get_path_hooks_relative },
{ "path.index.absolute", get_path_index_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 04e6b8553c..6c47989df7 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -213,6 +213,12 @@ test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
'.git' \
'GIT_DIR="../.git" && export GIT_DIR'
+test_repo_info_path 'grafts standard' 'grafts' '.git/info/grafts'
+
+test_repo_info_path 'grafts with GIT_GRAFT_FILE override' 'grafts' \
+ 'custom-graft-file' \
+ 'GIT_GRAFT_FILE="$ROOT/custom-graft-file" && export GIT_GRAFT_FILE'
+
test_repo_info_path 'hooks standard fallback' 'hooks' '.git/hooks'
test_repo_info_path 'hooks with core.hooksPath override' 'hooks' \
--
2.55.GIT
^ permalink raw reply related [flat|nested] 21+ messages in thread* Re: [GSoC Patch v2 6/7] repo: add path.grafts with absolute and relative suffix formatting
2026-07-17 13:30 ` [GSoC Patch v2 6/7] repo: add path.grafts " K Jayatheerth
@ 2026-07-20 0:20 ` Lucas Seiki Oshiro
2026-07-20 4:01 ` Junio C Hamano
0 siblings, 1 reply; 21+ messages in thread
From: Lucas Seiki Oshiro @ 2026-07-20 0:20 UTC (permalink / raw)
To: K Jayatheerth; +Cc: git, jltobler, Junio C Hamano
> Introduce `path.grafts.absolute` and `path.grafts.relative` keys to
> `git repo info`. This allows scripting layers to query the active grafts
> context cleanly while scaling transparently with active `GIT_GRAFT_FILE`
> environment variable overrides.
I ran `git repo info path.grafts.relative` in a repository with no
`grafts` file, and it returned `.git/info/grafts`, which obviously
doesn't exist.
Wouldn't it be better if we check if that file exists before
returning this value?
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [GSoC Patch v2 6/7] repo: add path.grafts with absolute and relative suffix formatting
2026-07-20 0:20 ` Lucas Seiki Oshiro
@ 2026-07-20 4:01 ` Junio C Hamano
0 siblings, 0 replies; 21+ messages in thread
From: Junio C Hamano @ 2026-07-20 4:01 UTC (permalink / raw)
To: Lucas Seiki Oshiro; +Cc: K Jayatheerth, git, jltobler
Lucas Seiki Oshiro <lucasseikioshiro@gmail.com> writes:
>> Introduce `path.grafts.absolute` and `path.grafts.relative` keys to
>> `git repo info`. This allows scripting layers to query the active grafts
>> context cleanly while scaling transparently with active `GIT_GRAFT_FILE`
>> environment variable overrides.
>
> I ran `git repo info path.grafts.relative` in a repository with no
> `grafts` file, and it returned `.git/info/grafts`, which obviously
> doesn't exist.
>
> Wouldn't it be better if we check if that file exists before
> returning this value?
That is an interesting question, but I think it depends on who is
querying and for what purpose.
If a script is asking where to write the file, then the author wants
to know where the file is supposed to be, even if no such file
exists yet. Since the file format is public, they are free to write
their own tools to manipulate it.
Thanks.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [GSoC Patch v2 7/7] repo: add path.git-prefix path key
2026-07-17 13:30 ` [GSoC Patch v2 0/7] repo: add more path keys to git repo info K Jayatheerth
` (5 preceding siblings ...)
2026-07-17 13:30 ` [GSoC Patch v2 6/7] repo: add path.grafts " K Jayatheerth
@ 2026-07-17 13:30 ` K Jayatheerth
6 siblings, 0 replies; 21+ messages in thread
From: K Jayatheerth @ 2026-07-17 13:30 UTC (permalink / raw)
To: jayatheerthkulkarni2005; +Cc: git, jltobler, lucasseikioshiro
Scripts and command-line prompt integrations frequently need to know their
relative depth inside a repository working tree layout. Currently, this
is retrieved using `git rev-parse --show-prefix`.
Introduce the `path.git-prefix` key to `git repo info`. This mirrors the
prefix location tracking framework as a standalone key, returning the
exact relative path offset complete with a trailing slash, or an empty
string if run directly at the repository working tree root.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Documentation/git-repo.adoc | 5 +++++
builtin/repo.c | 11 +++++++++++
t/t1900-repo-info.sh | 19 +++++++++++++++++++
3 files changed, 35 insertions(+)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 6c962620ec..5ba2ab1612 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -113,6 +113,11 @@ values that they return:
The path to the Git repository's common directory relative to
the current working directory.
+`path.git-prefix`::
+ The relative path from the top-level directory of the working tree to
+ the current working directory (including a trailing slash). Outputs an
+ empty string if executed at the root of the working tree.
+
`path.gitdir.absolute`::
The canonical absolute path to the Git repository directory (the `.git` directory).
diff --git a/builtin/repo.c b/builtin/repo.c
index a97ad71649..b93c140c74 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -100,6 +100,16 @@ static int get_path_commondir_relative(struct repository *repo, struct strbuf *b
return 0;
}
+static int get_path_git_prefix(struct repository *repo UNUSED, struct strbuf *buf)
+{
+ /*
+ * startup_info->prefix is NULL if we are at the working tree root.
+ * We add an empty string to ensure the buffer is cleanly initialized.
+ */
+ strbuf_addstr(buf, startup_info->prefix ? startup_info->prefix : "");
+ return 0;
+}
+
static int get_path_gitdir_absolute(struct repository *repo, struct strbuf *buf)
{
const char *git_dir = repo_get_git_dir(repo);
@@ -278,6 +288,7 @@ static const struct repo_info_field repo_info_field[] = {
{ "object.format", get_object_format },
{ "path.commondir.absolute", get_path_commondir_absolute },
{ "path.commondir.relative", get_path_commondir_relative },
+ { "path.git-prefix", get_path_git_prefix },
{ "path.gitdir.absolute", get_path_gitdir_absolute },
{ "path.gitdir.relative", get_path_gitdir_relative },
{ "path.grafts.absolute", get_path_grafts_absolute },
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 6c47989df7..3e5e42f6d3 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -207,6 +207,25 @@ test_repo_info_path 'commondir with only GIT_DIR' 'commondir' \
'.git' \
'GIT_DIR="../.git" && export GIT_DIR'
+test_expect_success 'path.git-prefix at root and in a subdirectory' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ echo "path.git-prefix=" >expect.root &&
+ git repo info path.git-prefix >actual.root &&
+ test_cmp expect.root actual.root &&
+
+ mkdir -p sub/dir &&
+ cd sub/dir &&
+
+ echo "path.git-prefix=sub/dir/" >expect.sub &&
+ git repo info path.git-prefix >actual.sub &&
+ test_cmp expect.sub actual.sub
+ )
+'
+
test_repo_info_path 'gitdir standard' 'gitdir' '.git'
test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
--
2.55.GIT
^ permalink raw reply related [flat|nested] 21+ messages in thread