* [PATCH 0/7] setup: drop global state
@ 2026-06-10 6:56 Patrick Steinhardt
2026-06-10 6:56 ` [PATCH 1/7] builtin/init: stop modifying global `git_work_tree_cfg` variable Patrick Steinhardt
` (6 more replies)
0 siblings, 7 replies; 13+ messages in thread
From: Patrick Steinhardt @ 2026-06-10 6:56 UTC (permalink / raw)
To: git
Hi,
this patch series continues to refactor "setup.c", where the focus is to
drop remaining global state that we have in "setup.c". The most
important consequence of this is that we don't need to rely on
`the_repository` in `is_bare_repository()` anymore.
This series is built on top of 1ff279f340 (The 13th batch, 2026-06-09)
with ps/setup-centralize-odb-creation at 42b9d3dc9d (setup: construct
object database in `apply_repository_format()`, 2026-06-04) merged into
it.
Thanks!
Patrick
---
Patrick Steinhardt (7):
builtin/init: stop modifying global `git_work_tree_cfg` variable
builtin/init: simplify logic to configure worktree
setup: remove global `git_work_tree_cfg` variable
builtin/init: stop modifying `is_bare_repository_cfg`
environment: split up concerns of `is_bare_repository_cfg`
environment: stop using `the_repository` in `is_bare_repository()`
treewide: drop USE_THE_REPOSITORY_VARIABLE
attr.c | 4 ++--
builtin/bisect.c | 2 +-
builtin/blame.c | 2 +-
builtin/check-attr.c | 2 +-
builtin/fetch.c | 2 +-
builtin/gc.c | 2 +-
builtin/history.c | 2 +-
builtin/init-db.c | 44 +++++++++++++++++++++++++++-----------------
builtin/repack.c | 3 +--
builtin/repo.c | 2 +-
builtin/reset.c | 2 +-
builtin/rev-parse.c | 2 +-
environment.c | 10 +++-------
environment.h | 6 ++----
git.c | 2 +-
mailmap.c | 6 ++----
refs/files-backend.c | 2 +-
refs/reftable-backend.c | 4 +---
repository.c | 1 +
repository.h | 7 +++++++
setup.c | 45 ++++++++++++++++++++++++---------------------
setup.h | 6 ++++++
transport.c | 4 ++--
worktree.c | 4 ++--
24 files changed, 91 insertions(+), 75 deletions(-)
---
base-commit: f5a08a09a0fdf0fc2a355eba7979e2cfd65659e5
change-id: 20260422-b4-pks-setup-drop-global-state-6b1374aed5db
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/7] builtin/init: stop modifying global `git_work_tree_cfg` variable
2026-06-10 6:56 [PATCH 0/7] setup: drop global state Patrick Steinhardt
@ 2026-06-10 6:56 ` Patrick Steinhardt
2026-06-10 21:15 ` Justin Tobler
2026-06-10 6:56 ` [PATCH 2/7] builtin/init: simplify logic to configure worktree Patrick Steinhardt
` (5 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: Patrick Steinhardt @ 2026-06-10 6:56 UTC (permalink / raw)
To: git
When executing git-init(1) we need to figure out the final location of
the worktree. This location can be configured in a couple of ways: via
an environment variable, via the preexisting "core.worktree" config in
case we're reinitializing, or implicitly when reinitializing a non-bare
repository.
When checking for the worktree location in "builtin/init-db.c" we
populate any potentially-discovered value both by setting the global
`git_work_tree_cfg` variable and via `set_git_work_tree()`, which
ultimately ends up modifying `struct repository::worktree`.
Modifying `git_work_tree_cfg` is unnecessary though: we configure the
worktree in `create_default_files()`, and that function derives the
worktree location via `repo_get_work_tree()`. Consequently, propagating
the worktree via `set_git_work_tree()` is sufficient.
Stop munging `git_work_tree_cfg` and make it file-local to "setup.c" and
function-local to `cmd_init_db()`.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/init-db.c | 4 ++++
environment.c | 3 ---
environment.h | 1 -
setup.c | 3 +++
4 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/builtin/init-db.c b/builtin/init-db.c
index c55517ad94..01bc27904e 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -229,6 +229,8 @@ int cmd_init_db(int argc,
if (!is_bare_repository_cfg) {
const char *git_dir_parent = strrchr(git_dir, '/');
+ char *git_work_tree_cfg = NULL;
+
if (git_dir_parent) {
char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
git_work_tree_cfg = real_pathdup(rel, 1);
@@ -243,6 +245,8 @@ int cmd_init_db(int argc,
if (access(repo_get_work_tree(the_repository), X_OK))
die_errno (_("Cannot access work tree '%s'"),
repo_get_work_tree(the_repository));
+
+ free(git_work_tree_cfg);
}
else {
if (real_git_dir)
diff --git a/environment.c b/environment.c
index fc3ed8bb1c..4e86335f25 100644
--- a/environment.c
+++ b/environment.c
@@ -100,9 +100,6 @@ int auto_comment_line_char;
bool warn_on_auto_comment_char;
#endif /* !WITH_BREAKING_CHANGES */
-/* This is set by setup_git_directory_gently() and/or git_default_config() */
-char *git_work_tree_cfg;
-
/*
* Repository-local GIT_* environment variables; see environment.h for details.
*/
diff --git a/environment.h b/environment.h
index ccfcf37bfb..5d6e4e6c1b 100644
--- a/environment.h
+++ b/environment.h
@@ -149,7 +149,6 @@ int have_git_dir(void);
extern int is_bare_repository_cfg;
int is_bare_repository(void);
-extern char *git_work_tree_cfg;
/* Environment bits from configuration mechanism */
extern int trust_executable_bit;
diff --git a/setup.c b/setup.c
index b4652651df..52228b42a1 100644
--- a/setup.c
+++ b/setup.c
@@ -31,6 +31,9 @@ enum allowed_bare_repo {
ALLOWED_BARE_REPO_ALL,
};
+/* This is set by setup_git_directory_gently() and/or git_default_config() */
+static char *git_work_tree_cfg;
+
static struct startup_info the_startup_info;
struct startup_info *startup_info = &the_startup_info;
const char *tmp_original_cwd;
--
2.54.0.1189.g8c84645362.dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/7] builtin/init: simplify logic to configure worktree
2026-06-10 6:56 [PATCH 0/7] setup: drop global state Patrick Steinhardt
2026-06-10 6:56 ` [PATCH 1/7] builtin/init: stop modifying global `git_work_tree_cfg` variable Patrick Steinhardt
@ 2026-06-10 6:56 ` Patrick Steinhardt
2026-06-10 21:29 ` Justin Tobler
2026-06-10 6:56 ` [PATCH 3/7] setup: remove global `git_work_tree_cfg` variable Patrick Steinhardt
` (4 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: Patrick Steinhardt @ 2026-06-10 6:56 UTC (permalink / raw)
To: git
In the preceding commit we have stopped modifying the global
`git_work_tree_cfg` variable. With this change there's now some code
paths where we end up setting the local `git_work_tree_cfg` variable,
but without actually using the value for anything.
Refactor the code a bit so that we only set the worktree configuration
in case it's actually needed. Furthermore, reflow it a bit to make the
code easier to follow.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/init-db.c | 31 ++++++++++++++++++-------------
1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 01bc27904e..b4343c2804 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -229,24 +229,29 @@ int cmd_init_db(int argc,
if (!is_bare_repository_cfg) {
const char *git_dir_parent = strrchr(git_dir, '/');
- char *git_work_tree_cfg = NULL;
- if (git_dir_parent) {
- char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
- git_work_tree_cfg = real_pathdup(rel, 1);
- free(rel);
- }
- if (!git_work_tree_cfg)
- git_work_tree_cfg = xgetcwd();
- if (work_tree)
+ if (work_tree) {
set_git_work_tree(the_repository, work_tree);
- else
- set_git_work_tree(the_repository, git_work_tree_cfg);
+ } else {
+ char *work_tree_cfg = NULL;
+
+ if (git_dir_parent) {
+ char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
+ work_tree_cfg = real_pathdup(rel, 1);
+ free(rel);
+ }
+
+ if (!work_tree_cfg)
+ work_tree_cfg = xgetcwd();
+
+ set_git_work_tree(the_repository, work_tree_cfg);
+
+ free(work_tree_cfg);
+ }
+
if (access(repo_get_work_tree(the_repository), X_OK))
die_errno (_("Cannot access work tree '%s'"),
repo_get_work_tree(the_repository));
-
- free(git_work_tree_cfg);
}
else {
if (real_git_dir)
--
2.54.0.1189.g8c84645362.dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 3/7] setup: remove global `git_work_tree_cfg` variable
2026-06-10 6:56 [PATCH 0/7] setup: drop global state Patrick Steinhardt
2026-06-10 6:56 ` [PATCH 1/7] builtin/init: stop modifying global `git_work_tree_cfg` variable Patrick Steinhardt
2026-06-10 6:56 ` [PATCH 2/7] builtin/init: simplify logic to configure worktree Patrick Steinhardt
@ 2026-06-10 6:56 ` Patrick Steinhardt
2026-06-10 21:52 ` Justin Tobler
2026-06-10 6:56 ` [PATCH 4/7] builtin/init: stop modifying `is_bare_repository_cfg` Patrick Steinhardt
` (3 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: Patrick Steinhardt @ 2026-06-10 6:56 UTC (permalink / raw)
To: git
The global `git_work_tree_cfg` variable used to be modified by both
"setup.c" and by "builtin/init-db.c". We have refactored the latter user
to not use that variable at all anymore in a preceding commit, which
makes "setup.c" the only remaining user.
Even for "setup.c" it is unnecessary though, as we only ever set it to
the value we have stored in the discovered repository format. The
consequence is that we only ever set it in case we already have it set
to the same value in our discovered repository format, which makes it
redundant.
Refactor the code so that we instead use the worktree configuration as
discovered via the repository format. Drop the global variable.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
setup.c | 28 +++++++++++-----------------
1 file changed, 11 insertions(+), 17 deletions(-)
diff --git a/setup.c b/setup.c
index 52228b42a1..71fc6b33da 100644
--- a/setup.c
+++ b/setup.c
@@ -31,9 +31,6 @@ enum allowed_bare_repo {
ALLOWED_BARE_REPO_ALL,
};
-/* This is set by setup_git_directory_gently() and/or git_default_config() */
-static char *git_work_tree_cfg;
-
static struct startup_info the_startup_info;
struct startup_info *startup_info = &the_startup_info;
const char *tmp_original_cwd;
@@ -799,13 +796,10 @@ static int check_repository_format_gently(const char *gitdir,
}
if (!has_common) {
- if (candidate->is_bare != -1) {
+ if (candidate->is_bare != -1)
is_bare_repository_cfg = candidate->is_bare;
- }
- if (candidate->work_tree) {
- free(git_work_tree_cfg);
- git_work_tree_cfg = xstrdup(candidate->work_tree);
- }
+ } else {
+ FREE_AND_NULL(candidate->work_tree);
}
return 0;
@@ -1145,7 +1139,7 @@ static const char *setup_explicit_git_dir(struct repository *repo,
if (work_tree_env)
set_git_work_tree(repo, work_tree_env);
else if (is_bare_repository_cfg > 0) {
- if (git_work_tree_cfg) {
+ if (repo_fmt->work_tree) {
/* #22.2, #30 */
warning("core.bare and core.worktree do not make sense");
repo->worktree_config_is_bogus = true;
@@ -1156,15 +1150,15 @@ static const char *setup_explicit_git_dir(struct repository *repo,
free(gitfile);
return NULL;
}
- else if (git_work_tree_cfg) { /* #6, #14 */
- if (is_absolute_path(git_work_tree_cfg))
- set_git_work_tree(repo, git_work_tree_cfg);
+ else if (repo_fmt->work_tree) { /* #6, #14 */
+ if (is_absolute_path(repo_fmt->work_tree))
+ set_git_work_tree(repo, repo_fmt->work_tree);
else {
char *core_worktree;
if (chdir(gitdirenv))
die_errno(_("cannot chdir to '%s'"), gitdirenv);
- if (chdir(git_work_tree_cfg))
- die_errno(_("cannot chdir to '%s'"), git_work_tree_cfg);
+ if (chdir(repo_fmt->work_tree))
+ die_errno(_("cannot chdir to '%s'"), repo_fmt->work_tree);
core_worktree = xgetcwd();
if (chdir(cwd->buf))
die_errno(_("cannot come back to cwd"));
@@ -1217,7 +1211,7 @@ static const char *setup_discovered_git_dir(struct repository *repo,
return NULL;
/* --work-tree is set without --git-dir; use discovered one */
- if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
+ if (getenv(GIT_WORK_TREE_ENVIRONMENT) || repo_fmt->work_tree) {
char *to_free = NULL;
const char *ret;
@@ -1267,7 +1261,7 @@ static const char *setup_bare_git_dir(struct repository *repo,
setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1);
/* --work-tree is set without --git-dir; use discovered one */
- if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
+ if (getenv(GIT_WORK_TREE_ENVIRONMENT) || repo_fmt->work_tree) {
static const char *gitdir;
gitdir = offset == cwd->len ? "." : xmemdupz(cwd->buf, offset);
--
2.54.0.1189.g8c84645362.dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 4/7] builtin/init: stop modifying `is_bare_repository_cfg`
2026-06-10 6:56 [PATCH 0/7] setup: drop global state Patrick Steinhardt
` (2 preceding siblings ...)
2026-06-10 6:56 ` [PATCH 3/7] setup: remove global `git_work_tree_cfg` variable Patrick Steinhardt
@ 2026-06-10 6:56 ` Patrick Steinhardt
2026-06-10 6:56 ` [PATCH 5/7] environment: split up concerns of `is_bare_repository_cfg` Patrick Steinhardt
` (2 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Patrick Steinhardt @ 2026-06-10 6:56 UTC (permalink / raw)
To: git
We're modifying `is_bare_repository_cfg` in "builtin/init.c" to indicate
whether the newly created repository is supposed to be a bare repository
or not.
This is ultimately unnecessary though: when initializing the repository
in `init_db()` we eventually set `is_bare_repository_cfg = !work_tree`,
so all that matters is whether or not we have a working tree configured,
and the working tree is set up in the non-bare in "builtin/init.c".
Stop modifying the global variable in "builtin/init.c" in favor of a
local variable.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/init-db.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/builtin/init-db.c b/builtin/init-db.c
index b4343c2804..52aa92fb0a 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -81,6 +81,7 @@ int cmd_init_db(int argc,
const char *template_dir = NULL;
char *template_dir_to_free = NULL;
unsigned int flags = 0;
+ int bare = is_bare_repository_cfg;
const char *object_format = NULL;
const char *ref_format = NULL;
const char *initial_branch = NULL;
@@ -90,7 +91,7 @@ int cmd_init_db(int argc,
const struct option init_db_options[] = {
OPT_STRING(0, "template", &template_dir, N_("template-directory"),
N_("directory from which templates will be used")),
- OPT_SET_INT(0, "bare", &is_bare_repository_cfg,
+ OPT_SET_INT(0, "bare", &bare,
N_("create a bare repository"), 1),
{
.type = OPTION_CALLBACK,
@@ -116,7 +117,7 @@ int cmd_init_db(int argc,
argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
- if (real_git_dir && is_bare_repository_cfg == 1)
+ if (real_git_dir && bare == 1)
die(_("options '%s' and '%s' cannot be used together"), "--separate-git-dir", "--bare");
if (real_git_dir && !is_absolute_path(real_git_dir))
@@ -160,7 +161,7 @@ int cmd_init_db(int argc,
} else if (0 < argc) {
usage(init_db_usage[0]);
}
- if (is_bare_repository_cfg == 1) {
+ if (bare == 1) {
char *cwd = xgetcwd();
setenv(GIT_DIR_ENVIRONMENT, cwd, argc > 0);
free(cwd);
@@ -187,7 +188,7 @@ int cmd_init_db(int argc,
*/
git_dir = xstrdup_or_null(getenv(GIT_DIR_ENVIRONMENT));
work_tree = xstrdup_or_null(getenv(GIT_WORK_TREE_ENVIRONMENT));
- if ((!git_dir || is_bare_repository_cfg == 1) && work_tree)
+ if ((!git_dir || bare == 1) && work_tree)
die(_("%s (or --work-tree=<directory>) not allowed without "
"specifying %s (or --git-dir=<directory>)"),
GIT_WORK_TREE_ENVIRONMENT,
@@ -224,10 +225,10 @@ int cmd_init_db(int argc,
strbuf_release(&sb);
}
- if (is_bare_repository_cfg < 0)
- is_bare_repository_cfg = guess_repository_type(git_dir);
+ if (bare < 0)
+ bare = guess_repository_type(git_dir);
- if (!is_bare_repository_cfg) {
+ if (!bare) {
const char *git_dir_parent = strrchr(git_dir, '/');
if (work_tree) {
--
2.54.0.1189.g8c84645362.dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 5/7] environment: split up concerns of `is_bare_repository_cfg`
2026-06-10 6:56 [PATCH 0/7] setup: drop global state Patrick Steinhardt
` (3 preceding siblings ...)
2026-06-10 6:56 ` [PATCH 4/7] builtin/init: stop modifying `is_bare_repository_cfg` Patrick Steinhardt
@ 2026-06-10 6:56 ` Patrick Steinhardt
2026-06-10 22:22 ` Justin Tobler
2026-06-10 6:56 ` [PATCH 6/7] environment: stop using `the_repository` in `is_bare_repository()` Patrick Steinhardt
2026-06-10 6:56 ` [PATCH 7/7] treewide: drop USE_THE_REPOSITORY_VARIABLE Patrick Steinhardt
6 siblings, 1 reply; 13+ messages in thread
From: Patrick Steinhardt @ 2026-06-10 6:56 UTC (permalink / raw)
To: git
The `is_bare_repository_cfg` variable tracks two different pieces of
information:
- It tracks whether the user has invoked git with the "--bare" flag,
which makes us treat any discovered Git repository as if it was a
bare repository.
- Otherwise it tracks whether the discovered `the_repository` is bare.
This makes the flag extremely confusing and creates a bit of a challenge
when handling multiple repositories in the same process.
Split up the concerns of this variable into two pieces:
- `startup_info.force_bare_repository` tracks whether the user has
passed the "--bare" flag. This is used as a hint to treat newly set
up repositories as bare regardless of whether or not they have a
worktree.
- `struct repository::bare_cfg` tracks whether or not a repository is
considered bare. This takes into account both whether the user has
passed "--bare" and the discovered state of the repository itself.
Whether or not a repository is bare is now resolved when checking the
repository's format, and is then later applied to the repository itself
via `apply_repository_format()`.
This enables a subsequent change where we make `is_bare_repository()`
not depend on global state anymore.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/init-db.c | 2 +-
environment.c | 5 ++---
environment.h | 1 -
git.c | 2 +-
repository.c | 1 +
repository.h | 7 +++++++
setup.c | 21 ++++++++++++++-------
setup.h | 6 ++++++
worktree.c | 2 +-
9 files changed, 33 insertions(+), 14 deletions(-)
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 52aa92fb0a..566732c9f4 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -81,7 +81,7 @@ int cmd_init_db(int argc,
const char *template_dir = NULL;
char *template_dir_to_free = NULL;
unsigned int flags = 0;
- int bare = is_bare_repository_cfg;
+ int bare = startup_info->force_bare_repository ? 1 : -1;
const char *object_format = NULL;
const char *ref_format = NULL;
const char *initial_branch = NULL;
diff --git a/environment.c b/environment.c
index 4e86335f25..9d7c908c55 100644
--- a/environment.c
+++ b/environment.c
@@ -48,7 +48,6 @@ int has_symlinks = 1;
int minimum_abbrev = 4, default_abbrev = -1;
int ignore_case;
int assume_unchanged;
-int is_bare_repository_cfg = -1; /* unspecified */
int warn_on_object_refname_ambiguity = 1;
char *git_commit_encoding;
char *git_log_output_encoding;
@@ -136,7 +135,7 @@ const char *getenv_safe(struct strvec *argv, const char *name)
int is_bare_repository(void)
{
/* if core.bare is not 'false', let's see if there is a work tree */
- return is_bare_repository_cfg && !repo_get_work_tree(the_repository);
+ return the_repository->bare_cfg && !repo_get_work_tree(the_repository);
}
int have_git_dir(void)
@@ -342,7 +341,7 @@ int git_default_core_config(const char *var, const char *value,
}
if (!strcmp(var, "core.bare")) {
- is_bare_repository_cfg = git_config_bool(var, value);
+ the_repository->bare_cfg = git_config_bool(var, value);
return 0;
}
diff --git a/environment.h b/environment.h
index 5d6e4e6c1b..afb5bcf197 100644
--- a/environment.h
+++ b/environment.h
@@ -147,7 +147,6 @@ void repo_config_values_init(struct repo_config_values *cfg);
*/
int have_git_dir(void);
-extern int is_bare_repository_cfg;
int is_bare_repository(void);
/* Environment bits from configuration mechanism */
diff --git a/git.c b/git.c
index 36f08891ef..387eabe38c 100644
--- a/git.c
+++ b/git.c
@@ -255,7 +255,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
*envchanged = 1;
} else if (!strcmp(cmd, "--bare")) {
char *cwd = xgetcwd();
- is_bare_repository_cfg = 1;
+ startup_info->force_bare_repository = true;
setenv(GIT_DIR_ENVIRONMENT, cwd, 0);
free(cwd);
setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1);
diff --git a/repository.c b/repository.c
index 187dd471c4..c1e91eb0da 100644
--- a/repository.c
+++ b/repository.c
@@ -73,6 +73,7 @@ void initialize_repository(struct repository *repo)
ALLOC_ARRAY(repo->index, 1);
index_state_init(repo->index, repo);
repo->check_deprecated_config = true;
+ repo->bare_cfg = -1;
repo_config_values_init(&repo->config_values_private_);
/*
diff --git a/repository.h b/repository.h
index 36e2db2633..7d649e32e7 100644
--- a/repository.h
+++ b/repository.h
@@ -117,6 +117,13 @@ struct repository {
bool worktree_initialized;
bool worktree_config_is_bogus;
+ /*
+ * Whether the repository is bare, as set by "core.bare" config or
+ * inferred during repository discovery. -1 means unset/unknown, 0
+ * means non-bare, 1 means bare.
+ */
+ int bare_cfg;
+
/*
* Path from the root of the top-level superproject down to this
* repository. This is only non-NULL if the repository is initialized
diff --git a/setup.c b/setup.c
index 71fc6b33da..2b690da8ca 100644
--- a/setup.c
+++ b/setup.c
@@ -795,10 +795,16 @@ static int check_repository_format_gently(const char *gitdir,
has_common = 0;
}
- if (!has_common) {
- if (candidate->is_bare != -1)
- is_bare_repository_cfg = candidate->is_bare;
- } else {
+ if (startup_info->force_bare_repository) {
+ candidate->is_bare = 1;
+ FREE_AND_NULL(candidate->work_tree);
+ } else if (has_common) {
+ /*
+ * When sharing a common dir with another repository (e.g. a
+ * linked worktree), do not let this repository's config
+ * dictate bareness; it is inherited from the main worktree.
+ */
+ candidate->is_bare = -1;
FREE_AND_NULL(candidate->work_tree);
}
@@ -1138,7 +1144,7 @@ static const char *setup_explicit_git_dir(struct repository *repo,
/* #3, #7, #11, #15, #19, #23, #27, #31 (see t1510) */
if (work_tree_env)
set_git_work_tree(repo, work_tree_env);
- else if (is_bare_repository_cfg > 0) {
+ else if (repo_fmt->is_bare > 0) {
if (repo_fmt->work_tree) {
/* #22.2, #30 */
warning("core.bare and core.worktree do not make sense");
@@ -1225,7 +1231,7 @@ static const char *setup_discovered_git_dir(struct repository *repo,
}
/* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */
- if (is_bare_repository_cfg > 0) {
+ if (repo_fmt->is_bare > 0) {
set_git_dir(repo, gitdir, (offset != cwd->len));
if (chdir(cwd->buf))
die_errno(_("cannot come back to cwd"));
@@ -1762,6 +1768,7 @@ int apply_repository_format(struct repository *repo,
alternate_object_directories = xstrdup_or_null(getenv(ALTERNATE_DB_ENVIRONMENT));
}
+ repo->bare_cfg = format->is_bare;
repo_set_hash_algo(repo, format->hash_algo);
repo->objects = odb_new(repo, object_directory,
alternate_object_directories);
@@ -2571,7 +2578,7 @@ static int create_default_files(struct repository *repo,
repo_settings_set_shared_repository(repo,
init_shared_repository);
- is_bare_repository_cfg = !work_tree;
+ repo->bare_cfg = !work_tree;
/*
* We would have created the above under user's umask -- under
diff --git a/setup.h b/setup.h
index 705d1d6ff7..b9fd96bea6 100644
--- a/setup.h
+++ b/setup.h
@@ -292,6 +292,12 @@ enum sharedrepo {
int git_config_perm(const char *var, const char *value);
struct startup_info {
+ /*
+ * Whether the user is asking us to treat the repository as bare via
+ * `git --bare`, even if it's not.
+ */
+ bool force_bare_repository;
+
int have_repository;
const char *prefix;
const char *original_cwd;
diff --git a/worktree.c b/worktree.c
index 97eddc3916..7d70f2c1da 100644
--- a/worktree.c
+++ b/worktree.c
@@ -123,7 +123,7 @@ static struct worktree *get_main_worktree(int skip_reading_head)
worktree->repo = the_repository;
worktree->path = strbuf_detach(&worktree_path, NULL);
worktree->is_current = is_current_worktree(worktree);
- worktree->is_bare = (is_bare_repository_cfg == 1) ||
+ worktree->is_bare = (the_repository->bare_cfg == 1) ||
is_bare_repository() ||
/*
* When in a secondary worktree we have to also verify if the main
--
2.54.0.1189.g8c84645362.dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 6/7] environment: stop using `the_repository` in `is_bare_repository()`
2026-06-10 6:56 [PATCH 0/7] setup: drop global state Patrick Steinhardt
` (4 preceding siblings ...)
2026-06-10 6:56 ` [PATCH 5/7] environment: split up concerns of `is_bare_repository_cfg` Patrick Steinhardt
@ 2026-06-10 6:56 ` Patrick Steinhardt
2026-06-10 6:56 ` [PATCH 7/7] treewide: drop USE_THE_REPOSITORY_VARIABLE Patrick Steinhardt
6 siblings, 0 replies; 13+ messages in thread
From: Patrick Steinhardt @ 2026-06-10 6:56 UTC (permalink / raw)
To: git
Refactor `is_bare_repository()` to take in a repository parameter so
that we no longer depend on `the_repository`. Adjust callers
accordingly.
Furthermore, move the function outside of the declarations that are only
available when `USE_THE_REPOSITORY_VARIABLE` is set, as it no longer
depends on that variable.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
attr.c | 4 ++--
builtin/bisect.c | 2 +-
builtin/blame.c | 2 +-
builtin/check-attr.c | 2 +-
builtin/fetch.c | 2 +-
builtin/gc.c | 2 +-
builtin/history.c | 2 +-
builtin/repack.c | 2 +-
builtin/repo.c | 2 +-
builtin/reset.c | 2 +-
builtin/rev-parse.c | 2 +-
environment.c | 4 ++--
environment.h | 4 ++--
mailmap.c | 4 ++--
refs/files-backend.c | 2 +-
refs/reftable-backend.c | 2 +-
setup.c | 2 +-
transport.c | 4 ++--
worktree.c | 2 +-
19 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/attr.c b/attr.c
index 75369547b3..04cb284954 100644
--- a/attr.c
+++ b/attr.c
@@ -681,7 +681,7 @@ static enum git_attr_direction direction;
void git_attr_set_direction(enum git_attr_direction new_direction)
{
- if (is_bare_repository() && new_direction != GIT_ATTR_INDEX)
+ if (is_bare_repository(the_repository) && new_direction != GIT_ATTR_INDEX)
BUG("non-INDEX attr direction in a bare repo");
if (new_direction != direction)
@@ -848,7 +848,7 @@ static struct attr_stack *read_attr(struct index_state *istate,
res = read_attr_from_index(istate, path, flags);
} else if (tree_oid) {
res = read_attr_from_blob(istate, tree_oid, path, flags);
- } else if (!is_bare_repository()) {
+ } else if (!is_bare_repository(the_repository)) {
if (direction == GIT_ATTR_CHECKOUT) {
res = read_attr_from_index(istate, path, flags);
if (!res)
diff --git a/builtin/bisect.c b/builtin/bisect.c
index e7c2d2f3bb..798e28f501 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -724,7 +724,7 @@ static enum bisect_error bisect_start(struct bisect_terms *terms, int argc,
struct object_id oid;
const char *head;
- if (is_bare_repository())
+ if (is_bare_repository(the_repository))
no_checkout = 1;
/*
diff --git a/builtin/blame.c b/builtin/blame.c
index ffbd3ce5c5..553f4cb780 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -1163,7 +1163,7 @@ int cmd_blame(int argc,
revs.disable_stdin = 1;
setup_revisions(argc, argv, &revs, NULL);
- if (!revs.pending.nr && is_bare_repository()) {
+ if (!revs.pending.nr && is_bare_repository(the_repository)) {
struct commit *head_commit;
struct object_id head_oid;
diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index 98f64d5b92..217d83ea7d 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -116,7 +116,7 @@ int cmd_check_attr(int argc,
struct object_id initialized_oid;
int cnt, i, doubledash, filei;
- if (!is_bare_repository())
+ if (!is_bare_repository(the_repository))
setup_work_tree(the_repository);
repo_config(the_repository, git_default_config, NULL);
diff --git a/builtin/fetch.c b/builtin/fetch.c
index c1d7c672f4..44b8c70da1 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -1764,7 +1764,7 @@ static int set_head(const struct ref *remote_refs, struct remote *remote)
if (!head_name)
goto cleanup;
- baremirror = is_bare_repository() && remote->mirror;
+ baremirror = is_bare_repository(the_repository) && remote->mirror;
create_only = follow_remote_head == FOLLOW_REMOTE_ALWAYS ? 0 : !baremirror;
if (baremirror) {
strbuf_addstr(&b_head, "HEAD");
diff --git a/builtin/gc.c b/builtin/gc.c
index 84a66d3240..61da30de9f 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -902,7 +902,7 @@ int cmd_gc(int argc,
die(_("failed to parse gc.logExpiry value %s"), cfg.gc_log_expire);
if (cfg.pack_refs < 0)
- cfg.pack_refs = !is_bare_repository();
+ cfg.pack_refs = !is_bare_repository(the_repository);
argc = parse_options(argc, argv, prefix, builtin_gc_options,
builtin_gc_usage, 0);
diff --git a/builtin/history.c b/builtin/history.c
index 091465a59e..fd83de8265 100644
--- a/builtin/history.c
+++ b/builtin/history.c
@@ -525,7 +525,7 @@ static int cmd_history_fixup(int argc,
if (action == REF_ACTION_DEFAULT)
action = REF_ACTION_BRANCHES;
- if (is_bare_repository()) {
+ if (is_bare_repository(repo)) {
ret = error(_("cannot run fixup in a bare repository"));
goto out;
}
diff --git a/builtin/repack.c b/builtin/repack.c
index 1524a9c13a..bbc6f51639 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -265,7 +265,7 @@ int cmd_repack(int argc,
if (write_bitmaps < 0) {
if (write_midx == REPACK_WRITE_MIDX_NONE &&
- (!(pack_everything & ALL_INTO_ONE) || !is_bare_repository()))
+ (!(pack_everything & ALL_INTO_ONE) || !is_bare_repository(the_repository)))
write_bitmaps = 0;
}
if (po_args.pack_kept_objects < 0)
diff --git a/builtin/repo.c b/builtin/repo.c
index 71a5c1c29c..34e96514bc 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -58,7 +58,7 @@ struct repo_info_field {
static int get_layout_bare(struct repository *repo UNUSED, struct strbuf *buf)
{
- strbuf_addstr(buf, is_bare_repository() ? "true" : "false");
+ strbuf_addstr(buf, is_bare_repository(the_repository) ? "true" : "false");
return 0;
}
diff --git a/builtin/reset.c b/builtin/reset.c
index 3be6bd0121..78e69bd84b 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -470,7 +470,7 @@ int cmd_reset(int argc,
if (reset_type != SOFT && (reset_type != MIXED || repo_get_work_tree(the_repository)))
setup_work_tree(the_repository);
- if (reset_type == MIXED && is_bare_repository())
+ if (reset_type == MIXED && is_bare_repository(the_repository))
die(_("%s reset is not allowed in a bare repository"),
_(reset_type_names[reset_type]));
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index bb882678fe..090e5cfbb0 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -1084,7 +1084,7 @@ int cmd_rev_parse(int argc,
continue;
}
if (!strcmp(arg, "--is-bare-repository")) {
- printf("%s\n", is_bare_repository() ? "true"
+ printf("%s\n", is_bare_repository(the_repository) ? "true"
: "false");
continue;
}
diff --git a/environment.c b/environment.c
index 9d7c908c55..bf20953415 100644
--- a/environment.c
+++ b/environment.c
@@ -132,10 +132,10 @@ const char *getenv_safe(struct strvec *argv, const char *name)
return argv->v[argv->nr - 1];
}
-int is_bare_repository(void)
+int is_bare_repository(struct repository *repo)
{
/* if core.bare is not 'false', let's see if there is a work tree */
- return the_repository->bare_cfg && !repo_get_work_tree(the_repository);
+ return repo->bare_cfg && !repo_get_work_tree(repo);
}
int have_git_dir(void)
diff --git a/environment.h b/environment.h
index afb5bcf197..164a55df2c 100644
--- a/environment.h
+++ b/environment.h
@@ -125,6 +125,8 @@ int git_default_core_config(const char *var, const char *value,
void repo_config_values_init(struct repo_config_values *cfg);
+int is_bare_repository(struct repository *repo);
+
/*
* TODO: All the below state either explicitly or implicitly relies on
* `the_repository`. We should eventually get rid of these and make the
@@ -147,8 +149,6 @@ void repo_config_values_init(struct repo_config_values *cfg);
*/
int have_git_dir(void);
-int is_bare_repository(void);
-
/* Environment bits from configuration mechanism */
extern int trust_executable_bit;
extern int trust_ctime;
diff --git a/mailmap.c b/mailmap.c
index 3b2691781d..7d8590cdd6 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -219,10 +219,10 @@ int read_mailmap(struct repository *repo, struct string_list *map)
map->strdup_strings = 1;
map->cmp = namemap_cmp;
- if (!mailmap_blob && is_bare_repository())
+ if (!mailmap_blob && is_bare_repository(the_repository))
mailmap_blob = xstrdup("HEAD:.mailmap");
- if (!startup_info->have_repository || !is_bare_repository())
+ if (!startup_info->have_repository || !is_bare_repository(the_repository))
err |= read_mailmap_file(map, ".mailmap",
startup_info->have_repository ?
MAILMAP_NOFOLLOW : 0);
diff --git a/refs/files-backend.c b/refs/files-backend.c
index a4c7858787..2b27091484 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1865,7 +1865,7 @@ static int log_ref_setup(struct files_ref_store *refs,
char *logfile;
if (log_refs_cfg == LOG_REFS_UNSET)
- log_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;
+ log_refs_cfg = is_bare_repository(the_repository) ? LOG_REFS_NONE : LOG_REFS_NORMAL;
files_reflog_path(refs, &logfile_sb, refname);
logfile = strbuf_detach(&logfile_sb, NULL);
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index 4ae22922de..101ef29ac8 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -288,7 +288,7 @@ static int should_write_log(struct reftable_ref_store *refs, const char *refname
{
enum log_refs_config log_refs_cfg = refs->log_all_ref_updates;
if (log_refs_cfg == LOG_REFS_UNSET)
- log_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;
+ log_refs_cfg = is_bare_repository(the_repository) ? LOG_REFS_NONE : LOG_REFS_NORMAL;
switch (log_refs_cfg) {
case LOG_REFS_NONE:
diff --git a/setup.c b/setup.c
index 2b690da8ca..6b95bf546d 100644
--- a/setup.c
+++ b/setup.c
@@ -2604,7 +2604,7 @@ static int create_default_files(struct repository *repo,
}
repo_config_set(repo, "core.filemode", filemode ? "true" : "false");
- if (is_bare_repository())
+ if (is_bare_repository(the_repository))
repo_config_set(repo, "core.bare", "true");
else {
repo_config_set(repo, "core.bare", "false");
diff --git a/transport.c b/transport.c
index 0f5ec30247..fc144f0aed 100644
--- a/transport.c
+++ b/transport.c
@@ -1482,7 +1482,7 @@ int transport_push(struct repository *r,
if ((flags & (TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND |
TRANSPORT_RECURSE_SUBMODULES_ONLY)) &&
- !is_bare_repository()) {
+ !is_bare_repository(the_repository)) {
struct ref *ref = remote_refs;
struct oid_array commits = OID_ARRAY_INIT;
@@ -1509,7 +1509,7 @@ int transport_push(struct repository *r,
if (((flags & TRANSPORT_RECURSE_SUBMODULES_CHECK) ||
((flags & (TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND |
TRANSPORT_RECURSE_SUBMODULES_ONLY)) &&
- !pretend)) && !is_bare_repository()) {
+ !pretend)) && !is_bare_repository(the_repository)) {
struct ref *ref = remote_refs;
struct string_list needs_pushing = STRING_LIST_INIT_DUP;
struct oid_array commits = OID_ARRAY_INIT;
diff --git a/worktree.c b/worktree.c
index 7d70f2c1da..30125827fd 100644
--- a/worktree.c
+++ b/worktree.c
@@ -124,7 +124,7 @@ static struct worktree *get_main_worktree(int skip_reading_head)
worktree->path = strbuf_detach(&worktree_path, NULL);
worktree->is_current = is_current_worktree(worktree);
worktree->is_bare = (the_repository->bare_cfg == 1) ||
- is_bare_repository() ||
+ is_bare_repository(the_repository) ||
/*
* When in a secondary worktree we have to also verify if the main
* worktree is bare in $commondir/config.worktree.
--
2.54.0.1189.g8c84645362.dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 7/7] treewide: drop USE_THE_REPOSITORY_VARIABLE
2026-06-10 6:56 [PATCH 0/7] setup: drop global state Patrick Steinhardt
` (5 preceding siblings ...)
2026-06-10 6:56 ` [PATCH 6/7] environment: stop using `the_repository` in `is_bare_repository()` Patrick Steinhardt
@ 2026-06-10 6:56 ` Patrick Steinhardt
2026-06-10 22:26 ` Justin Tobler
6 siblings, 1 reply; 13+ messages in thread
From: Patrick Steinhardt @ 2026-06-10 6:56 UTC (permalink / raw)
To: git
Adapt a couple of trivial callers of `is_bare_repository()` to instead
use a repository available via the caller's context so that we can drop
the `USE_THE_REPOSITORY_VARIABLE` macro.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/repack.c | 3 +--
mailmap.c | 6 ++----
refs/reftable-backend.c | 4 +---
setup.c | 3 +--
4 files changed, 5 insertions(+), 11 deletions(-)
diff --git a/builtin/repack.c b/builtin/repack.c
index bbc6f51639..d0465fb4f5 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -1,4 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
#define DISABLE_SIGN_COMPARE_WARNINGS
#include "builtin.h"
@@ -265,7 +264,7 @@ int cmd_repack(int argc,
if (write_bitmaps < 0) {
if (write_midx == REPACK_WRITE_MIDX_NONE &&
- (!(pack_everything & ALL_INTO_ONE) || !is_bare_repository(the_repository)))
+ (!(pack_everything & ALL_INTO_ONE) || !is_bare_repository(repo)))
write_bitmaps = 0;
}
if (po_args.pack_kept_objects < 0)
diff --git a/mailmap.c b/mailmap.c
index 7d8590cdd6..2d5514f833 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -1,5 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
-
#include "git-compat-util.h"
#include "environment.h"
#include "string-list.h"
@@ -219,10 +217,10 @@ int read_mailmap(struct repository *repo, struct string_list *map)
map->strdup_strings = 1;
map->cmp = namemap_cmp;
- if (!mailmap_blob && is_bare_repository(the_repository))
+ if (!mailmap_blob && is_bare_repository(repo))
mailmap_blob = xstrdup("HEAD:.mailmap");
- if (!startup_info->have_repository || !is_bare_repository(the_repository))
+ if (!startup_info->have_repository || !is_bare_repository(repo))
err |= read_mailmap_file(map, ".mailmap",
startup_info->have_repository ?
MAILMAP_NOFOLLOW : 0);
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index 101ef29ac8..c151d331e7 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -1,5 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
-
#include "../git-compat-util.h"
#include "../abspath.h"
#include "../chdir-notify.h"
@@ -288,7 +286,7 @@ static int should_write_log(struct reftable_ref_store *refs, const char *refname
{
enum log_refs_config log_refs_cfg = refs->log_all_ref_updates;
if (log_refs_cfg == LOG_REFS_UNSET)
- log_refs_cfg = is_bare_repository(the_repository) ? LOG_REFS_NONE : LOG_REFS_NORMAL;
+ log_refs_cfg = is_bare_repository(refs->base.repo) ? LOG_REFS_NONE : LOG_REFS_NORMAL;
switch (log_refs_cfg) {
case LOG_REFS_NONE:
diff --git a/setup.c b/setup.c
index 6b95bf546d..f24a805658 100644
--- a/setup.c
+++ b/setup.c
@@ -1,4 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
#define DISABLE_SIGN_COMPARE_WARNINGS
#include "git-compat-util.h"
@@ -2604,7 +2603,7 @@ static int create_default_files(struct repository *repo,
}
repo_config_set(repo, "core.filemode", filemode ? "true" : "false");
- if (is_bare_repository(the_repository))
+ if (is_bare_repository(repo))
repo_config_set(repo, "core.bare", "true");
else {
repo_config_set(repo, "core.bare", "false");
--
2.54.0.1189.g8c84645362.dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 1/7] builtin/init: stop modifying global `git_work_tree_cfg` variable
2026-06-10 6:56 ` [PATCH 1/7] builtin/init: stop modifying global `git_work_tree_cfg` variable Patrick Steinhardt
@ 2026-06-10 21:15 ` Justin Tobler
0 siblings, 0 replies; 13+ messages in thread
From: Justin Tobler @ 2026-06-10 21:15 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git
On 26/06/10 08:56AM, Patrick Steinhardt wrote:
> When executing git-init(1) we need to figure out the final location of
> the worktree. This location can be configured in a couple of ways: via
> an environment variable, via the preexisting "core.worktree" config in
> case we're reinitializing, or implicitly when reinitializing a non-bare
> repository.
>
> When checking for the worktree location in "builtin/init-db.c" we
> populate any potentially-discovered value both by setting the global
> `git_work_tree_cfg` variable and via `set_git_work_tree()`, which
> ultimately ends up modifying `struct repository::worktree`.
Does `git_work_tree_cfg` have any bearing on the worktree value that
ends up in `struct repository`? Or is it just `set_git_work_tree()`?
> Modifying `git_work_tree_cfg` is unnecessary though: we configure the
> worktree in `create_default_files()`, and that function derives the
> worktree location via `repo_get_work_tree()`. Consequently, propagating
> the worktree via `set_git_work_tree()` is sufficient.
Ok, so IIUC there is really no reason to globally store the
`git_work_tree_cfg` value derived during `cmd_init_db()`. We only care
about the worktree written to `struct repository`.
> Stop munging `git_work_tree_cfg` and make it file-local to "setup.c" and
> function-local to `cmd_init_db()`.
Makes sense.
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
> builtin/init-db.c | 4 ++++
> environment.c | 3 ---
> environment.h | 1 -
> setup.c | 3 +++
> 4 files changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/builtin/init-db.c b/builtin/init-db.c
> index c55517ad94..01bc27904e 100644
> --- a/builtin/init-db.c
> +++ b/builtin/init-db.c
> @@ -229,6 +229,8 @@ int cmd_init_db(int argc,
>
> if (!is_bare_repository_cfg) {
> const char *git_dir_parent = strrchr(git_dir, '/');
> + char *git_work_tree_cfg = NULL;
We figure out the worktree locally and continue to set it via
`set_git_work_tree()` without updating a global worktree config value.
> +
> if (git_dir_parent) {
> char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
> git_work_tree_cfg = real_pathdup(rel, 1);
> @@ -243,6 +245,8 @@ int cmd_init_db(int argc,
> if (access(repo_get_work_tree(the_repository), X_OK))
> die_errno (_("Cannot access work tree '%s'"),
> repo_get_work_tree(the_repository));
> +
> + free(git_work_tree_cfg);
> }
> else {
> if (real_git_dir)
> diff --git a/environment.c b/environment.c
> index fc3ed8bb1c..4e86335f25 100644
> --- a/environment.c
> +++ b/environment.c
> @@ -100,9 +100,6 @@ int auto_comment_line_char;
> bool warn_on_auto_comment_char;
> #endif /* !WITH_BREAKING_CHANGES */
>
> -/* This is set by setup_git_directory_gently() and/or git_default_config() */
> -char *git_work_tree_cfg;
> -
> /*
> * Repository-local GIT_* environment variables; see environment.h for details.
> */
> diff --git a/environment.h b/environment.h
> index ccfcf37bfb..5d6e4e6c1b 100644
> --- a/environment.h
> +++ b/environment.h
> @@ -149,7 +149,6 @@ int have_git_dir(void);
>
> extern int is_bare_repository_cfg;
> int is_bare_repository(void);
> -extern char *git_work_tree_cfg;
>
> /* Environment bits from configuration mechanism */
> extern int trust_executable_bit;
> diff --git a/setup.c b/setup.c
> index b4652651df..52228b42a1 100644
> --- a/setup.c
> +++ b/setup.c
> @@ -31,6 +31,9 @@ enum allowed_bare_repo {
> ALLOWED_BARE_REPO_ALL,
> };
>
> +/* This is set by setup_git_directory_gently() and/or git_default_config() */
> +static char *git_work_tree_cfg;
Ok, now `git_work_tree_cfg` is only referenced from "setup.c".
-Justin
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/7] builtin/init: simplify logic to configure worktree
2026-06-10 6:56 ` [PATCH 2/7] builtin/init: simplify logic to configure worktree Patrick Steinhardt
@ 2026-06-10 21:29 ` Justin Tobler
0 siblings, 0 replies; 13+ messages in thread
From: Justin Tobler @ 2026-06-10 21:29 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git
On 26/06/10 08:56AM, Patrick Steinhardt wrote:
> In the preceding commit we have stopped modifying the global
> `git_work_tree_cfg` variable. With this change there's now some code
> paths where we end up setting the local `git_work_tree_cfg` variable,
> but without actually using the value for anything.
>
> Refactor the code a bit so that we only set the worktree configuration
> in case it's actually needed. Furthermore, reflow it a bit to make the
> code easier to follow.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
> builtin/init-db.c | 31 ++++++++++++++++++-------------
> 1 file changed, 18 insertions(+), 13 deletions(-)
>
> diff --git a/builtin/init-db.c b/builtin/init-db.c
> index 01bc27904e..b4343c2804 100644
> --- a/builtin/init-db.c
> +++ b/builtin/init-db.c
> @@ -229,24 +229,29 @@ int cmd_init_db(int argc,
>
> if (!is_bare_repository_cfg) {
> const char *git_dir_parent = strrchr(git_dir, '/');
> - char *git_work_tree_cfg = NULL;
>
> - if (git_dir_parent) {
> - char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
> - git_work_tree_cfg = real_pathdup(rel, 1);
> - free(rel);
> - }
> - if (!git_work_tree_cfg)
> - git_work_tree_cfg = xgetcwd();
> - if (work_tree)
> + if (work_tree) {
> set_git_work_tree(the_repository, work_tree);
Ok, if the worktree is already set via the GIT_WORK_TREE environment
variable, we can just apply it skip everything else.
> - else
> - set_git_work_tree(the_repository, git_work_tree_cfg);
> + } else {
> + char *work_tree_cfg = NULL;
> +
> + if (git_dir_parent) {
> + char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
> + work_tree_cfg = real_pathdup(rel, 1);
> + free(rel);
> + }
> +
> + if (!work_tree_cfg)
> + work_tree_cfg = xgetcwd();
When the environment variable is not set, we try to derive the worktree
from the parent directory of the gitdir. If that doesn't work we
fallback to the current working directory.
This matches previous the previous behavior.
> +
> + set_git_work_tree(the_repository, work_tree_cfg);
> +
> + free(work_tree_cfg);
> + }
Good cleanup. I think this is a bit easier to read too.
-Justin
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/7] setup: remove global `git_work_tree_cfg` variable
2026-06-10 6:56 ` [PATCH 3/7] setup: remove global `git_work_tree_cfg` variable Patrick Steinhardt
@ 2026-06-10 21:52 ` Justin Tobler
0 siblings, 0 replies; 13+ messages in thread
From: Justin Tobler @ 2026-06-10 21:52 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git
On 26/06/10 08:56AM, Patrick Steinhardt wrote:
> The global `git_work_tree_cfg` variable used to be modified by both
> "setup.c" and by "builtin/init-db.c". We have refactored the latter user
> to not use that variable at all anymore in a preceding commit, which
> makes "setup.c" the only remaining user.
>
> Even for "setup.c" it is unnecessary though, as we only ever set it to
> the value we have stored in the discovered repository format. The
> consequence is that we only ever set it in case we already have it set
> to the same value in our discovered repository format, which makes it
> redundant.
Nice. I was wondering in the first patch if there would really be any
need to keep `git_work_tree_cfg` around here at all. Makes sense to me
to just set the repository worktree directly.
> Refactor the code so that we instead use the worktree configuration as
> discovered via the repository format. Drop the global variable.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
> setup.c | 28 +++++++++++-----------------
> 1 file changed, 11 insertions(+), 17 deletions(-)
>
> diff --git a/setup.c b/setup.c
> index 52228b42a1..71fc6b33da 100644
> --- a/setup.c
> +++ b/setup.c
> @@ -31,9 +31,6 @@ enum allowed_bare_repo {
> ALLOWED_BARE_REPO_ALL,
> };
>
> -/* This is set by setup_git_directory_gently() and/or git_default_config() */
> -static char *git_work_tree_cfg;
> -
> static struct startup_info the_startup_info;
> struct startup_info *startup_info = &the_startup_info;
> const char *tmp_original_cwd;
> @@ -799,13 +796,10 @@ static int check_repository_format_gently(const char *gitdir,
> }
>
> if (!has_common) {
> - if (candidate->is_bare != -1) {
> + if (candidate->is_bare != -1)
> is_bare_repository_cfg = candidate->is_bare;
> - }
> - if (candidate->work_tree) {
> - free(git_work_tree_cfg);
> - git_work_tree_cfg = xstrdup(candidate->work_tree);
Ok, we no longer set `git_work_tree_cfg` in favor of just relying on the
worktree specified in the repository format.
> - }
> + } else {
> + FREE_AND_NULL(candidate->work_tree);
Huh, we were not previously freeing the worktree here, but I assume this
to avoid a resource leak?
The remainder of this patch replaces `git_work_tree_cfg` usage with the
repository format worktree and looks good.
-Justin
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 5/7] environment: split up concerns of `is_bare_repository_cfg`
2026-06-10 6:56 ` [PATCH 5/7] environment: split up concerns of `is_bare_repository_cfg` Patrick Steinhardt
@ 2026-06-10 22:22 ` Justin Tobler
0 siblings, 0 replies; 13+ messages in thread
From: Justin Tobler @ 2026-06-10 22:22 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git
On 26/06/10 08:56AM, Patrick Steinhardt wrote:
> The `is_bare_repository_cfg` variable tracks two different pieces of
> information:
>
> - It tracks whether the user has invoked git with the "--bare" flag,
> which makes us treat any discovered Git repository as if it was a
> bare repository.
>
> - Otherwise it tracks whether the discovered `the_repository` is bare.
>
> This makes the flag extremely confusing and creates a bit of a challenge
> when handling multiple repositories in the same process.
Indeed, this does seem rather confusing.
> Split up the concerns of this variable into two pieces:
>
> - `startup_info.force_bare_repository` tracks whether the user has
> passed the "--bare" flag. This is used as a hint to treat newly set
> up repositories as bare regardless of whether or not they have a
> worktree.
>
> - `struct repository::bare_cfg` tracks whether or not a repository is
> considered bare. This takes into account both whether the user has
> passed "--bare" and the discovered state of the repository itself.
>
> Whether or not a repository is bare is now resolved when checking the
> repository's format, and is then later applied to the repository itself
> via `apply_repository_format()`.
Nice. These seem like they should be tracked separately, so splitting
them up sounds like a good idea.
> This enables a subsequent change where we make `is_bare_repository()`
> not depend on global state anymore.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
> builtin/init-db.c | 2 +-
> environment.c | 5 ++---
> environment.h | 1 -
> git.c | 2 +-
> repository.c | 1 +
> repository.h | 7 +++++++
> setup.c | 21 ++++++++++++++-------
> setup.h | 6 ++++++
> worktree.c | 2 +-
> 9 files changed, 33 insertions(+), 14 deletions(-)
>
> diff --git a/builtin/init-db.c b/builtin/init-db.c
> index 52aa92fb0a..566732c9f4 100644
> --- a/builtin/init-db.c
> +++ b/builtin/init-db.c
> @@ -81,7 +81,7 @@ int cmd_init_db(int argc,
> const char *template_dir = NULL;
> char *template_dir_to_free = NULL;
> unsigned int flags = 0;
> - int bare = is_bare_repository_cfg;
> + int bare = startup_info->force_bare_repository ? 1 : -1;
Any particular reason to continue mapping `force_bare_repository=false`
to -1? Or was this to just minimize changes?
> const char *object_format = NULL;
> const char *ref_format = NULL;
> const char *initial_branch = NULL;
[snip]
> diff --git a/repository.h b/repository.h
> index 36e2db2633..7d649e32e7 100644
> --- a/repository.h
> +++ b/repository.h
> @@ -117,6 +117,13 @@ struct repository {
> bool worktree_initialized;
> bool worktree_config_is_bogus;
>
> + /*
> + * Whether the repository is bare, as set by "core.bare" config or
> + * inferred during repository discovery. -1 means unset/unknown, 0
> + * means non-bare, 1 means bare.
> + */
> + int bare_cfg;
Now we track whether a repository is bare in `struct repository` and
removes the need to a separate global to track this state.
> +
> /*
> * Path from the root of the top-level superproject down to this
> * repository. This is only non-NULL if the repository is initialized
> diff --git a/setup.c b/setup.c
> index 71fc6b33da..2b690da8ca 100644
> --- a/setup.c
> +++ b/setup.c
> @@ -795,10 +795,16 @@ static int check_repository_format_gently(const char *gitdir,
> has_common = 0;
> }
>
> - if (!has_common) {
> - if (candidate->is_bare != -1)
> - is_bare_repository_cfg = candidate->is_bare;
> - } else {
> + if (startup_info->force_bare_repository) {
> + candidate->is_bare = 1;
> + FREE_AND_NULL(candidate->work_tree);
> + } else if (has_common) {
> + /*
> + * When sharing a common dir with another repository (e.g. a
> + * linked worktree), do not let this repository's config
> + * dictate bareness; it is inherited from the main worktree.
> + */
> + candidate->is_bare = -1;
> FREE_AND_NULL(candidate->work_tree);
Previously, when there was a common dir, `candidate->work_tree` was left
untouched, but now we are expclicitly setting it. I'm not sure I fully
understand this change.
-Justin
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 7/7] treewide: drop USE_THE_REPOSITORY_VARIABLE
2026-06-10 6:56 ` [PATCH 7/7] treewide: drop USE_THE_REPOSITORY_VARIABLE Patrick Steinhardt
@ 2026-06-10 22:26 ` Justin Tobler
0 siblings, 0 replies; 13+ messages in thread
From: Justin Tobler @ 2026-06-10 22:26 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git
On 26/06/10 08:56AM, Patrick Steinhardt wrote:
> Adapt a couple of trivial callers of `is_bare_repository()` to instead
> use a repository available via the caller's context so that we can drop
> the `USE_THE_REPOSITORY_VARIABLE` macro.
Nice cleanup, this patch looks trivially correct. :)
-Justin
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-06-10 22:26 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-10 6:56 [PATCH 0/7] setup: drop global state Patrick Steinhardt
2026-06-10 6:56 ` [PATCH 1/7] builtin/init: stop modifying global `git_work_tree_cfg` variable Patrick Steinhardt
2026-06-10 21:15 ` Justin Tobler
2026-06-10 6:56 ` [PATCH 2/7] builtin/init: simplify logic to configure worktree Patrick Steinhardt
2026-06-10 21:29 ` Justin Tobler
2026-06-10 6:56 ` [PATCH 3/7] setup: remove global `git_work_tree_cfg` variable Patrick Steinhardt
2026-06-10 21:52 ` Justin Tobler
2026-06-10 6:56 ` [PATCH 4/7] builtin/init: stop modifying `is_bare_repository_cfg` Patrick Steinhardt
2026-06-10 6:56 ` [PATCH 5/7] environment: split up concerns of `is_bare_repository_cfg` Patrick Steinhardt
2026-06-10 22:22 ` Justin Tobler
2026-06-10 6:56 ` [PATCH 6/7] environment: stop using `the_repository` in `is_bare_repository()` Patrick Steinhardt
2026-06-10 6:56 ` [PATCH 7/7] treewide: drop USE_THE_REPOSITORY_VARIABLE Patrick Steinhardt
2026-06-10 22:26 ` Justin Tobler
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox