Git development
 help / color / mirror / Atom feed
* [PATCH v2 4/7] builtin/init: stop modifying `is_bare_repository_cfg`
From: Patrick Steinhardt @ 2026-06-11  6:44 UTC (permalink / raw)
  To: git; +Cc: Justin Tobler
In-Reply-To: <20260611-b4-pks-setup-drop-global-state-v2-0-a6f7269c841d@pks.im>

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

* [PATCH v2 3/7] setup: remove global `git_work_tree_cfg` variable
From: Patrick Steinhardt @ 2026-06-11  6:44 UTC (permalink / raw)
  To: git; +Cc: Justin Tobler
In-Reply-To: <20260611-b4-pks-setup-drop-global-state-v2-0-a6f7269c841d@pks.im>

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.

Note that in `check_repository_format_gently()` we now have to free the
candidate work tree variable. This change is required to retain previous
semantics: before we essentially had an implicit `else` branch where we
set `git_work_tree_cfg = NULL`, but we were able to elide that branch
because we already knew that it would be `NULL` anyway. Now that we use
the candidate work tree directly to populate the repository's work tree
though we have to clear it to retain those semantics.

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

* [PATCH v2 2/7] builtin/init: simplify logic to configure worktree
From: Patrick Steinhardt @ 2026-06-11  6:44 UTC (permalink / raw)
  To: git; +Cc: Justin Tobler
In-Reply-To: <20260611-b4-pks-setup-drop-global-state-v2-0-a6f7269c841d@pks.im>

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

* [PATCH v2 1/7] builtin/init: stop modifying global `git_work_tree_cfg` variable
From: Patrick Steinhardt @ 2026-06-11  6:44 UTC (permalink / raw)
  To: git; +Cc: Justin Tobler
In-Reply-To: <20260611-b4-pks-setup-drop-global-state-v2-0-a6f7269c841d@pks.im>

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

* [PATCH v2 0/7] setup: drop global state
From: Patrick Steinhardt @ 2026-06-11  6:44 UTC (permalink / raw)
  To: git; +Cc: Justin Tobler
In-Reply-To: <20260610-b4-pks-setup-drop-global-state-v1-0-5dff3eec8f06@pks.im>

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.

Changes in v2:
  - Improve documentation for some aspects of `check_repository_format_gently()`.
  - Link to v1: https://patch.msgid.link/20260610-b4-pks-setup-drop-global-state-v1-0-5dff3eec8f06@pks.im

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                 | 51 +++++++++++++++++++++++++++++--------------------
 setup.h                 |  6 ++++++
 transport.c             |  4 ++--
 worktree.c              |  4 ++--
 24 files changed, 97 insertions(+), 75 deletions(-)

Range-diff versus v1:

1:  0281a4bca9 = 1:  96b71f5223 builtin/init: stop modifying global `git_work_tree_cfg` variable
2:  6fdc8d77e8 = 2:  a51c0ff79d builtin/init: simplify logic to configure worktree
3:  ce31595ff5 ! 3:  e06393ddc5 setup: remove global `git_work_tree_cfg` variable
    @@ Commit message
         Refactor the code so that we instead use the worktree configuration as
         discovered via the repository format. Drop the global variable.
     
    +    Note that in `check_repository_format_gently()` we now have to free the
    +    candidate work tree variable. This change is required to retain previous
    +    semantics: before we essentially had an implicit `else` branch where we
    +    set `git_work_tree_cfg = NULL`, but we were able to elide that branch
    +    because we already knew that it would be `NULL` anyway. Now that we use
    +    the candidate work tree directly to populate the repository's work tree
    +    though we have to clear it to retain those semantics.
    +
         Signed-off-by: Patrick Steinhardt <ps@pks.im>
     
      ## setup.c ##
4:  6a69dc853c = 4:  628ed54c8c builtin/init: stop modifying `is_bare_repository_cfg`
5:  afa2d8bbda ! 5:  02ceaf4a20 environment: split up concerns of `is_bare_repository_cfg`
    @@ setup.c: static int check_repository_format_gently(const char *gitdir,
     +		 * dictate bareness; it is inherited from the main worktree.
     +		 */
     +		candidate->is_bare = -1;
    ++
    ++		/*
    ++		 * Furthermore, "core.worktree" is supposed to be ignored when
    ++		 * we have a commondir configured, unless it comes from the
    ++		 * per-worktree configuration.
    ++		 */
      		FREE_AND_NULL(candidate->work_tree);
      	}
      
6:  04849a2cb5 = 6:  a08aef5685 environment: stop using `the_repository` in `is_bare_repository()`
7:  78191c7557 = 7:  f93f6599df treewide: drop USE_THE_REPOSITORY_VARIABLE

---
base-commit: f5a08a09a0fdf0fc2a355eba7979e2cfd65659e5
change-id: 20260422-b4-pks-setup-drop-global-state-6b1374aed5db


^ permalink raw reply

* Re: [PATCH v2] describe: limit default ref iteration to tags
From: Jeff King @ 2026-06-11  6:41 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: Tamir Duberstein, git, Junio C Hamano
In-Reply-To: <aika_Q0rWhcI6eXR@pks.im>

On Wed, Jun 10, 2026 at 10:08:51AM +0200, Patrick Steinhardt wrote:

> > Given the discussion in earlier rounds and sibling topics, I assume the
> > commit message here was AI-generated. And it's OK in the sense that it
> > is describing what happened and I assume is entirely accurate. But as a
> > human reader, it feels so much more verbose than what I'd expect, as it
> > is full of semi-irrelevant details. Why set --warmup and --runs? Why
> > bother with --command-name, which just means you have to show the
> > commands separately anyway? Is the amount of RAM in the machine
> > important for this test? Surely it could be if it was absurdly tiny, but
> > in general, no, I would not expect it to be.
> 
> I agree. Earlier this week I also drafted a message that was going down
> this angle, but I think I didn't end up sending it to the mailing list.
> Or at least I'm not able to find it anymore.
> 
> To me the biggest problem is not the verbosity, even though it _is_
> overly verbose. The bigger problem though is the incoherence of the
> story that the commit message is trying to tell where it jumps around
> randomly. It almost feels like rambling to me, and that makes it
> extremely hard to follow the narrative and figure out what the message
> even wants to tell the reader in the first place.

Thanks, this hits directly at the point I was trying to make (I have
trouble sometimes with verbosity, too!). A commit message should
primarily be laying out a narrative about why we are going from the old
state to the new, with supporting arguments. Sometimes you need
back-story for that, sometimes not.  Sometimes you need to discuss
alternatives, sometimes you need specific details about the platform or
versions used for testing, and so on.

> I very much think that we should and even have to expect that
> contributors adapt, because if we don't we will basically reinforce
> whatever AI is doing right now and increase the load on reviewers even
> more.
> 
> I also think that we should reserve the right to reject a patch series
> completely in case we notice that we're basically just talking to a
> middleman that sits between an AI prompt and us (please note that I
> don't refer to this patch series specifically, this is more of a general
> statement). My assumption is that this will become more important as AI
> gets established in more workflows. The number of patch series that look
> sane on the surface but that are utter garbage will very likely increase
> quite significantly going forward.

Yep, agreed.

-Peff

^ permalink raw reply

* Re: [PATCH v2] describe: limit default ref iteration to tags
From: Jeff King @ 2026-06-11  6:37 UTC (permalink / raw)
  To: D. Ben Knoble; +Cc: Tamir Duberstein, git, Junio C Hamano, Patrick Steinhardt
In-Reply-To: <CALnO6CB-9a=P4Os90978YzEH=3iYEHwSbG2oLv9sxVBjBfchMA@mail.gmail.com>

On Tue, Jun 09, 2026 at 09:40:25AM -0400, D. Ben Knoble wrote:

> > Given the discussion in earlier rounds and sibling topics, I assume the
> > commit message here was AI-generated. And it's OK in the sense that it
> > is describing what happened and I assume is entirely accurate. But as a
> > human reader, it feels so much more verbose than what I'd expect, as it
> > is full of semi-irrelevant details. Why set --warmup and --runs? Why
> > bother with --command-name, which just means you have to show the
> > commands separately anyway? Is the amount of RAM in the machine
> > important for this test? Surely it could be if it was absurdly tiny, but
> > in general, no, I would not expect it to be.
> 
> [You probably know this] It is common in academic papers to report
> benchmarks with details about the hardware and how they were run to
> contextualize the results and help with reproducibility.

Yeah, I almost drew the same comparison in my original email. I agree
that having every last detail _could_ help with reproducing in the
future. And that's important when producing a high quality dataset or
academic paper. But the tradeoff seems worse in a commit message, where
it is easy to obscure the main point or overwhelm the reader in what is
otherwise a short-ish document.

> Of course, Git's commits do not form an academic paper… so I have no
> real opinion on what to see here. But I've seen a few other mails
> where having perf test outputs or similar was suggested (maybe that
> was to be reserved for the cover letter? idk).
> 
> _If_ we show all the hyperfine details, I think it's reasonable to use
> --command-name to make distinguishing the versions easy, unless it's
> obvious from the path/to/git in each benchmark (which I think I've
> seen from Peff's benchmark reports before?).

Yeah, I tend to copy the various versions to their own executables,
which gives them short names (so you see "./git.old vs ./git.new" or
something). That's not always completely obvious either, though.

The "short" example I showed may have been a little hyperbolic. I'm OK
with hyperfine output in general, and sometimes show it myself. It is
kind of verbose, but occasionally the distribution of values, or user vs
system vs clock times are important. I'm even OK with --command-name if
it makes things more readable.

I guess what I was really responding to is that I think it is helpful
when the incoming data is cut down to the minimal set of useful details.
That helps a reader immediately assess what is important to the point
being made. Humans tend to do this naturally because we are lazy and
do not want to bother typing or pasting the uninteresting details.
Program output (whether AI or just verbose software) has less of that
impulse.

> Someone with better lore skills can probably dig up a few exemplars of
> how to write about performance in a commit message?

Probably searching for emails from René. :)

-Peff

^ permalink raw reply

* Re: [PATCH 3/7] setup: remove global `git_work_tree_cfg` variable
From: Patrick Steinhardt @ 2026-06-11  6:36 UTC (permalink / raw)
  To: Justin Tobler; +Cc: git
In-Reply-To: <ainXM84fGggtEZzM@denethor>

On Wed, Jun 10, 2026 at 04:52:12PM -0500, Justin Tobler wrote:
> On 26/06/10 08:56AM, Patrick Steinhardt wrote:
> > 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?

This is in fact a required change. Before this patch this here was the
place where we populated `git_work_tree_cfg`, and that variable was then
later on applied to the repository. So the implicit `else` branch was
basically just `git_work_tree_cfg = NULL`, but we didn't have to do that
as it already was set to `NULL`.

With the new code though we're not setting `git_work_tree_cfg` anymore
and instead directly populate from `candidate->work_tree`. But that also
means that we now have to clear that variable to retain previous
semantics.

I'll add an explanation to the commit message.

Patrick

^ permalink raw reply

* Re: [PATCH v2 3/3] doc: git-config: escape erroneous highlight markup
From: Jeff King @ 2026-06-11  6:25 UTC (permalink / raw)
  To: Tuomas Ahola
  Cc: git, Kristoffer Haugsbakk, Junio C Hamano, Jean-Noël Avila
In-Reply-To: <20260611062423.GA2189088@coredump.intra.peff.net>

[and naturally I forgot to cc Jean-Noël; resending, sorry for the noise]

On Thu, Jun 11, 2026 at 02:24:23AM -0400, Jeff King wrote:

> On Thu, Jun 11, 2026 at 02:11:57AM -0400, Jeff King wrote:
> 
> > Though curiously the case of `#` in git-fast-import seems not to get
> > marked as <code> in the html output (even though the nearby `LF` does).
> > I wonder if there is some special treatment of `#` or something.
> 
> Ah, weird, it has to do with our config file.
> 
> If I do this (not in the git repository):
> 
>   echo 'This is a literal `#` symbol.' >foo.adoc
>   asciidoc foo.adoc
>   grep -i symbol foo.html
> 
> then I get <code> markers, like:
> 
>   <div class="paragraph"><p>This is a literal <code>#</code> symbol.</p></div>
> 
> But if I build with:
> 
>   asciidoc -f path/to/git/Documentation/asciidoc.conf foo.adoc
> 
> then the grep shows:
> 
>   <div class="paragraph"><p>This is a literal # symbol.</p></div>
> 
> Looks like it is due to our [literal-inlinemacro] definition, which
> comes from 974cdca345 (doc: introduce a synopsis typesetting,
> 2024-09-24). I think this might have been an unintended side effect.
> +cc the author of that commit.
> 
> For the purposes of your series, I think we can ignore any issues with
> [literal-inlinemacro] for the moment, and decide on "\" versus ``
> depending on which we prefer.
> 
> -Peff

^ permalink raw reply

* Re: [PATCH v2 3/3] doc: git-config: escape erroneous highlight markup
From: Jeff King @ 2026-06-11  6:24 UTC (permalink / raw)
  To: Tuomas Ahola; +Cc: git, Kristoffer Haugsbakk, Junio C Hamano
In-Reply-To: <20260611061156.GC2187173@coredump.intra.peff.net>

On Thu, Jun 11, 2026 at 02:11:57AM -0400, Jeff King wrote:

> Though curiously the case of `#` in git-fast-import seems not to get
> marked as <code> in the html output (even though the nearby `LF` does).
> I wonder if there is some special treatment of `#` or something.

Ah, weird, it has to do with our config file.

If I do this (not in the git repository):

  echo 'This is a literal `#` symbol.' >foo.adoc
  asciidoc foo.adoc
  grep -i symbol foo.html

then I get <code> markers, like:

  <div class="paragraph"><p>This is a literal <code>#</code> symbol.</p></div>

But if I build with:

  asciidoc -f path/to/git/Documentation/asciidoc.conf foo.adoc

then the grep shows:

  <div class="paragraph"><p>This is a literal # symbol.</p></div>

Looks like it is due to our [literal-inlinemacro] definition, which
comes from 974cdca345 (doc: introduce a synopsis typesetting,
2024-09-24). I think this might have been an unintended side effect.
+cc the author of that commit.

For the purposes of your series, I think we can ignore any issues with
[literal-inlinemacro] for the moment, and decide on "\" versus ``
depending on which we prefer.

-Peff

^ permalink raw reply

* [PATCH v2] log: improve --follow following renames for non-linear history
From: Miklos Vajna @ 2026-06-11  6:18 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jeff King, git
In-Reply-To: <xmqqpl21vzj2.fsf@gitster.g>

Have a repo with a subtree merge, do a 'git log --follow prefix/test.c',
the output only contains history in the outer repo, not commits that
were merged via a subtree merge.

What happens is that 'git log --follow' stores the followed path only in
opt->diffopt.pathspec, so in case the commit history is non-linear, and
multiple parents have renames to the followed path, then the end result
isn't really defined: the first commit that happens to be visited in one
of the parents update opt->diffopt.pathspec, and from that point, only
that updated path is visited.

Fix the problem by introducing a commit -> paths map
(follow_pathspec_slab) that stores what will be paths to follow when
visiting that parent. At the top of log_tree_commit(), if the slab has
an entry for this commit, we replace opt->diffopt.pathspec with paths
from this entry, so the correct paths are followed, even if an unrelated
sub-tree changed the paths to be followed to something else. After
log_tree_diff() runs, we record each parent's paths in the slab. As a
result, the walk order doesn't matter, which was exactly the source of
problems previously.

This helps with subtree merges (rename happens inside the merge commit),
but also fixes the general case when the rename happens in the history
of parents, not in the merge commit itself. This does not remove the
limitation that only a single path can be specified on the command-line,
but we now do follow multiple paths instead of a "last write wins"
situation when determining what path to follow for a specific commit
with multiple previously visited children.
---

Hi Junio,

On Mon, Jun 08, 2026 at 08:10:25AM -0700, Junio C Hamano <gitster@pobox.com> wrote:
> When describing a problematic symptom you are trying to improve, you
> should talk about the current state of the system in the present
> tense.  "used to store" makes it sound like in ancient times back
> when Linus wrote the first version of this feature it was so, but a
> few years ago that changed, but that is not what you want to say, is
> it?
> 
> The above may sound picky, but using the consistent style of
> description makes it easier to follow the thought process,
> especially when you need to read many commits to understand what is
> going on.

Makes sense, I now fixed this.

> Can a "map" cut it?
> 
> If a history forked at commit A, with two children commit B and
> commit C, and you started traversing the history from a much later
> descendant M that merges these two lines of history (i.e., M^1
> contains B, M^2 contains C, and A==B^1==C^1), while traversing down
> from M to B you may find that you need to follow path1 and similarly
> somewhere between M down to C the path you are following may be
> path2.  And the traversal meets at A.  The slab records path1 for B
> and path2 for C.  Wouldn't you need to be able to store both path1
> and path2 for commit A?  What path do you need to pay attention to
> when traversing past A to its ancestors?

Indeed, I focused on merge commits and their parents and I did not 
consider that slab[A] may be set to path1 when visiting one parent and 
then slab[A] may be set to path2 when visiting an other parent -- even 
if "A" itself is just a plain commit with no renames and is not a merge.

Here is an updated version, where I changed the value of 
follow_pathspec_slab to be a string_list, and appended a new test that 
shows we now handle this case.

Thanks,

Miklos

 Documentation/config/log.adoc |   3 +-
 log-tree.c                    | 133 ++++++++++++++++++++++++++++++++++
 log-tree.h                    |   1 +
 revision.c                    |   2 +
 revision.h                    |   4 +
 t/meson.build                 |   1 +
 t/t4218-log-follow-merge.sh   | 119 ++++++++++++++++++++++++++++++
 7 files changed, 261 insertions(+), 2 deletions(-)
 create mode 100755 t/t4218-log-follow-merge.sh

diff --git a/Documentation/config/log.adoc b/Documentation/config/log.adoc
index f20cc25cd7..757a7be196 100644
--- a/Documentation/config/log.adoc
+++ b/Documentation/config/log.adoc
@@ -53,8 +53,7 @@ This is the same as the `--decorate` option of the `git log`.
 `log.follow`::
 	If `true`, `git log` will act as if the `--follow` option was used when
 	a single <path> is given.  This has the same limitations as `--follow`,
-	i.e. it cannot be used to follow multiple files and does not work well
-	on non-linear history.
+	i.e. it cannot be used to follow multiple files.
 
 `log.graphColors`::
 	A list of colors, separated by commas, that can be used to draw
diff --git a/log-tree.c b/log-tree.c
index 7e048701d0..f6f396be22 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -3,6 +3,7 @@
 
 #include "git-compat-util.h"
 #include "commit-reach.h"
+#include "commit-slab.h"
 #include "config.h"
 #include "diff.h"
 #include "diffcore.h"
@@ -1089,6 +1090,104 @@ static int do_remerge_diff(struct rev_info *opt,
 	return !opt->loginfo;
 }
 
+/* Per-commit paths storage for --follow across merges */
+define_commit_slab(follow_pathspec_slab, struct string_list);
+
+static const char *pathspec_single_path(const struct pathspec *ps)
+{
+	if (ps->nr != 1)
+		return NULL;
+	return ps->items[0].match;
+}
+
+static void set_pathspec_to_paths(struct pathspec *ps,
+				  const struct string_list *paths)
+{
+	const char **argv;
+	struct string_list_item *item;
+	int i = 0;
+
+	clear_pathspec(ps);
+	if (!paths->nr)
+		return;
+	ALLOC_ARRAY(argv, paths->nr + 1);
+	for_each_string_list_item(item, paths)
+		argv[i++] = item->string;
+	argv[i] = NULL;
+	parse_pathspec(ps,
+		       PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,
+		       PATHSPEC_LITERAL_PATH, "", argv);
+	free(argv);
+}
+
+static struct string_list *get_follow_pathspec_at(struct rev_info *opt,
+						  struct commit *c)
+{
+	struct string_list *list;
+
+	if (!opt->follow_pathspec_slab) {
+		opt->follow_pathspec_slab = xmalloc(sizeof(*opt->follow_pathspec_slab));
+		init_follow_pathspec_slab(opt->follow_pathspec_slab);
+	}
+	list = follow_pathspec_slab_at(opt->follow_pathspec_slab, c);
+	if (!list->strdup_strings)
+		list->strdup_strings = 1;
+	return list;
+}
+
+static void remember_follow_pathspec(struct rev_info *opt,
+				     struct commit *c, const char *path)
+{
+	if (!path)
+		return;
+	string_list_insert(get_follow_pathspec_at(opt, c), path);
+}
+
+static void free_follow_pathspec_slot(struct string_list *slot)
+{
+	string_list_clear(slot, 0);
+}
+
+void release_follow_pathspec_slab(struct rev_info *opt)
+{
+	if (!opt->follow_pathspec_slab)
+		return;
+	deep_clear_follow_pathspec_slab(opt->follow_pathspec_slab,
+					free_follow_pathspec_slot);
+	FREE_AND_NULL(opt->follow_pathspec_slab);
+}
+
+/* Compute a path to follow in parent, if there is one */
+static void propagate_follow_pathspec_to_parent(struct rev_info *opt,
+						const char *path,
+						struct commit *commit,
+						struct commit *parent)
+{
+	struct diff_options diff_opts;
+	const char *paths[2] = { path, NULL };
+	const char *out_path;
+
+	parse_commit_or_die(parent);
+	repo_diff_setup(opt->diffopt.repo, &diff_opts);
+	parse_pathspec(&diff_opts.pathspec,
+		       PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,
+		       PATHSPEC_LITERAL_PATH, "", paths);
+	diff_opts.flags.recursive = 1;
+	diff_opts.flags.follow_renames = 1;
+	diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;
+	diff_setup_done(&diff_opts);
+	diff_tree_oid(get_commit_tree_oid(parent),
+		      get_commit_tree_oid(commit),
+		      "", &diff_opts);
+
+	out_path = pathspec_single_path(&diff_opts.pathspec);
+	if (out_path)
+		remember_follow_pathspec(opt, parent, out_path);
+
+	diff_queue_clear(&diff_queued_diff);
+	diff_free(&diff_opts);
+}
+
 /*
  * Show the diff of a commit.
  *
@@ -1173,12 +1272,30 @@ int log_tree_commit(struct rev_info *opt, struct commit *commit)
 	int shown;
 	/* maybe called by e.g. cmd_log_walk(), maybe stand-alone */
 	int no_free = opt->diffopt.no_free;
+	int saved_follow_renames = 0;
+	struct string_list *paths = NULL;
 
 	log.commit = commit;
 	log.parent = NULL;
 	opt->loginfo = &log;
 	opt->diffopt.no_free = 1;
 
+	/* Any recorded paths for this commit? If so, restore it */
+	if (opt->diffopt.flags.follow_renames) {
+		paths = get_follow_pathspec_at(opt, commit);
+		if (!paths->nr) {
+			const char *path = pathspec_single_path(&opt->diffopt.pathspec);
+			if (path)
+				string_list_insert(paths, path);
+		}
+		set_pathspec_to_paths(&opt->diffopt.pathspec, paths);
+		if (paths->nr > 1) {
+			/* diff_check_follow_pathspec() doesn't handle multiple paths */
+			saved_follow_renames = opt->diffopt.flags.follow_renames;
+			opt->diffopt.flags.follow_renames = 0;
+		}
+	}
+
 	/* NEEDSWORK: no restoring of no_free?  Why? */
 	if (opt->line_level_traverse)
 		return line_log_print(opt, commit);
@@ -1195,6 +1312,22 @@ int log_tree_commit(struct rev_info *opt, struct commit *commit)
 		fprintf(opt->diffopt.file, "\n%s\n", opt->break_bar);
 	if (shown)
 		show_diff_of_diff(opt);
+
+	if (saved_follow_renames)
+		opt->diffopt.flags.follow_renames = saved_follow_renames;
+
+	/* Record what paths each parent of this commit should use */
+	if (opt->diffopt.flags.follow_renames && paths) {
+		struct commit_list *parents = get_saved_parents(opt, commit);
+		struct commit_list *p;
+		struct string_list_item *item;
+		for (p = parents; p; p = p->next) {
+			for_each_string_list_item(item, paths)
+				propagate_follow_pathspec_to_parent(opt,
+					item->string, commit, p->item);
+		}
+	}
+
 	opt->loginfo = NULL;
 	maybe_flush_or_die(opt->diffopt.file, "stdout");
 	opt->diffopt.no_free = no_free;
diff --git a/log-tree.h b/log-tree.h
index 07924be8bc..e8679b6c4a 100644
--- a/log-tree.h
+++ b/log-tree.h
@@ -26,6 +26,7 @@ struct decoration_options {
 int parse_decorate_color_config(const char *var, const char *slot_name, const char *value);
 int log_tree_diff_flush(struct rev_info *);
 int log_tree_commit(struct rev_info *, struct commit *);
+void release_follow_pathspec_slab(struct rev_info *);
 void show_log(struct rev_info *opt);
 void format_decorations(struct strbuf *sb, const struct commit *commit,
 			enum git_colorbool use_color, const struct decoration_options *opts);
diff --git a/revision.c b/revision.c
index 5693618be4..caa85fb4c6 100644
--- a/revision.c
+++ b/revision.c
@@ -26,6 +26,7 @@
 #include "decorate.h"
 #include "string-list.h"
 #include "line-log.h"
+#include "log-tree.h"
 #include "mailmap.h"
 #include "commit-slab.h"
 #include "cache-tree.h"
@@ -3284,6 +3285,7 @@ void release_revisions(struct rev_info *revs)
 	line_log_free(revs);
 	oidset_clear(&revs->missing_commits);
 	release_revisions_bloom_keyvecs(revs);
+	release_follow_pathspec_slab(revs);
 }
 
 static void add_child(struct rev_info *revs, struct commit *parent, struct commit *child)
diff --git a/revision.h b/revision.h
index c9a11827cc..607113ca74 100644
--- a/revision.h
+++ b/revision.h
@@ -65,6 +65,7 @@ struct repository;
 struct rev_info;
 struct string_list;
 struct saved_parents;
+struct follow_pathspec_slab;
 struct bloom_keyvec;
 struct bloom_filter_settings;
 struct option;
@@ -354,6 +355,9 @@ struct rev_info {
 	/* copies of the parent lists, for --full-diff display */
 	struct saved_parents *saved_parents_slab;
 
+	/* per-commit pathspec for --follow across merges */
+	struct follow_pathspec_slab *follow_pathspec_slab;
+
 	struct commit_list *previous_parents;
 	struct commit_list *ancestry_path_bottoms;
 	const char *break_bar;
diff --git a/t/meson.build b/t/meson.build
index c5832fee05..faecae2b50 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -576,6 +576,7 @@ integration_tests = [
   't4215-log-skewed-merges.sh',
   't4216-log-bloom.sh',
   't4217-log-limit.sh',
+  't4218-log-follow-merge.sh',
   't4252-am-options.sh',
   't4253-am-keep-cr-dos.sh',
   't4254-am-corrupt.sh',
diff --git a/t/t4218-log-follow-merge.sh b/t/t4218-log-follow-merge.sh
new file mode 100755
index 0000000000..dcb0c937d7
--- /dev/null
+++ b/t/t4218-log-follow-merge.sh
@@ -0,0 +1,119 @@
+#!/bin/sh
+
+test_description='Test --follow follows renames across merges'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+test_expect_success 'setup subtree-merged repository' '
+	git init inner &&
+	echo inner >inner/inner.txt &&
+	git -C inner add inner.txt &&
+	git -C inner commit -m "inner init" &&
+
+	git init outer &&
+	echo outer >outer/outer.txt &&
+	git -C outer add outer.txt &&
+	git -C outer commit -m "outer init" &&
+
+	git -C outer fetch ../inner master &&
+	git -C outer merge -s ours --no-commit --allow-unrelated-histories \
+		FETCH_HEAD &&
+	git -C outer read-tree --prefix=inner/ -u FETCH_HEAD &&
+	git -C outer commit -m "Merge inner repo into inner/ subdirectory"
+'
+
+test_expect_success '--follow finds the pre-merge commit through a subtree merge' '
+	git -C outer log --follow --pretty=tformat:%s inner/inner.txt >actual &&
+	echo "inner init" >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'setup merge of two branches that both renamed a file to README' '
+	git init foo &&
+	mkdir foo/foo &&
+	echo "foo readme" >foo/foo/README &&
+	git -C foo add foo/README &&
+	git -C foo commit -m "add foo README" &&
+
+	git -C foo mv foo/README README &&
+	git -C foo commit -m "promote foo README to toplevel" &&
+
+	echo "foo c" >foo/foo.c &&
+	git -C foo add foo.c &&
+	git -C foo commit -m "add foo C impl" &&
+
+	git init bar &&
+	mkdir bar/bar &&
+	echo "bar readme" >bar/bar/README &&
+	git -C bar add bar/README &&
+	git -C bar commit -m "add bar README" &&
+
+	git -C bar mv bar/README README &&
+	git -C bar commit -m "promote bar README to toplevel" &&
+
+	echo "bar c" >bar/bar.c &&
+	git -C bar add bar.c &&
+	git -C bar commit -m "add bar C impl" &&
+
+	git -C foo fetch ../bar master &&
+	git -C foo merge -s ours --no-commit --allow-unrelated-histories \
+		FETCH_HEAD &&
+	git -C foo checkout FETCH_HEAD -- bar.c &&
+	git -C foo commit -m "merge bar into foo"
+'
+
+test_expect_success '--follow follows renames across both sides of a merge' '
+	git -C foo log --follow --pretty=tformat:%s README >actual &&
+	sort actual >actual.sorted &&
+	cat >expect <<-\EOF &&
+	add bar README
+	add foo README
+	promote bar README to toplevel
+	promote foo README to toplevel
+	EOF
+	test_cmp expect actual.sorted
+'
+
+# When two branches rename a different file to the same name and then meet again
+# in a merge, log --follow needs to keep track both paths.
+test_expect_success 'setup criss-cross merge where two paths converge in ancestor' '
+	git init crisscross &&
+	echo "alpha content" >crisscross/alpha.txt &&
+	git -C crisscross add alpha.txt &&
+	git -C crisscross commit -m "root: add alpha.txt" &&
+
+	echo "beta content" >crisscross/beta.txt &&
+	git -C crisscross add beta.txt &&
+	git -C crisscross commit -m "fork: add beta.txt" &&
+
+	git -C crisscross checkout -b branchB &&
+	git -C crisscross mv alpha.txt combined.txt &&
+	git -C crisscross rm beta.txt &&
+	git -C crisscross commit -m "B: rename alpha to combined" &&
+
+	git -C crisscross checkout master &&
+	git -C crisscross checkout -b branchC &&
+	git -C crisscross mv beta.txt combined.txt &&
+	git -C crisscross rm alpha.txt &&
+	git -C crisscross commit -m "C: rename beta to combined" &&
+
+	git -C crisscross checkout branchB &&
+	git -C crisscross merge -s ours -m "merge C into B" branchC
+'
+
+test_expect_success '--follow follows two diverged paths past their common ancestor' '
+	git -C crisscross log --follow --pretty=tformat:%s combined.txt >actual &&
+	sort actual >actual.sorted &&
+	cat >expect <<-\EOF &&
+	B: rename alpha to combined
+	C: rename beta to combined
+	fork: add beta.txt
+	root: add alpha.txt
+	EOF
+	test_cmp expect actual.sorted
+'
+
+test_done
-- 
2.51.0


^ permalink raw reply related

* Re: [PATCH v2 3/3] doc: git-config: escape erroneous highlight markup
From: Jeff King @ 2026-06-11  6:11 UTC (permalink / raw)
  To: Tuomas Ahola; +Cc: git, Kristoffer Haugsbakk, Junio C Hamano
In-Reply-To: <20260610225513.6269-4-taahol@utu.fi>

On Thu, Jun 11, 2026 at 01:55:13AM +0300, Tuomas Ahola wrote:

> Paired octothorpes are used in AsciiDoc to mark highlighted text,
> <mark> being the equivalent HTML tag.  To use the symbol as a literal
> character, it can be escaped with a backslash.
> 
> Do so in git-config.adoc.

I think this works OK, but in general I think most uses of backslash for
metacharacters should consider using literal backticks. That shields it
from the special meaning for asciidoc, but also will render it
differently for the user (usually with a typewriter font, which becomes
bold in roff output).

Though curiously the case of `#` in git-fast-import seems not to get
marked as <code> in the html output (even though the nearby `LF` does).
I wonder if there is some special treatment of `#` or something.

>  If _<message>_ begins with one or more whitespaces followed
> -by "#", it is used as-is.  If it begins with "#", a space is
> +by "\#", it is used as-is.  If it begins with "\#", a space is
>  prepended before it is used.  Otherwise, a string " # " (a
>  space followed by a hash followed by a space) is prepended

I saw the comment on round 1 about this second "#" on the line. But
while we are here, should we be doing the one in the context, too?

-Peff

^ permalink raw reply

* Re: [PATCH v2 1/3] doc: config: terminate runaway lists
From: Jeff King @ 2026-06-11  6:02 UTC (permalink / raw)
  To: Tuomas Ahola; +Cc: git, Kristoffer Haugsbakk, Junio C Hamano
In-Reply-To: <20260610225513.6269-2-taahol@utu.fi>

On Thu, Jun 11, 2026 at 01:55:11AM +0300, Tuomas Ahola wrote:

> There are many places in git-config(1) where paragraphs that should
> logically come after a list are instead appended to the last item of
> the list.  This is a well-documented quirk of AsciiDoc, and can be
> mitigated by enclosing the list in an open block:
> 
> 	--
> 	* first item
> 	* last item
> 	--
> 	+
> 	New paragraph after the list.
> 
> Fix the issue accordingly.

Makes sense. We've run into problems in the past where adding "--"
doesn't quite work, because we are already inside a "--" (and IIRC the
behavior is not always completely predictable). But I double-checked
these cases, and we are not already in a "--". So we should be good
here.

-Peff

^ permalink raw reply

* Re: followRemoteHEAD management question
From: Jeff King @ 2026-06-11  6:01 UTC (permalink / raw)
  To: Matt Hunter; +Cc: git, Bence Ferdinandy
In-Reply-To: <DJ5XE9HC5YNY.33U8AG1GX6ZP0@lfurio.us>

On Thu, Jun 11, 2026 at 12:12:54AM -0400, Matt Hunter wrote:

> > Yes, this is a common problem with the remote-config namespace. Defining
> > _any_ key makes the remote "exist", even without a defined url, but that
> > isn't usually the intent.  But we can't distinguish that from the case
> > where you really do want to define a remote without a url (in which case
> > the url is the name of the remote).
> 
> I had no idea a remote like that was supported.  Interesting.

I suspect it is more of an emergent property than something that was
carefully designed, but after so many years I'd hesitate to change it
(at least without a big warning and deprecation period).

> > I think you are on the right track. I can see arguments for or against
> > putting it in fetch.* or remote.*, so you'll have to pick one. ;)
> 
> As stated, I think putting it in fetch.* is more consistent.  I'd be
> curious to hear arguments the other way.

My initial thought is that it might affect clone as well as fetch. But I
guess this feature does not kick in for clone, as it has its own logic
for handling the remote-tracking HEAD. Though arguably it should be
possible to configure it not to create one in the first place.

> As for another design decision: I'm leaning toward omitting support for
> the "warn-if-not-$branch" value in fetch.followRemoteHEAD.
> 
> My take on that option as-documented is that it serves more as an
> acknowledgment from the user that "yes, I understand that origin has
> pointed HEAD at foo, please only warn me if it changes" as opposed to the
> user expressing that the branch "foo" is in some way special to them.
> 
> This interpretation feels very remote-dependent and doesn't make sense in
> the context of a default catch-all value to me.

Agreed. I can't think of a reason you'd want it in the global option.
And if we're wrong, it is easy to add support later (versus adding it
now, finding out that it creates awkward corner cases, and then having
the backwards-incompatible change of ripping it out).

-Peff

^ permalink raw reply

* Re: [PATCH v4] git-gui: silence install recipes under "make -s"
From: Johannes Sixt @ 2026-06-11  5:37 UTC (permalink / raw)
  To: Harald Nordgren; +Cc: git, Harald Nordgren via GitGitGadget
In-Reply-To: <CAHwyqnUpiWmXo0SVr=7L-+cwA+qhVyqodpV-O4C46w=kLqaLMg@mail.gmail.com>

Am 10.06.26 um 15:19 schrieb Harald Nordgren:
> What does it mean for it to be queued here, should I expect it to show
> up on seen or next?
It means that I'll arrange that it will appear in the next Git release.
Until then you can find the commit in
https://github.com/j6t/git-gui/tree/hn/silence-make-s .

-- Hannes


^ permalink raw reply

* Re: followRemoteHEAD management question
From: Matt Hunter @ 2026-06-11  4:12 UTC (permalink / raw)
  To: Jeff King; +Cc: git, Bence Ferdinandy
In-Reply-To: <20260608234946.GB358144@coredump.intra.peff.net>

On Mon Jun 8, 2026 at 7:49 PM EDT, Jeff King wrote:
>> 
>> The topic mentioned above (merged in a1f34d595503) adds a new
>> configuration key 'remote.<name>.followRemoteHEAD'.  I'm assuming that
>> the intended use for followRemoteHEAD is really only in local /
>> per-repository config, since trying to apply it to my personal
>> .gitconfig has some odd behavior.
>
> I think this is a gap in the new feature's implementation. It added
> per-remote config, but there is no global config to fall back to (e.g.,
> the way that remote.*.prune falls back to fetch.prune). There should be
> a fetch.followRemoteHEAD option (or perhaps remote.followRemoteHEAD).

Earlier on while working on this, I actually settled on
fetch.followRemoteHEAD instead, taking example from the prune setting.
Thanks for the confirmation.

>> The <name> in the key template does not accept a wildcard, so I must
>> list out each of the common remote names I use across different
>> repositories.  Since many of my repos don't actually have remotes
>> established for all of these names, they pick up a kind of half-baked
>> definition for each of them as git performs its config parsing.  For
>> instance, a name will appear under 'git remote -v', but it won't
>> have any actual properties configured.
>
> Yes, this is a common problem with the remote-config namespace. Defining
> _any_ key makes the remote "exist", even without a defined url, but that
> isn't usually the intent.  But we can't distinguish that from the case
> where you really do want to define a remote without a url (in which case
> the url is the name of the remote).

I had no idea a remote like that was supported.  Interesting.

>> Is there another solution in place I've missed?  If not, would there be
>> any opposition to a new key like 'remote.followRemoteHEAD' which serves
>> to provide a default value for any remote that doesn't have its own
>> 'remote.<name>.followRemoteHEAD' key?
>> 
>> I've started scouting out changes to make for such a patch.  It's not
>> ready yet, but I figured I would throw this question out in case an easy
>> answer can save the effort.
>
> I think you are on the right track. I can see arguments for or against
> putting it in fetch.* or remote.*, so you'll have to pick one. ;)

As stated, I think putting it in fetch.* is more consistent.  I'd be
curious to hear arguments the other way.

As for another design decision: I'm leaning toward omitting support for
the "warn-if-not-$branch" value in fetch.followRemoteHEAD.

My take on that option as-documented is that it serves more as an
acknowledgment from the user that "yes, I understand that origin has
pointed HEAD at foo, please only warn me if it changes" as opposed to the
user expressing that the branch "foo" is in some way special to them.

This interpretation feels very remote-dependent and doesn't make sense in
the context of a default catch-all value to me.

Thanks for the feedback!

^ permalink raw reply

* Re: [PATCH v3 02/11] doc: interpret-trailers: replace “lines” with “metadata”
From: Matt Hunter @ 2026-06-11  3:10 UTC (permalink / raw)
  To: kristofferhaugsbakk, git
  Cc: Kristoffer Haugsbakk, christian.couder, jackmanb, Linus Arver,
	D . Ben Knoble
In-Reply-To: <V3_metadata_not_lines.8a5@msgid.xyz>

On Wed Jun 10, 2026 at 5:21 PM EDT, kristofferhaugsbakk wrote:
>
> diff --git a/Documentation/git-interpret-trailers.adoc b/Documentation/git-interpret-trailers.adoc
> index 1878848ad2a..3f60fd9b720 100644
> --- a/Documentation/git-interpret-trailers.adoc
> +++ b/Documentation/git-interpret-trailers.adoc
> @@ -14,7 +14,7 @@ git interpret-trailers [--in-place] [--trim-empty]
>  
>  DESCRIPTION
>  -----------
> -Add or parse _trailer_ lines at the end of the otherwise
> +Add or parse trailers metadata at the end of the otherwise

fwiw, I think "trailer metadata" reads more naturally.

^ permalink raw reply

* Re: [PATCH v2 3/3] environment: move trust_executable_bit into repo_config_values
From: Tian Yuchen @ 2026-06-11  2:58 UTC (permalink / raw)
  To: git; +Cc: ps, Christian Couder, Ayush Chandekar, Olamide Caleb Bello
In-Reply-To: <20260610093635.139719-4-cat@malon.dev>

On 6/10/26 17:36, Tian Yuchen wrote:
> Move the global 'trust_executable_bit' configurations
> into the repository-specific 'repo_config_values'
> struct. To ensure code readability, the getter functions
> 'repo_trust_executable_bit()' has been introduced.
> 
> For now, associated functions access this configuration by
> explicitly falling back to 'the_repository'.
> 
> Mentored-by: Christian Couder <christian.couder@gmail.com>
> Mentored-by: Ayush Chandekar <ayu.chandekar@gmail.com>
> Mentored-by: Olamide Caleb Bello <belkid98@gmail.com>
> Signed-off-by: Tian Yuchen <cat@malon.dev>
> ---
>   apply.c       |  2 +-
>   environment.c | 11 +++++++++--
>   environment.h |  9 ++++++++-
>   read-cache.c  |  8 ++++----
>   4 files changed, 22 insertions(+), 8 deletions(-)
> 
> diff --git a/apply.c b/apply.c
> index 249248d4f2..fbb907d3c0 100644
> --- a/apply.c
> +++ b/apply.c
> @@ -3893,7 +3893,7 @@ static int check_preimage(struct apply_state *state,
>   		if (*ce && !(*ce)->ce_mode)
>   			BUG("ce_mode == 0 for path '%s'", old_name);
>   
> -		if (trust_executable_bit || !S_ISREG(st->st_mode))
> +		if (repo_trust_executable_bit(the_repository) || !S_ISREG(st->st_mode))
>   			st_mode = ce_mode_from_stat(*ce, st->st_mode);
>   		else if (*ce)
>   			st_mode = (*ce)->ce_mode;
> diff --git a/environment.c b/environment.c
> index fc3ed8bb1c..75069a884d 100644
> --- a/environment.c
> +++ b/environment.c
> @@ -41,7 +41,6 @@
>   static int pack_compression_seen;
>   static int zlib_compression_seen;
>   
> -int trust_executable_bit = 1;
>   int trust_ctime = 1;
>   int check_stat = 1;
>   int has_symlinks = 1;
> @@ -142,6 +141,13 @@ int is_bare_repository(void)
>   	return is_bare_repository_cfg && !repo_get_work_tree(the_repository);
>   }
>   
> +int repo_trust_executable_bit(struct repository *repo)
> +{
> +	return repo->gitdir?
> +		repo_config_values(repo)->trust_executable_bit :
> +		1;
> +}
> +
>   int have_git_dir(void)
>   {
>   	return startup_info->have_repository
> @@ -305,7 +311,7 @@ int git_default_core_config(const char *var, const char *value,
>   
>   	/* This needs a better name */
>   	if (!strcmp(var, "core.filemode")) {
> -		trust_executable_bit = git_config_bool(var, value);
> +		cfg->trust_executable_bit = git_config_bool(var, value);
>   		return 0;
>   	}
>   	if (!strcmp(var, "core.trustctime")) {
> @@ -720,5 +726,6 @@ void repo_config_values_init(struct repo_config_values *cfg)
>   {
>   	cfg->attributes_file = NULL;
>   	cfg->apply_sparse_checkout = 0;
> +	cfg->trust_executable_bit = 1;
>   	cfg->branch_track = BRANCH_TRACK_REMOTE;
>   }
> diff --git a/environment.h b/environment.h
> index 123a71cdc8..44b97be654 100644
> --- a/environment.h
> +++ b/environment.h
> @@ -91,6 +91,7 @@ struct repo_config_values {
>   	/* section "core" config values */
>   	char *attributes_file;
>   	int apply_sparse_checkout;
> +	int trust_executable_bit;
>   
>   	/* section "branch" config values */
>   	enum branch_track branch_track;
> @@ -123,6 +124,13 @@ int git_default_config(const char *, const char *,
>   int git_default_core_config(const char *var, const char *value,
>   			    const struct config_context *ctx, void *cb);
>   
> +/*
> + * Getters for the `repo_trust_executable_bit` fields of `struct repo_config_values`.
> + * They check `repo->gitdir` to prevent calling repo_config_values()
> + * before the configuration is loaded or in bare environments.
> + */
> +int repo_trust_executable_bit(struct repository *repo);
> +
>   void repo_config_values_init(struct repo_config_values *cfg);
>   
>   /*
> @@ -160,7 +168,6 @@ int is_bare_repository(void);
>   extern char *git_work_tree_cfg;
>   
>   /* Environment bits from configuration mechanism */
> -extern int trust_executable_bit;
>   extern int trust_ctime;
>   extern int check_stat;
>   extern int has_symlinks;
> diff --git a/read-cache.c b/read-cache.c
> index cb4f4878c8..89f5c88c58 100644
> --- a/read-cache.c
> +++ b/read-cache.c
> @@ -214,7 +214,7 @@ unsigned int ce_mode_from_stat(const struct cache_entry *ce, unsigned int mode)
>   	if (!has_symlinks && S_ISREG(mode) &&
>   	    ce && S_ISLNK(ce->ce_mode))
>   		return ce->ce_mode;
> -	if (!trust_executable_bit && S_ISREG(mode)) {
> +	if (!repo_trust_executable_bit(the_repository) && S_ISREG(mode)) {
>   		if (ce && S_ISREG(ce->ce_mode))
>   			return ce->ce_mode;
>   		return create_ce_mode(0666);
> @@ -228,7 +228,7 @@ static unsigned int st_mode_from_ce(const struct cache_entry *ce)
>   	case S_IFLNK:
>   		return has_symlinks ? S_IFLNK : (S_IFREG | 0644);
>   	case S_IFREG:
> -		return (ce->ce_mode & (trust_executable_bit ? 0755 : 0644)) | S_IFREG;
> +		return (ce->ce_mode & (repo_trust_executable_bit(the_repository) ? 0755 : 0644)) | S_IFREG;
>   	case S_IFGITLINK:
>   		return S_IFDIR | 0755;
>   	case S_IFDIR:
> @@ -338,7 +338,7 @@ static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)
>   		/* We consider only the owner x bit to be relevant for
>   		 * "mode changes"
>   		 */
> -		if (trust_executable_bit &&
> +		if (repo_trust_executable_bit(the_repository) &&
>   		    (0100 & (ce->ce_mode ^ st->st_mode)))
>   			changed |= MODE_CHANGED;
>   		break;
> @@ -759,7 +759,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
>   		ce->ce_flags |= CE_INTENT_TO_ADD;
>   
>   
> -	if (trust_executable_bit && has_symlinks) {
> +	if (repo_trust_executable_bit(the_repository) && has_symlinks) {
>   		ce->ce_mode = create_ce_mode(st_mode);
>   	} else {
>   		/* If there is an existing entry, pick the mode bits and type

There seem to be typos everywhere here, will change in the next reroll.

Regards, yuchen


^ permalink raw reply

* [PATCH v2 0/3] doc: config: fix AsciiDoc glitches
From: Tuomas Ahola @ 2026-06-10 22:55 UTC (permalink / raw)
  To: git; +Cc: Kristoffer Haugsbakk, Junio C Hamano, Tuomas Ahola
In-Reply-To: <20260610185148.23920-1-taahol@utu.fi>

Fix various markup shortcomings in git-config(1).

Based on 29bd7ed512 (The second batch, 2026-05-12).

Tuomas Ahola (3):
  doc: config: terminate runaway lists
  doc: config/sideband: fix description list delimiter
  doc: git-config: escape erroneous highlight markup

 Documentation/config.adoc          | 4 +++-
 Documentation/config/promisor.adoc | 2 ++
 Documentation/config/safe.adoc     | 2 ++
 Documentation/config/sideband.adoc | 2 +-
 Documentation/git-config.adoc      | 6 ++++--
 5 files changed, 12 insertions(+), 4 deletions(-)

Intervall-diff mot v1:
1:  224303c555 = 1:  c9131b23fd doc: config: terminate runaway lists
2:  a7e6b82c97 ! 2:  ca65211ea4 doc: config/sideband: fix typo in adoc markup
    @@ Metadata
     Author: Tuomas Ahola <taahol@utu.fi>
     
      ## Commit message ##
    -    doc: config/sideband: fix typo in adoc markup
    -
    -    Fix a simple typo in AsciiDoc markup.
    +    doc: config/sideband: fix description list delimiter
     
         Signed-off-by: Tuomas Ahola <taahol@utu.fi>
     
3:  7d0916a874 ! 3:  0341a4bde9 doc: git-config: escape erroneous adoc markup
    @@ Metadata
     Author: Tuomas Ahola <taahol@utu.fi>
     
      ## Commit message ##
    -    doc: git-config: escape erroneous adoc markup
    +    doc: git-config: escape erroneous highlight markup
     
         Paired octothorpes are used in AsciiDoc to mark highlighted text,
         <mark> being the equivalent HTML tag.  To use the symbol as a literal
    @@ Documentation/git-config.adoc: OPTIONS
      +
      If _<message>_ begins with one or more whitespaces followed
     -by "#", it is used as-is.  If it begins with "#", a space is
    -+by "\#", it is used as-is.  If it begins with "#", a space is
    ++by "\#", it is used as-is.  If it begins with "\#", a space is
      prepended before it is used.  Otherwise, a string " # " (a
      space followed by a hash followed by a space) is prepended
     -to it.  And the resulting string is placed immediately after

base-commit: 29bd7ed5127255713c1ac2f43b7c6f257d7b4594
-- 
2.30.2


^ permalink raw reply

* [PATCH v2 3/3] doc: git-config: escape erroneous highlight markup
From: Tuomas Ahola @ 2026-06-10 22:55 UTC (permalink / raw)
  To: git; +Cc: Kristoffer Haugsbakk, Junio C Hamano, Tuomas Ahola
In-Reply-To: <20260610225513.6269-1-taahol@utu.fi>

Paired octothorpes are used in AsciiDoc to mark highlighted text,
<mark> being the equivalent HTML tag.  To use the symbol as a literal
character, it can be escaped with a backslash.

Do so in git-config.adoc.

While at it, tweak the text slightly to make it scan better.

Signed-off-by: Tuomas Ahola <taahol@utu.fi>
---
 Documentation/git-config.adoc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-config.adoc b/Documentation/git-config.adoc
index 8439ce97df..e4af6cac68 100644
--- a/Documentation/git-config.adoc
+++ b/Documentation/git-config.adoc
@@ -119,10 +119,10 @@ OPTIONS
 	Append a comment at the end of new or modified lines.
 +
 If _<message>_ begins with one or more whitespaces followed
-by "#", it is used as-is.  If it begins with "#", a space is
+by "\#", it is used as-is.  If it begins with "\#", a space is
 prepended before it is used.  Otherwise, a string " # " (a
 space followed by a hash followed by a space) is prepended
-to it.  And the resulting string is placed immediately after
+to it.  The resulting string is placed immediately after
 the value defined for the variable.  The _<message>_ must
 not contain linefeed characters (no multi-line comments are
 permitted).
-- 
2.30.2


^ permalink raw reply related

* [PATCH v2 2/3] doc: config/sideband: fix description list delimiter
From: Tuomas Ahola @ 2026-06-10 22:55 UTC (permalink / raw)
  To: git; +Cc: Kristoffer Haugsbakk, Junio C Hamano, Tuomas Ahola
In-Reply-To: <20260610225513.6269-1-taahol@utu.fi>

Signed-off-by: Tuomas Ahola <taahol@utu.fi>
---
 Documentation/config/sideband.adoc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/config/sideband.adoc b/Documentation/config/sideband.adoc
index 96fade7f5f..06de0d5c07 100644
--- a/Documentation/config/sideband.adoc
+++ b/Documentation/config/sideband.adoc
@@ -9,7 +9,7 @@ sideband.allowControlCharacters::
 	`color`::
 		Allow ANSI color sequences, line feeds and horizontal tabs,
 		but mask all other control characters. This is the default.
-	`cursor:`:
+	`cursor`::
 		Allow control sequences that move the cursor. This is
 		disabled by default.
 	`erase`::
-- 
2.30.2


^ permalink raw reply related

* [PATCH v2 1/3] doc: config: terminate runaway lists
From: Tuomas Ahola @ 2026-06-10 22:55 UTC (permalink / raw)
  To: git; +Cc: Kristoffer Haugsbakk, Junio C Hamano, Tuomas Ahola
In-Reply-To: <20260610225513.6269-1-taahol@utu.fi>

There are many places in git-config(1) where paragraphs that should
logically come after a list are instead appended to the last item of
the list.  This is a well-documented quirk of AsciiDoc, and can be
mitigated by enclosing the list in an open block:

	--
	* first item
	* last item
	--
	+
	New paragraph after the list.

Fix the issue accordingly.

Signed-off-by: Tuomas Ahola <taahol@utu.fi>
---
 Documentation/config.adoc          | 4 +++-
 Documentation/config/promisor.adoc | 2 ++
 Documentation/config/safe.adoc     | 2 ++
 Documentation/git-config.adoc      | 2 ++
 4 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/Documentation/config.adoc b/Documentation/config.adoc
index dcea3c0c15..fc48c1c461 100644
--- a/Documentation/config.adoc
+++ b/Documentation/config.adoc
@@ -276,13 +276,15 @@ boolean::
        When a variable is said to take a boolean value, many
        synonyms are accepted for 'true' and 'false'; these are all
        case-insensitive.
-
++
+--
 	true;; Boolean true literals are `yes`, `on`, `true`,
 		and `1`.  Also, a variable defined without `= <value>`
 		is taken as true.
 
 	false;; Boolean false literals are `no`, `off`, `false`,
 		`0` and the empty string.
+--
 +
 When converting a value to its canonical form using the `--type=bool` type
 specifier, 'git config' will ensure that the output is "true" or
diff --git a/Documentation/config/promisor.adoc b/Documentation/config/promisor.adoc
index b0fa43b839..39af63dcb8 100644
--- a/Documentation/config/promisor.adoc
+++ b/Documentation/config/promisor.adoc
@@ -63,11 +63,13 @@ If one of these field names (e.g., "token") is being checked for an
 advertised promisor remote (e.g., "foo"), three conditions must be met
 for the check of this specific field to pass:
 +
+--
 1. The corresponding local configuration (e.g., `remote.foo.token`)
    must be set.
 2. The server must advertise the "token" field for remote "foo".
 3. The value of the locally configured `remote.foo.token` must exactly
    match the value advertised by the server for the "token" field.
+--
 +
 If any of these conditions is not met for any field name listed in
 `promisor.checkFields`, the advertised remote "foo" is rejected.
diff --git a/Documentation/config/safe.adoc b/Documentation/config/safe.adoc
index 2d45c98b12..5ae4476b24 100644
--- a/Documentation/config/safe.adoc
+++ b/Documentation/config/safe.adoc
@@ -2,10 +2,12 @@ safe.bareRepository::
 	Specifies which bare repositories Git will work with. The currently
 	supported values are:
 +
+--
 * `all`: Git works with all bare repositories. This is the default.
 * `explicit`: Git only works with bare repositories specified via
   the top-level `--git-dir` command-line option, or the `GIT_DIR`
   environment variable (see linkgit:git[1]).
+--
 +
 If you do not use bare repositories in your workflow, then it may be
 beneficial to set `safe.bareRepository` to `explicit` in your global
diff --git a/Documentation/git-config.adoc b/Documentation/git-config.adoc
index 00545b2054..8439ce97df 100644
--- a/Documentation/git-config.adoc
+++ b/Documentation/git-config.adoc
@@ -221,6 +221,7 @@ Use `--no-value` to unset _<pattern>_.
 +
 Valid `<type>`'s include:
 +
+--
 - 'bool': canonicalize values `true`, `yes`, `on`, and positive
   numbers as "true", and values `false`, `no`, `off` and `0` as
   "false".
@@ -239,6 +240,7 @@ Valid `<type>`'s include:
   escape sequence. When setting a value, a sanity-check is performed to ensure
   that the given value is canonicalize-able as an ANSI color, but it is written
   as-is.
+--
 +
 If the command is in `list` mode, then the `--type <type>` argument will apply
 to each listed config value. If the value does not successfully parse in that
-- 
2.30.2


^ permalink raw reply related

* Re: [PATCH 6/6] SubmittingPatches: note that trailer order matters
From: Junio C Hamano @ 2026-06-10 22:30 UTC (permalink / raw)
  To: kristofferhaugsbakk; +Cc: git, Kristoffer Haugsbakk
In-Reply-To: <trailer_order_matters.8f9@msgid.xyz>

kristofferhaugsbakk@fastmail.com writes:

> From: Kristoffer Haugsbakk <code@khaugsbakk.name>
>
> It matters where you put the s-o-b; it should be last. You are signing
> off on the patch as well as the whole message up to that point.
>
> This also makes it clear who added what:
>
>     Acked-by: The Reviewer <r@example.org>
>     Signed-off-by: The Contributor <c@example.org>
>     Acked-by: The (Late) Reviewer <late@example.org>
>     Signed-off-by: The Maintainer <m@example.org>
>
> The the first ack was added by the contributor and the second one was
> added by the maintainer.
>
> Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
> ---
>  Documentation/SubmittingPatches | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
> index 3d2e9ecfbb8..2045708bdf5 100644
> --- a/Documentation/SubmittingPatches
> +++ b/Documentation/SubmittingPatches
> @@ -490,6 +490,11 @@ particular are not used in this project.
>  Only capitalize the very first letter of the trailer, i.e. favor
>  `Signed-off-by:` over `Signed-Off-By:` and `Acked-by:` over `Acked-By:`.
>  
> +Note that these trailers should come before your `Signed-off-by:`
> +trailer. You are signing off to the patch as well as the message. This
> +also makes it clear who added trailers when multiple people have signed
> +off on a patch.

Perhaps first mention the underlying rule that they are added in the
order that helps us to understand the chronological order of events.
That would avoid giving a wrong impression that the nature of each
trailer keys determine the order of these lines.

Thanks.

^ permalink raw reply

* Re: [PATCH 7/7] treewide: drop USE_THE_REPOSITORY_VARIABLE
From: Justin Tobler @ 2026-06-10 22:26 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: git
In-Reply-To: <20260610-b4-pks-setup-drop-global-state-v1-7-5dff3eec8f06@pks.im>

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

* [PATCH 6/6] SubmittingPatches: note that trailer order matters
From: kristofferhaugsbakk @ 2026-06-10 22:22 UTC (permalink / raw)
  To: git; +Cc: Kristoffer Haugsbakk
In-Reply-To: <CV_SubPatches_trailers.8f3@msgid.xyz>

From: Kristoffer Haugsbakk <code@khaugsbakk.name>

It matters where you put the s-o-b; it should be last. You are signing
off on the patch as well as the whole message up to that point.

This also makes it clear who added what:

    Acked-by: The Reviewer <r@example.org>
    Signed-off-by: The Contributor <c@example.org>
    Acked-by: The (Late) Reviewer <late@example.org>
    Signed-off-by: The Maintainer <m@example.org>

The the first ack was added by the contributor and the second one was
added by the maintainer.

Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
---
 Documentation/SubmittingPatches | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 3d2e9ecfbb8..2045708bdf5 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -490,6 +490,11 @@ particular are not used in this project.
 Only capitalize the very first letter of the trailer, i.e. favor
 `Signed-off-by:` over `Signed-Off-By:` and `Acked-by:` over `Acked-By:`.
 
+Note that these trailers should come before your `Signed-off-by:`
+trailer. You are signing off to the patch as well as the message. This
+also makes it clear who added trailers when multiple people have signed
+off on a patch.
+
 [[ai]]
 === Use of Artificial Intelligence (AI)
 
-- 
2.54.0.22.g9e26862b904


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox