* [PATCH GSoC v14 13/13] cat-file: make remote-object-info allow-list dynamic
From: Pablo Sabater @ 2026-06-25 12:13 UTC (permalink / raw)
To: git
Cc: pabloosabaterr, chandrapratap3519, chriscool, eric.peijian,
gitster, jltobler, karthik.188, peff, toon
In-Reply-To: <20260625-ps-eric-work-rebase-v14-0-09f7ffe21a53@gmail.com>
The static allow-list in expand_atom() is hardcoded to only allow
"objectname" and "objectsize" for remote queries. This works because
up to this point all servers will either support object-info with name
and size or they do not support them at all, but we cannot expect that
in a future different servers with different git versions to have the
same object-info capabilities. Therefore, the allow_list needs to be
dynamic depending on what the server advertises.
The client will now:
1. Request the protocol option that the placeholder refers to (i.e.
"size" when "%(objectsize)").
2. Filters the request in fetch_object_info() dropping any option that
the server does not advertise.
3. After the fetching, the options that haven't been dropped are the ones
fetched and supported by the server, these supported options are
mapped and remote_allowed_atoms is populated with the placeholders.
4. expand_atom() checks remote_allowed_atoms with the same behaviour as
the static allow_list had.
Move object_info_options out of get_remote_info so the caller which has
data can select what options will be requested instead of requesting
always size.
Move batch_object_write() out so there will always be an output even if
all the placeholders are not supported by the server (returns an empty
line).
Include "type" in the object_info_options so once the server supports
it, the clients know already how to request it.
Mentored-by: Karthik Nayak <karthik.188@gmail.com>
Mentored-by: Chandra Pratap <chandrapratap3519@gmail.com>
Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com>
---
builtin/cat-file.c | 97 +++++++++++++++++++++++++++++++++++------------------
fetch-object-info.c | 20 +++++++++++
2 files changed, 84 insertions(+), 33 deletions(-)
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index ea3869f3ed..86e4f78eb6 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -338,13 +338,11 @@ struct expand_data {
* Flags about when an object info is being fetched from remote.
*/
unsigned is_remote:1;
-};
-#define EXPAND_DATA_INIT { .mode = S_IFINVALID, .type = OBJ_BAD }
-static const char *remote_object_info_atoms[] = {
- "objectname",
- "objectsize",
+ struct string_list remote_allowed_atoms;
};
+#define EXPAND_DATA_INIT { .mode = S_IFINVALID, .type = OBJ_BAD, \
+ .remote_allowed_atoms = STRING_LIST_INIT_NODUP }
static int is_atom(const char *atom, const char *s, int slen)
{
@@ -356,17 +354,11 @@ static int expand_atom(struct strbuf *sb, const char *atom, int len,
struct expand_data *data)
{
if (data->is_remote) {
- size_t i, allowed_nr = ARRAY_SIZE(remote_object_info_atoms);
- for (i = 0; i < allowed_nr; i++)
- if (is_atom(remote_object_info_atoms[i], atom, len))
+ size_t i;
+ for (i = 0; i < data->remote_allowed_atoms.nr; i++)
+ if (is_atom(data->remote_allowed_atoms.items[i].string, atom, len))
break;
-
- /*
- * On remote, skip unsupported atoms returning an empty sb,
- * honoring how for-each-ref handles known but inapplicable
- * atoms (e.g. %(tagger)).
- */
- if (i == allowed_nr)
+ if (i == data->remote_allowed_atoms.nr)
return 1;
}
@@ -680,12 +672,12 @@ static int get_remote_info(struct batch_options *opt,
int argc,
const char **argv,
struct object_info **remote_object_info,
- struct oid_array *object_info_oids)
+ struct oid_array *object_info_oids,
+ struct string_list *object_info_options)
{
int retval = 0;
struct remote *remote = NULL;
struct object_id oid;
- struct string_list object_info_options = STRING_LIST_INIT_NODUP;
struct transport *gtransport;
/*
@@ -734,15 +726,12 @@ static int get_remote_info(struct batch_options *opt,
gtransport->smart_options->object_info = 1;
gtransport->smart_options->object_info_oids = object_info_oids;
- string_list_append(&object_info_options, "size");
-
- if (object_info_options.nr > 0) {
- gtransport->smart_options->object_info_options = &object_info_options;
+ if (object_info_options->nr > 0) {
+ gtransport->smart_options->object_info_options = object_info_options;
gtransport->smart_options->object_info_data = *remote_object_info;
retval = transport_fetch_refs(gtransport, NULL);
}
cleanup:
- string_list_clear(&object_info_options, 0);
transport_disconnect(gtransport);
return retval;
}
@@ -828,6 +817,21 @@ static void parse_cmd_mailmap(struct batch_options *opt UNUSED,
load_mailmap();
}
+struct protocol_placeholder_entry {
+ const char *option;
+ const char *atom;
+};
+
+static const struct protocol_placeholder_entry remote_atom_map[] = {
+ {"size", "objectsize"},
+ {"type", "objecttype"},
+ /*
+ * Add new protocol options here. Even if the server doesn't support
+ * them the allow_list will drop them if the server doesn't advertise
+ * them.
+ */
+};
+
static void parse_cmd_remote_object_info(struct batch_options *opt,
const char *line, struct strbuf *output,
struct expand_data *data)
@@ -837,6 +841,7 @@ static void parse_cmd_remote_object_info(struct batch_options *opt,
char *line_to_split;
struct object_info *remote_object_info = NULL;
struct oid_array object_info_oids = OID_ARRAY_INIT;
+ struct string_list object_info_options = STRING_LIST_INIT_NODUP;
if (strlen(line) >= MAX_REMOTE_OBJ_INFO_LINE)
die(_("remote-object-info command too long"));
@@ -849,32 +854,57 @@ static void parse_cmd_remote_object_info(struct batch_options *opt,
die(_("remote-object-info supports at most %d objects"),
MAX_ALLOWED_OBJ_LIMIT);
+ if (data->info.sizep)
+ string_list_append(&object_info_options, "size");
+ if (data->info.typep)
+ string_list_append(&object_info_options, "type");
+
if (get_remote_info(opt, count, argv, &remote_object_info,
- &object_info_oids))
+ &object_info_oids, &object_info_options))
goto cleanup;
+ string_list_clear(&data->remote_allowed_atoms, 0);
+ string_list_append(&data->remote_allowed_atoms, "objectname");
+ for (size_t i = 0; i < ARRAY_SIZE(remote_atom_map); i++)
+ if (unsorted_string_list_has_string(&object_info_options, remote_atom_map[i].option))
+ string_list_append(&data->remote_allowed_atoms,
+ remote_atom_map[i].atom);
+
data->skip_object_info = 1;
for (size_t i = 0; i < object_info_oids.nr; i++) {
+ int found = 0;
data->oid = object_info_oids.oid[i];
+ /*
+ * When reaching here, it means remote-object-info can retrieve
+ * information from server without downloading them.
+ */
if (remote_object_info[i].sizep) {
- /*
- * When reaching here, it means remote-object-info can retrieve
- * information from server without downloading them.
- */
data->size = *remote_object_info[i].sizep;
- opt->batch_mode = BATCH_MODE_INFO;
- data->is_remote = 1;
- batch_object_write(argv[i + 1], output, opt, data, NULL, 0);
- data->is_remote = 0;
- } else {
- report_object_status(opt, oid_to_hex(&data->oid), &data->oid, "missing");
+ found = 1;
}
+
+ if (remote_object_info[i].typep) {
+ data->type = *remote_object_info[i].typep;
+ found = 1;
+ }
+
+ if (!found && object_info_options.nr > 0) {
+ report_object_status(opt, oid_to_hex(&data->oid),
+ &data->oid, "missing");
+ continue;
+ }
+
+ opt->batch_mode = BATCH_MODE_INFO;
+ data->is_remote = 1;
+ batch_object_write(argv[i + 1], output, opt, data, NULL, 0);
+ data->is_remote = 0;
}
data->skip_object_info = 0;
cleanup:
for (size_t i = 0; i < object_info_oids.nr; i++)
free_object_info_contents(&remote_object_info[i]);
+ string_list_clear(&object_info_options, 0);
free(line_to_split);
free(argv);
free(remote_object_info);
@@ -1190,6 +1220,7 @@ static int batch_objects(struct batch_options *opt)
cleanup:
strbuf_release(&input);
strbuf_release(&output);
+ string_list_clear(&data.remote_allowed_atoms, 0);
cfg->warn_on_object_refname_ambiguity = save_warning;
return retval;
}
diff --git a/fetch-object-info.c b/fetch-object-info.c
index 9c4ae9bd11..c6954bde5d 100644
--- a/fetch-object-info.c
+++ b/fetch-object-info.c
@@ -39,6 +39,26 @@ int fetch_object_info(const enum protocol_version version, struct object_info_ar
case protocol_v2:
if (!server_supports_v2("object-info"))
die(_("object-info capability is not enabled on the server"));
+ /*
+ * When removing an element from the list it gets swapped by the
+ * last element, iterate backwards to prevent elements skipping
+ * evaluation.
+ *
+ * object_info_options->nr can be safely casted without overflow
+ * beacuse the number of options is a small known number (the
+ * supported placeholders which currently are size and type).
+ */
+ for (int i = (int)args->object_info_options->nr - 1; i >= 0; i--)
+ if (!server_supports_feature("object-info",
+ args->object_info_options->items[i].string, 0))
+ unsorted_string_list_delete_item(args->object_info_options, i, 0);
+ /*
+ * If no options are left after the filtering, avoid unnecessary
+ * request to the server.
+ */
+ if (!args->object_info_options->nr)
+ return 0;
+
send_object_info_request(fd_out, args);
break;
case protocol_v1:
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v2 2/2] push: suggest <remote> <branch> for a slash slip
From: Junio C Hamano @ 2026-06-25 13:12 UTC (permalink / raw)
To: Harald Nordgren; +Cc: Harald Nordgren via GitGitGadget, git
In-Reply-To: <CAHwyqnWaY9bHX1ZvuMTDMGGBG8f+_tbhcPycOYbWAcW23ZAoPg@mail.gmail.com>
Harald Nordgren <haraldnordgren@gmail.com> writes:
> than five GitHub CI tests are failing (with the 4GB warning) and tests
> are passing locally, then I can submit" which is admittedly not a good
> heuristic.
This particular one you would have caught if you try-merged your
topic to 'seen' and ran test locally. That is how I found it before
pushing the integration result out.
^ permalink raw reply
* Re: [PATCH v6 09/10] builtin/history: split handling of ref updates into two phases
From: Christian Couder @ 2026-06-25 13:37 UTC (permalink / raw)
To: Patrick Steinhardt
Cc: git, Pablo Sabater, Junio C Hamano, Kristoffer Haugsbakk,
Phillip Wood
In-Reply-To: <20260615-b4-pks-history-drop-v6-9-2e329e536d78@pks.im>
On Mon, Jun 15, 2026 at 3:56 PM Patrick Steinhardt <ps@pks.im> wrote:
> @@ -414,14 +389,43 @@ static int handle_reference_updates(struct rev_info *revs,
> !detached_head)
> continue;
>
> + ALLOC_GROW(result->updates, result->updates_nr + 1, result->updates_alloc);
> + result->updates[result->updates_nr].refname = xstrdup(decoration->name);
> + result->updates[result->updates_nr].old_oid = original->object.oid;
> + result->updates[result->updates_nr].new_oid = rewritten->object.oid;
> + result->updates_nr++;
It looks like this duplicates what replay_result_queue_update() from
replay.c does.
> + }
^ permalink raw reply
* Re: [PATCH v6 10/10] builtin/history: implement "drop" subcommand
From: Christian Couder @ 2026-06-25 13:51 UTC (permalink / raw)
To: Patrick Steinhardt
Cc: git, Pablo Sabater, Junio C Hamano, Kristoffer Haugsbakk,
Phillip Wood
In-Reply-To: <20260615-b4-pks-history-drop-v6-10-2e329e536d78@pks.im>
On Mon, Jun 15, 2026 at 3:55 PM Patrick Steinhardt <ps@pks.im> wrote:
> + /*
> + * If HEAD will move as a result of the rewrite then we'll have to
> + * merge in the changes into the worktree and index. This merge can of
> + * course conflict, which will cause the whole operation to abort.
> + *
> + * If we had already updated the refs at that point then we'd have an
> + * inconsistent repository state. So we first perform a dry-run merge
> + * here before updating refs.
> + */
> + if (!is_bare_repository()) {
When your ps/setup-drop-global-state series is merged, this will look like:
if (!is_bare_repository(repo)) {
which is nicer.
So except for perhaps the replay_result_queue_update() duplication,
the series looks great to me.
Thanks.
^ permalink raw reply
* Re: [PATCH v6 00/11] refs: fix "onbranch" conditions
From: Justin Tobler @ 2026-06-25 15:06 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git, Karthik Nayak, Jeff King
In-Reply-To: <20260625-b4-pks-refs-avoid-chdir-notify-reparent-v6-0-41fbca3cf5e3@pks.im>
On 26/06/25 11:19AM, Patrick Steinhardt wrote:
> Changes in v6:
> - Drop redundant condition when setting the default for
> "core.logallrefupdates".
> - Leave breakcrumb for why we lazy-load write options for the "files"
> backend.
> - Fix commit message typo.
Thanks. This version of the series looks good to me.
-Justin
^ permalink raw reply
* [PATCH v4] doc: clarify --follow and log.follow for git log
From: Tamir Duberstein @ 2026-06-25 16:01 UTC (permalink / raw)
To: git; +Cc: Jean-Noël Avila, Junio C Hamano, Miklos Vajna,
Tamir Duberstein
In-Reply-To: <20260510-document-log-no-follow-v3-1-d6d3368c64bb@gmail.com>
aebbcf5797 (diff: accept --no-follow option, 2012-09-21) added the
--no-follow option, but git-log(1) only documents --follow.
Document --no-follow alongside --follow, and note that it overrides
the log.follow configuration.
Signed-off-by: Tamir Duberstein <tamird@gmail.com>
---
Changes in v4:
- Limit the patch to `--no-follow` and its `log.follow` override; leave
the existing `--follow` limitations unchanged.
- Link to v3: https://patch.msgid.link/20260510-document-log-no-follow-v3-1-d6d3368c64bb@gmail.com
This conflicts textually with `mv/log-follow-mergy` in `next`. Keep that
topic's shorter limitation text and append the `--no-follow` override.
Changes in v3:
- Retitle the patch to avoid the awkward `doc: git-log:` subject.
- List `--no-follow` before `--follow`.
- Clarify that `--follow` follows a single file across renames, even
though the option is accepted with exactly one pathspec.
- Document the directory-pathspec case: directory renames are not
followed, but `--follow` still uses file-follow traversal, disabling
normal pathspec pruning and possibly changing which commits,
especially merges, are shown.
- Link to v2: https://patch.msgid.link/20260507-document-log-no-follow-v2-1-ee7bcbbe612f@gmail.com
Changes in v2:
- Document --follow as limited to a single pathspec, not a single file.
- Adjust the log.follow documentation to use the same wording.
- Link to v1: https://patch.msgid.link/20260507-document-log-no-follow-v1-1-46ce02490eba@gmail.com
---
Documentation/config/log.adoc | 2 +-
Documentation/git-log.adoc | 5 ++++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/Documentation/config/log.adoc b/Documentation/config/log.adoc
index f20cc25cd7..58147dff9b 100644
--- a/Documentation/config/log.adoc
+++ b/Documentation/config/log.adoc
@@ -54,7 +54,7 @@ This is the same as the `--decorate` option of the `git log`.
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.
+ on non-linear history. This can be overridden by `--no-follow`.
`log.graphColors`::
A list of colors, separated by commas, that can be used to draw
diff --git a/Documentation/git-log.adoc b/Documentation/git-log.adoc
index fb3ac11283..64fbec0f57 100644
--- a/Documentation/git-log.adoc
+++ b/Documentation/git-log.adoc
@@ -27,9 +27,12 @@ each commit introduces are shown.
OPTIONS
-------
+`--no-follow`::
`--follow`::
Continue listing the history of a file beyond renames
- (works only for a single file).
+ (works only for a single file). `--no-follow` disables this
+ behavior, including when it was enabled by the
+ `log.follow` configuration variable.
`--no-decorate`::
`--decorate[=(short|full|auto|no)]`::
---
base-commit: ab776a62a78576513ee121424adb19597fbb7613
change-id: 20260507-document-log-no-follow-72c33dc15017
Best regards,
--
Tamir Duberstein <tamird@gmail.com>
^ permalink raw reply related
* [PATCH v1 0/2] environment: move excludes_file into repo_config_values
From: Tian Yuchen @ 2026-06-25 16:18 UTC (permalink / raw)
To: git
Cc: cirnovskyv, Tian Yuchen, Christian Couder, Ayush Chandekar,
Olamide Caleb Bello
This series continues the libification effort by migrating the global
string variable 'excludes_file' into 'struct repo_config_values'. Since
this is a dynamically allocated variable, the migration requires proper
heap memory management.
The series is structured in two commits:
- Abstract the XDG fallback lazy-loading logic out of dir.c into a proper
getter.
- Move the variable into the struct and introducs 'repo_config_values_clear()'.
Note on Submodules: A temporary shield 'if (repo != the_repository)' is
included in both the getter and the clear function. This prevents
uninitialized submodules from triggering the BUG() assertion.
(Inspiration: [1])
Thanks.
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>
[1] https://lore.kernel.org/git/c95a7730-7b14-4be0-a4e4-861b2f5430ea@gmail.com/
Tian Yuchen (2):
dir: encapsulate excludes_file lazy-load
environment: move excludes_file into repo_config_values
dir.c | 4 ++--
environment.c | 29 ++++++++++++++++++++++++++---
environment.h | 14 +++++++++++++-
repository.c | 1 +
4 files changed, 42 insertions(+), 6 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH v1 2/2] environment: move excludes_file into repo_config_values
From: Tian Yuchen @ 2026-06-25 16:18 UTC (permalink / raw)
To: git
Cc: cirnovskyv, Tian Yuchen, Christian Couder, Ayush Chandekar,
Olamide Caleb Bello
In-Reply-To: <20260625161845.7543-1-cat@malon.dev>
Continue the libification effor by moving the 'excludes_file' global
variable into 'struct repo_config_values'.
Since 'excludes_file' is a dynamically allocated string (char *), it
requires proper memory management. Introduce repo_config_values_clear()
to safely free the heap memory when repository instance is destroyed.
Note: 'if (repo != the_repository)' fallback logic is temporarily added
in both the getter and the clear function. This prevents calling
repo_config_values() on uninitialized submodules, which triggers BUG().
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>
---
environment.c | 28 ++++++++++++++++++++++------
environment.h | 15 +++++++++++----
repository.c | 1 +
3 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/environment.c b/environment.c
index 8efcaeafa6..e1c7ed178a 100644
--- a/environment.c
+++ b/environment.c
@@ -57,7 +57,6 @@ enum fsync_method fsync_method = FSYNC_METHOD_DEFAULT;
enum fsync_component fsync_components = FSYNC_COMPONENTS_DEFAULT;
char *editor_program;
char *askpass_program;
-char *excludes_file;
enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
enum eol core_eol = EOL_UNSET;
int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;
@@ -136,9 +135,13 @@ int is_bare_repository(void)
const char *repo_excludes_file(struct repository *repo)
{
- if (!excludes_file)
- excludes_file = xdg_config_home("ignore");
- return excludes_file;
+ if (!repo || !repo->initialized || repo != the_repository)
+ return NULL;
+
+ if (!repo_config_values(repo)->excludes_file)
+ repo_config_values(repo)->excludes_file = xdg_config_home("ignore");
+
+ return repo_config_values(repo)->excludes_file;
}
int have_git_dir(void)
@@ -468,8 +471,8 @@ int git_default_core_config(const char *var, const char *value,
}
if (!strcmp(var, "core.excludesfile")) {
- FREE_AND_NULL(excludes_file);
- return git_config_pathname(&excludes_file, var, value);
+ FREE_AND_NULL(cfg->excludes_file);
+ return git_config_pathname(&cfg->excludes_file, var, value);
}
if (!strcmp(var, "core.whitespace")) {
@@ -733,3 +736,16 @@ void repo_config_values_init(struct repo_config_values *cfg)
cfg->sparse_expect_files_outside_of_patterns = 0;
cfg->warn_on_object_refname_ambiguity = 1;
}
+
+void repo_config_values_clear(struct repository *repo)
+{
+ struct repo_config_values *cfg;
+
+ if (repo != the_repository)
+ return;
+
+ cfg = repo_config_values(repo);
+ if (!cfg)
+ return;
+ FREE_AND_NULL(cfg->excludes_file);
+}
diff --git a/environment.h b/environment.h
index 52d531e4ea..2839913551 100644
--- a/environment.h
+++ b/environment.h
@@ -98,6 +98,7 @@ struct repo_config_values {
int precomposed_unicode;
int core_sparse_checkout_cone;
int warn_on_object_refname_ambiguity;
+ char *excludes_file;
/* section "sparse" config values */
int sparse_expect_files_outside_of_patterns;
@@ -133,13 +134,20 @@ 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);
-/*
- * TODO: This still relies on the global state.
- */
const char *repo_excludes_file(struct repository *repo);
void repo_config_values_init(struct repo_config_values *cfg);
+/*
+ * Frees memory allocated for dynamically loaded configuration values
+ * inside `repo_config_values`.
+ *
+ * Note: `excludes_file` is currently the only heap-allocated field in
+ * this struct. As other dynamically allocated variables are migrated,
+ * their FREE_AND_NULL() calls should be appended here.
+ */
+void repo_config_values_clear(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
@@ -213,7 +221,6 @@ extern char *git_log_output_encoding;
extern char *editor_program;
extern char *askpass_program;
-extern char *excludes_file;
/*
* The character that begins a commented line in user-editable file
diff --git a/repository.c b/repository.c
index 187dd471c4..b31f1b7852 100644
--- a/repository.c
+++ b/repository.c
@@ -388,6 +388,7 @@ void repo_clear(struct repository *repo)
FREE_AND_NULL(repo->parsed_objects);
repo_settings_clear(repo);
+ repo_config_values_clear(repo);
if (repo->config) {
git_configset_clear(repo->config);
--
2.43.0
^ permalink raw reply related
* [PATCH v1 1/2] dir: encapsulate excludes_file lazy-load
From: Tian Yuchen @ 2026-06-25 16:18 UTC (permalink / raw)
To: git
Cc: cirnovskyv, Tian Yuchen, Christian Couder, Ayush Chandekar,
Olamide Caleb Bello
In-Reply-To: <20260625161845.7543-1-cat@malon.dev>
The global variable 'excludes_file' is used to track the path to the
global ignore file, 'core.excludesfile'. If this variable is NULL,
setup_standard_excludes() in dir.c forcefully evaluates and assigns
the XDG default path to it.
Introduce repo_excludes_file() as a getter to encapsulate this
lazy-loading logic. This prepares the variable to be safely moved
into 'struct repo_config_values' in the subsequent commit.
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>
---
dir.c | 4 ++--
environment.c | 7 +++++++
environment.h | 5 +++++
3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/dir.c b/dir.c
index 7a73690fbc..4f87a52b3c 100644
--- a/dir.c
+++ b/dir.c
@@ -3481,11 +3481,11 @@ static GIT_PATH_FUNC(git_path_info_exclude, "info/exclude")
void setup_standard_excludes(struct dir_struct *dir)
{
+ const char *excludes_file = repo_excludes_file(the_repository);
+
dir->exclude_per_dir = ".gitignore";
/* core.excludesfile defaulting to $XDG_CONFIG_HOME/git/ignore */
- if (!excludes_file)
- excludes_file = xdg_config_home("ignore");
if (excludes_file && !access_or_warn(excludes_file, R_OK, 0))
add_patterns_from_file_1(dir, excludes_file,
dir->untracked ? &dir->internal.ss_excludes_file : NULL);
diff --git a/environment.c b/environment.c
index ba2c60103f..8efcaeafa6 100644
--- a/environment.c
+++ b/environment.c
@@ -134,6 +134,13 @@ int is_bare_repository(void)
return is_bare_repository_cfg && !repo_get_work_tree(the_repository);
}
+const char *repo_excludes_file(struct repository *repo)
+{
+ if (!excludes_file)
+ excludes_file = xdg_config_home("ignore");
+ return excludes_file;
+}
+
int have_git_dir(void)
{
return startup_info->have_repository
diff --git a/environment.h b/environment.h
index 6f18286955..52d531e4ea 100644
--- a/environment.h
+++ b/environment.h
@@ -133,6 +133,11 @@ 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);
+/*
+ * TODO: This still relies on the global state.
+ */
+const char *repo_excludes_file(struct repository *repo);
+
void repo_config_values_init(struct repo_config_values *cfg);
/*
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v4] doc: clarify --follow and log.follow for git log
From: Junio C Hamano @ 2026-06-25 17:23 UTC (permalink / raw)
To: Tamir Duberstein; +Cc: git, Jean-Noël Avila, Miklos Vajna
In-Reply-To: <20260625-document-log-no-follow-v4-1-9bb233248b8f@gmail.com>
Tamir Duberstein <tamird@gmail.com> writes:
> aebbcf5797 (diff: accept --no-follow option, 2012-09-21) added the
> --no-follow option, but git-log(1) only documents --follow.
>
> Document --no-follow alongside --follow, and note that it overrides
> the log.follow configuration.
>
> Signed-off-by: Tamir Duberstein <tamird@gmail.com>
> ---
> Changes in v4:
> - Limit the patch to `--no-follow` and its `log.follow` override; leave
> the existing `--follow` limitations unchanged.
> - Link to v3: https://patch.msgid.link/20260510-document-log-no-follow-v3-1-d6d3368c64bb@gmail.com
OK.
> Changes in v3:
> - List `--no-follow` before `--follow`.
Ah, I think I misread the patch and its preimage while reviewing v2
and I didn't notice my mistake when you sent v3. Sorry.
I somehow thought that the original before the patch was
--follow::
... description of follow here ...
--no-follow::
... description of no-follow here ..
and I thought the patch was doing
--follow::
--no-follow::
... combined description ...
and commented that it was a good change. I didn't mean to comment
which between --no-foo and --foo should come first (looking at the
output of "git grep -C1 -E -e '^`?--no-'", I think --foo should come
before --no-foo, especially when --foo does not take any value, but
it seems there are many instances that list the negated form first).
As the existing text has mixture of --foo before and after --no-foo
let's not worry about which one should come first, but if we have a
chance to redo this patch, I would actually prefer to see --follow
comes before --no-follow.
> diff --git a/Documentation/config/log.adoc b/Documentation/config/log.adoc
> index f20cc25cd7..58147dff9b 100644
> --- a/Documentation/config/log.adoc
> +++ b/Documentation/config/log.adoc
> @@ -54,7 +54,7 @@ This is the same as the `--decorate` option of the `git log`.
> 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.
> + on non-linear history. This can be overridden by `--no-follow`.
OK. This is the usual "command line options override configured
default" in play.
> diff --git a/Documentation/git-log.adoc b/Documentation/git-log.adoc
> index fb3ac11283..64fbec0f57 100644
> --- a/Documentation/git-log.adoc
> +++ b/Documentation/git-log.adoc
> @@ -27,9 +27,12 @@ each commit introduces are shown.
> OPTIONS
> -------
>
> +`--no-follow`::
> `--follow`::
> Continue listing the history of a file beyond renames
> - (works only for a single file).
> + (works only for a single file). `--no-follow` disables this
> + behavior, including when it was enabled by the
> + `log.follow` configuration variable.
Ditto, but I am not sure if we want to sprinkle the "command line
overrides configured defaults" all over the place. The description
of --[no-]decorate below says
default to configuration value of `log.decorate` if
configured, otherwise `auto`.
which silently assumes that the readers _know_ that command line
--no-decorate overrides that default. And I think it is a sensible
assumption to make.
So, while the patch may have meant well, I think this part should
actually become a single liner that adds `--no-follow`:: and nothing
else. The changes to config/log.adoc should probably be kept.
Thanks.
^ permalink raw reply
* [PATCH] history: close COMMIT_EDITMSG before launching the editor
From: Johannes Schindelin via GitGitGadget @ 2026-06-25 18:33 UTC (permalink / raw)
To: git; +Cc: Patrick Steinhardt, Johannes Schindelin, Johannes Schindelin
From: Johannes Schindelin <johannes.schindelin@gmx.de>
The `git history reword` and `git history fixup` subcommands prepare the
commit message by writing it to COMMIT_EDITMSG and then opening that same
file a second time, in append mode, through `wt_status`'s `fp` field to
append the status information. That second handle is never closed before
`launch_editor()` runs, so the editor is started while git still holds
the file open.
Everywhere this leaks a file descriptor, but on Windows it is outright
broken: a process cannot replace a file that another process keeps open,
so an editor that rewrites COMMIT_EDITMSG by creating a fresh file in its
place fails. This surfaced while running Git for Windows' test suite with
BusyBox' `ash` as the POSIX shell: the fake editor's `cp message "$1"`
aborts with "cp: can't create '.../COMMIT_EDITMSG': File exists" (MSYS2's
coreutils `cp` hides the problem via its POSIX unlink emulation, BusyBox'
native `cp` does not), making t3451-history-reword and t3453-history-fixup
fail wholesale.
Close the handle once the status has been written, before handing the
file off to the editor.
Assisted-by: Opus 4.8
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
history: close COMMIT_EDITMSG before launching the editor
I noticed this problem while trying to whip MinGit-BusyBox into a better
shape during the -rc phase. Technically, this is not a fix for a
regression during the v2.55.0 period, but I figured it'd be better to
send it now anyway than to forget about sending it after v2.55.0 is
released.
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2158%2Fdscho%2Ffix-fd-leak-in-history-reword-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2158/dscho/fix-fd-leak-in-history-reword-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/2158
builtin/history.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/builtin/history.c b/builtin/history.c
index 9526938085..4a5d9192f3 100644
--- a/builtin/history.c
+++ b/builtin/history.c
@@ -74,6 +74,14 @@ static int fill_commit_message(struct repository *repo,
wt_status_collect_free_buffers(&s);
string_list_clear_func(&s.change, change_data_free);
+ /*
+ * Close the handle before launching the editor: on Windows an open
+ * handle would prevent the editor from replacing the file (e.g.
+ * BusyBox' `ash` cannot overwrite a file that another process keeps
+ * open), and leaving it open leaks the descriptor everywhere else.
+ */
+ fclose(s.fp);
+
strbuf_reset(out);
if (launch_editor(path, out, NULL)) {
fprintf(stderr, _("Aborting commit as launching the editor failed.\n"));
base-commit: 94f057755b7941b321fd11fec1b2e3ca5313a4e0
--
gitgitgadget
^ permalink raw reply related
* Re: [PATCH] t4216: fix no-op test that breaks TAP output
From: Todd Zullinger @ 2026-06-25 18:51 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: Junio C Hamano, Taylor Blau, git, Jeff King
In-Reply-To: <ajjBmi39IFJW5p5V@pks.im>
Patrick Steinhardt wrote:
> On Fri, Jun 19, 2026 at 09:29:44AM -0700, Junio C Hamano wrote:
>> Taylor Blau <me@ttaylorr.com> writes:
>>
>>> Given this and the above, I would probably err on the side of
>>> designating this as 'test_lazy_prereq' or otherwise silencing the output
>>> of 'test_cmp' so that this does not taint the TAP output.
>>
>> We can argue the merit and demerit with a good log message. The
>> central issue at hand is how precious 52a9 in the script lost by
>> this patch is (in other words, are we checking more than "is our
>> char signed or unsigned?").
>
> Ultimately, I don't mind much which way we go. But if we want to retain
> this, would you mind sending a rewritten v2, Taylor? I feel like you're
> in a better position to argue why we should retain it.
Is this something which can be merged before 2.55.0 final?
It's certainly not a grave issue, but it is a new test
failure for anyone who diligently runs the test suite on
many (most?) non-x86 architectures. It seems a shame to
punish those folks. :)
FWIW, Tested-by: Todd Zullinger <tmz@pobox.com>
I tested the earlier test_lazy_prereq version as well.
--
Todd
^ permalink raw reply
* [PATCH] gpg-interface: still print ssh signatures when allowed signers file is not set
From: Grayson Tinker @ 2026-06-25 19:43 UTC (permalink / raw)
To: git
Cc: Grayson Tinker, Junio C Hamano, Patrick Steinhardt, Elijah Newren,
Fabian Stelzer, Jeff King, René Scharfe
"show-signature" errors when the allowed signers file is not configured,
which means that the user can't see the key that the ref was signed with
without creating and configuring the file. Change the logic so that the file
is only used when configured, and so the signature status is always displayed.
Example of previous output:
```
error: gpg.ssh.allowedSignersFile needs to be configured and exist for ssh signature verification
commit b437db5ddc38ebda223bbae2087eee90a7b1c6e2 (HEAD -> master)
No signature
Author: Grayson Tinker <graysontinker@gmail.com>
```
Example of new output:
```
commit b437db5ddc38ebda223bbae2087eee90a7b1c6e2 (HEAD -> master)
hint: Configure gpg.ssh.allowedSignersFile for automatic principal matching
Good "git" signature with ED25519-SK key SHA256:yTU4KFs/g6MY7biDSlVStB63Gi1rCKg7dOFDXbe0yuw
Author: Grayson Tinker <graysontinker@gmail.com>
```
Signed-off-by: Grayson Tinker <graysontinker@gmail.com>
---
gpg-interface.c | 42 +++++++++++++++++++++++-------------------
1 file changed, 23 insertions(+), 19 deletions(-)
diff --git a/gpg-interface.c b/gpg-interface.c
index dafd5371fa..ef3e1a0aa0 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -1,6 +1,7 @@
#define USE_THE_REPOSITORY_VARIABLE
#include "git-compat-util.h"
+#include "advice.h"
#include "commit.h"
#include "config.h"
#include "date.h"
@@ -480,11 +481,6 @@ static int verify_ssh_signed_buffer(struct signature_check *sigc,
.local = 1,
};
- if (!ssh_allowed_signers) {
- error(_("gpg.ssh.allowedSignersFile needs to be configured and exist for ssh signature verification"));
- return -1;
- }
-
buffer_file = mks_tempfile_t(".git_vtag_tmpXXXXXX");
if (!buffer_file)
return error_errno(_("could not create temporary file"));
@@ -500,22 +496,26 @@ static int verify_ssh_signed_buffer(struct signature_check *sigc,
strbuf_addf(&verify_time, "-Overify-time=%s",
show_date(sigc->payload_timestamp, 0, verify_date_mode));
- /* Find the principal from the signers */
- strvec_pushl(&ssh_keygen.args, fmt->program,
- "-Y", "find-principals",
- "-f", ssh_allowed_signers,
- "-s", buffer_file->filename.buf,
- verify_time.buf,
- NULL);
- ret = pipe_command(&ssh_keygen, NULL, 0, &ssh_principals_out, 0,
- &ssh_principals_err, 0);
- if (ret && strstr(ssh_principals_err.buf, "usage:")) {
- error(_("ssh-keygen -Y find-principals/verify is needed for ssh signature verification (available in openssh version 8.2p1+)"));
- goto out;
+ if (ssh_allowed_signers) {
+ /* Find the principal from the signers */
+ strvec_pushl(&ssh_keygen.args, fmt->program,
+ "-Y", "find-principals",
+ "-f", ssh_allowed_signers,
+ "-s", buffer_file->filename.buf,
+ verify_time.buf,
+ NULL);
+ ret = pipe_command(&ssh_keygen, NULL, 0, &ssh_principals_out, 0,
+ &ssh_principals_err, 0);
+ if (ret && strstr(ssh_principals_err.buf, "usage:")) {
+ error(_("ssh-keygen -Y find-principals/verify is needed for ssh signature verification (available in openssh version 8.2p1+)"));
+ goto out;
+ }
}
- if (ret || !ssh_principals_out.len) {
+
+ if (!ssh_allowed_signers || ret || !ssh_principals_out.len) {
/*
- * We did not find a matching principal in the allowedSigners
+ * We did not find a matching principal in the allowedSigners,
+ * or no allowedSigners file was configured
* Check without validation
*/
child_process_init(&ssh_keygen);
@@ -528,6 +528,10 @@ static int verify_ssh_signed_buffer(struct signature_check *sigc,
pipe_command(&ssh_keygen, sigc->payload, sigc->payload_len,
&ssh_keygen_out, 0, &ssh_keygen_err, 0);
+ if (!ssh_allowed_signers) {
+ advise(_("Configure gpg.ssh.allowedSignersFile for automatic principal matching\n"));
+ }
+
/*
* Fail on unknown keys
* we still call check-novalidate to display the signature info
--
2.54.0
^ permalink raw reply related
* Re* [PATCH] history: close COMMIT_EDITMSG before launching the editor
From: Junio C Hamano @ 2026-06-25 20:06 UTC (permalink / raw)
To: Johannes Schindelin via GitGitGadget
Cc: git, Patrick Steinhardt, Johannes Schindelin
In-Reply-To: <pull.2158.git.1782412427801.gitgitgadget@gmail.com>
"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
writes:
> Close the handle once the status has been written, before handing the
> file off to the editor.
>
> Assisted-by: Opus 4.8
Do we even need this?
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
> history: close COMMIT_EDITMSG before launching the editor
>
> I noticed this problem while trying to whip MinGit-BusyBox into a better
> shape during the -rc phase. Technically, this is not a fix for a
> regression during the v2.55.0 period, but I figured it'd be better to
> send it now anyway than to forget about sending it after v2.55.0 is
> released.
>
> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2158%2Fdscho%2Ffix-fd-leak-in-history-reword-v1
> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2158/dscho/fix-fd-leak-in-history-reword-v1
> Pull-Request: https://github.com/gitgitgadget/git/pull/2158
>
> builtin/history.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/builtin/history.c b/builtin/history.c
> index 9526938085..4a5d9192f3 100644
> --- a/builtin/history.c
> +++ b/builtin/history.c
> @@ -74,6 +74,14 @@ static int fill_commit_message(struct repository *repo,
> wt_status_collect_free_buffers(&s);
> string_list_clear_func(&s.change, change_data_free);
>
> + /*
> + * Close the handle before launching the editor: on Windows an open
> + * handle would prevent the editor from replacing the file (e.g.
> + * BusyBox' `ash` cannot overwrite a file that another process keeps
> + * open), and leaving it open leaks the descriptor everywhere else.
> + */
> + fclose(s.fp);
> +
> strbuf_reset(out);
> if (launch_editor(path, out, NULL)) {
> fprintf(stderr, _("Aborting commit as launching the editor failed.\n"));
The function is extremely sloppy beyond words X-<. Thanks for
taking the first step to clean it up.
* It calls git_path_commit_editmsg() to obtain a constant pathname
into "const char *path", but then the part that leads to this
file stream leak does not even use that "path" constant. It
makes two independent calls to git_path_commit_editmsg()!
* The function first calls write_file_buf() to the file, which is a
convenience function when you have something you need to write
upfront and just want to write it and be done with it.
* And then the unclosed file stream you just fixed.
What is surprising is that all of this was created in a single
commit. I suspected that this part that does fopen() to leak the
file stream was a later addition than the initial write_file_buf(),
which should have been critiqued with "once you want to do your
custom writing that is more than "I have this block of memory, write
it into file", you should rewrite write_file_buf() call and roll it
into your own custom writing", but that is not the case.
So taking the opportunity to clean things up, how about doing it
this way intead?
----- >8 ---------- >8 ---------- >8 -----
Subject: [PATCH] history: streamline message preparation and plug file stream leak
An early part of fill_commit_mmessage() function uses write_file_buf()
to write out what was prepared in a strbuf, which is primarily meant
for use by callers that have their own message prepared fully and
called as the last thing to flush it to the destination file.
However, the function then opens a file stream in append mode to
further write into it. It may have been understandable if this was
a later addition, but it seems it came from a single commit,
d205234c (builtin/history: implement "reword" subcommand,
2026-01-13), which is somewhat puzzling, but anyway...
Just open the file stream upfront for writing, write the message
the function has in the strbuf, and then keep writing whatever it
wants to write to the same open file stream.
And do not forget to close the stream. We are about to pass the
resulting file to an external editor, and on some systems, notably
Windows, you are not supposed to keep a file open while expecting
another program to access it.
Diagnosed-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin/history.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/builtin/history.c b/builtin/history.c
index 8dcb9a6046..a882ad82e5 100644
--- a/builtin/history.c
+++ b/builtin/history.c
@@ -41,11 +41,6 @@ static int fill_commit_message(struct repository *repo,
" empty message aborts the commit.\n");
struct wt_status s;
- strbuf_addstr(out, default_message);
- strbuf_addch(out, '\n');
- strbuf_commented_addf(out, comment_line_str, hint, action, comment_line_str);
- write_file_buf(path, out->buf, out->len);
-
wt_status_prepare(repo, &s);
FREE_AND_NULL(s.branch);
s.ahead_behind_flags = AHEAD_BEHIND_QUICK;
@@ -57,14 +52,20 @@ static int fill_commit_message(struct repository *repo,
s.whence = FROM_COMMIT;
s.committable = 1;
- s.fp = fopen(git_path_commit_editmsg(), "a");
+ s.fp = fopen(path, "w");
if (!s.fp)
- return error_errno(_("could not open '%s'"), git_path_commit_editmsg());
+ return error_errno(_("could not open '%s'"), path);
+
+ strbuf_addstr(out, default_message);
+ strbuf_addch(out, '\n');
+ strbuf_commented_addf(out, comment_line_str, hint, action, comment_line_str);
+ fwrite(out.buf, 1, out.len, s.fp);
wt_status_collect_changes_trees(&s, old_tree, new_tree);
wt_status_print(&s);
wt_status_collect_free_buffers(&s);
string_list_clear_func(&s.change, change_data_free);
+ fclose(s.fp);
strbuf_reset(out);
if (launch_editor(path, out, NULL)) {
--
2.55.0-rc2-165-g3249676ba5
^ permalink raw reply related
* Re: Re* [PATCH] history: close COMMIT_EDITMSG before launching the editor
From: Junio C Hamano @ 2026-06-25 20:12 UTC (permalink / raw)
To: Johannes Schindelin via GitGitGadget
Cc: git, Patrick Steinhardt, Johannes Schindelin
In-Reply-To: <xmqqh5mqfkpv.fsf@gitster.g>
Junio C Hamano <gitster@pobox.com> writes:
Of course, this should be ...
> + fwrite(out.buf, 1, out.len, s.fp);
...
fwrite(out->buf, 1, out->len, s.fp);
^ permalink raw reply
* Re: [PATCH] t4216: fix no-op test that breaks TAP output
From: Junio C Hamano @ 2026-06-25 20:17 UTC (permalink / raw)
To: Todd Zullinger; +Cc: Patrick Steinhardt, Taylor Blau, git, Jeff King
In-Reply-To: <20260625185112.jjH0K9LI@teonanacatl.net>
Todd Zullinger <tmz@pobox.com> writes:
> Patrick Steinhardt wrote:
>> On Fri, Jun 19, 2026 at 09:29:44AM -0700, Junio C Hamano wrote:
>>> Taylor Blau <me@ttaylorr.com> writes:
>>>
>>>> Given this and the above, I would probably err on the side of
>>>> designating this as 'test_lazy_prereq' or otherwise silencing the output
>>>> of 'test_cmp' so that this does not taint the TAP output.
>>>
>>> We can argue the merit and demerit with a good log message. The
>>> central issue at hand is how precious 52a9 in the script lost by
>>> this patch is (in other words, are we checking more than "is our
>>> char signed or unsigned?").
>>
>> Ultimately, I don't mind much which way we go. But if we want to retain
>> this, would you mind sending a rewritten v2, Taylor? I feel like you're
>> in a better position to argue why we should retain it.
>
> Is this something which can be merged before 2.55.0 final?
> It's certainly not a grave issue, but it is a new test
> failure for anyone who diligently runs the test suite on
> many (most?) non-x86 architectures. It seems a shame to
> punish those folks. :)
>
> FWIW, Tested-by: Todd Zullinger <tmz@pobox.com>
>
> I tested the earlier test_lazy_prereq version as well.
Good that you pinged, as I forgot that we haven't seen Taylor for
some time. Let's merge down Patrick's one you have already tested
while leaving it as an option to resurrect the "52a9 is still
precious" tweak from Taylor perhaps after the release.
Thanks.
^ permalink raw reply
* Re: [PATCH v3 4/4] connected: search promisor objects generically
From: Junio C Hamano @ 2026-06-25 20:22 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git, Christian Couder
In-Reply-To: <20260625-pks-connected-generic-promisor-checks-v3-4-7308f3b9dc44@pks.im>
Patrick Steinhardt <ps@pks.im> writes:
> When performing connectivity checks we have to figure out whether any of
> the new objects are promisor objects, as we cannot assume full
> connectivity if so.
>
> This check is performed by iterating through all packfiles in the
> repository and searching each of them for the given object. Of course,
> this mechanism is quite specific to implementation details of the object
> database, as we assume that it uses packfiles in the first place.
>
> Refactor the logic so that we instead use `odb_for_each_object_ext()`
> with an object prefix filter and the `ODB_FOR_EACH_OBJECT_PROMISOR_ONLY`
> flag. This will yield all objects that have the exact object name and
> that are part of a promisor pack in a generic way.
>
> Add a test to verify that we indeed use the optimization.
OK. The new test is a good way to catch the issue we noticed in the
previous round, I guess. Looking good.
Thanks.
^ permalink raw reply
* Re: [PATCH v1 2/2] environment: move excludes_file into repo_config_values
From: Junio C Hamano @ 2026-06-25 20:40 UTC (permalink / raw)
To: Tian Yuchen
Cc: git, cirnovskyv, Christian Couder, Ayush Chandekar,
Olamide Caleb Bello
In-Reply-To: <20260625161845.7543-3-cat@malon.dev>
Tian Yuchen <cat@malon.dev> writes:
> Continue the libification effor by moving the 'excludes_file' global
"effort"?
> variable into 'struct repo_config_values'.
>
> Since 'excludes_file' is a dynamically allocated string (char *), it
> requires proper memory management. Introduce repo_config_values_clear()
> to safely free the heap memory when repository instance is destroyed.
>
> Note: 'if (repo != the_repository)' fallback logic is temporarily added
> in both the getter and the clear function. This prevents calling
> repo_config_values() on uninitialized submodules, which triggers BUG().
>
> 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>
> ---
> environment.c | 28 ++++++++++++++++++++++------
> environment.h | 15 +++++++++++----
> repository.c | 1 +
> 3 files changed, 34 insertions(+), 10 deletions(-)
> ...
> @@ -733,3 +736,16 @@ void repo_config_values_init(struct repo_config_values *cfg)
> cfg->sparse_expect_files_outside_of_patterns = 0;
> cfg->warn_on_object_refname_ambiguity = 1;
Shouldn't cfg->excludes_file be explicitly initialized to NULL here
for completeness? There are other explicit but redundant 0 assignment
to the members of this struct in the same function.
> }
> +
> +void repo_config_values_clear(struct repository *repo)
> +{
> + struct repo_config_values *cfg;
> +
> + if (repo != the_repository)
> + return;
> +
> + cfg = repo_config_values(repo);
> + if (!cfg)
> + return;
> + FREE_AND_NULL(cfg->excludes_file);
> +}
> diff --git a/environment.h b/environment.h
> index 52d531e4ea..2839913551 100644
> --- a/environment.h
> +++ b/environment.h
> @@ -98,6 +98,7 @@ struct repo_config_values {
> int precomposed_unicode;
> int core_sparse_checkout_cone;
> int warn_on_object_refname_ambiguity;
> + char *excludes_file;
>
> /* section "sparse" config values */
> int sparse_expect_files_outside_of_patterns;
> @@ -133,13 +134,20 @@ 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);
>
> -/*
> - * TODO: This still relies on the global state.
> - */
> const char *repo_excludes_file(struct repository *repo);
Good.
> +/*
> + * Frees memory allocated for dynamically loaded configuration values
> + * inside `repo_config_values`.
> + *
> + * Note: `excludes_file` is currently the only heap-allocated field in
> + * this struct. As other dynamically allocated variables are migrated,
> + * their FREE_AND_NULL() calls should be appended here.
Isn't attributes_file also heap-allocated member in this struct as well?
^ permalink raw reply
* Re: [PATCH v6 00/11] refs: fix "onbranch" conditions
From: Junio C Hamano @ 2026-06-25 20:50 UTC (permalink / raw)
To: Justin Tobler; +Cc: Patrick Steinhardt, git, Karthik Nayak, Jeff King
In-Reply-To: <aj1DuUzusBUqmF_C@denethor>
Justin Tobler <jltobler@gmail.com> writes:
> On 26/06/25 11:19AM, Patrick Steinhardt wrote:
>> Changes in v6:
>> - Drop redundant condition when setting the default for
>> "core.logallrefupdates".
>> - Leave breakcrumb for why we lazy-load write options for the "files"
>> backend.
>> - Fix commit message typo.
>
> Thanks. This version of the series looks good to me.
>
> -Justin
Thanks, both. Let's call it ready for 'next' then.
^ permalink raw reply
* Re: [PATCH v6 10/10] builtin/history: implement "drop" subcommand
From: Junio C Hamano @ 2026-06-25 20:50 UTC (permalink / raw)
To: Christian Couder
Cc: Patrick Steinhardt, git, Pablo Sabater, Kristoffer Haugsbakk,
Phillip Wood
In-Reply-To: <CAP8UFD3jsepRaiHDen_CzWcse-atvBfCdzAQovk+1csaQeDxmQ@mail.gmail.com>
Christian Couder <christian.couder@gmail.com> writes:
> On Mon, Jun 15, 2026 at 3:55 PM Patrick Steinhardt <ps@pks.im> wrote:
>
>> + /*
>> + * If HEAD will move as a result of the rewrite then we'll have to
>> + * merge in the changes into the worktree and index. This merge can of
>> + * course conflict, which will cause the whole operation to abort.
>> + *
>> + * If we had already updated the refs at that point then we'd have an
>> + * inconsistent repository state. So we first perform a dry-run merge
>> + * here before updating refs.
>> + */
>> + if (!is_bare_repository()) {
>
> When your ps/setup-drop-global-state series is merged, this will look like:
>
> if (!is_bare_repository(repo)) {
>
> which is nicer.
>
> So except for perhaps the replay_result_queue_update() duplication,
> the series looks great to me.
Thanks. Let me mark it as "Waiting for response(s) to review
comment(s)." then.
^ permalink raw reply
* Re: [PATCH GSoC v14 02/13] git-compat-util: add strtoul_szt() with error handling
From: Junio C Hamano @ 2026-06-25 21:09 UTC (permalink / raw)
To: Pablo Sabater
Cc: git, chandrapratap3519, chriscool, eric.peijian, jltobler,
karthik.188, peff, toon
In-Reply-To: <20260625-ps-eric-work-rebase-v14-2-09f7ffe21a53@gmail.com>
Pablo Sabater <pabloosabaterr@gmail.com> writes:
> From: Eric Ju <eric.peijian@gmail.com>
>
> We already have strtoul_ui() and similar functions that provide proper
> error handling using strtoul from the standard library. However,
> there isn't currently a variant that returns an unsigned long.
But this one no longer returns an unsigned long anymore ;-)
> This variant is needed in a subsequent commit to enable returning an
> size_t with proper error handling.
I think it would allow a lot of code paths that want to deal with
size_t not to worry about "is ulong large enough?" to have a
function like this, but for that to happen, the implementation of
the function must carefully think through if these steps do sensible
things on platforms with too small ulong (which often is OK when we
are coming from decimal string to ulong and then to size_t) and too
large ulong (which is not OK, when coming from decimal string to
ulong which might be fine, but will bust the size of the final
type), etc.
Also, would it make sense to add yet another "static inline" like
this? After the dust settles, we may want to rethink these strtoX
wrappers we have, benchmark, and possibly make them into a proper
library function, not "static inline" that may bloat the runtime.
> diff --git a/git-compat-util.h b/git-compat-util.h
> index 8809776407..7f417f1acf 100644
> --- a/git-compat-util.h
> +++ b/git-compat-util.h
> @@ -975,6 +975,26 @@ static inline int strtoul_ui(char const *s, int base, unsigned int *result)
> return 0;
> }
>
> +/*
> + * Convert a string to a size_t using the standard library's strtoul, with
> + * additional error handling to ensure robustness.
> + */
> +static inline int strtoul_szt(char const *s, int base, size_t *result)
> +{
> + unsigned long ul;
> + char *p;
> +
> + errno = 0;
> + /* negative values would be accepted by strtoul */
> + if (strchr(s, '-'))
> + return -1;
> + ul = strtoul(s, &p, base);
> + if (errno || *p || p == s)
> + return -1;
> + *result = ul;
> + return 0;
> +}
> +
> static inline int strtol_i(char const *s, int base, int *result)
> {
> long ul;
^ permalink raw reply
* Re: [PATCH v2 1/2] branch: suggest <remote>/<branch> on upstream slip
From: Junio C Hamano @ 2026-06-25 21:16 UTC (permalink / raw)
To: Harald Nordgren; +Cc: Harald Nordgren via GitGitGadget, git
In-Reply-To: <CAHwyqnXZ_eGUPOhq1hXs==uYuYbRBWw120fXRQa=apWKekxVAQ@mail.gmail.com>
Harald Nordgren <haraldnordgren@gmail.com> writes:
>> Do we still need the _if_enabled() thing here? Isn't the caller
>> gated with the same condition in this version?
>>
>> > + strbuf_release(&remote_ref);
>> > + exit(code);
>> > +}
>> > +
>> > int cmd_branch(int argc,
>> > const char **argv,
>> > const char *prefix,
>> > @@ -957,6 +980,9 @@ int cmd_branch(int argc,
>> > if (!refs_ref_exists(get_main_ref_store(the_repository), branch->refname)) {
>> > if (!argc || branch_checked_out(branch->refname))
>> > die(_("no commit on branch '%s' yet"), branch->name);
>> > + if (argc == 1 &&
>> > + advice_enabled(ADVICE_SET_UPSTREAM_FAILURE))
>> > + die_if_upstream_looks_like_remote(new_upstream, argv[0]);
>> > die(_("branch '%s' does not exist"), branch->name);
>> > }
>
> I think we do, so it will give the advice and tell the user that it
> can be disabled in the standard format.
I was hoping that unconditional advise() should be sufficient, but
the caller there needs to say if_enabled, even though it _knows_
that it is enabled, only to give the turn-off instructions.
I wonder if future readers would be confused just like I was,
without a comment on the callsite of _if_enabled() added by this
patch?
Thanks.
^ permalink raw reply
* What's cooking in git.git (Jun 2026, #10)
From: Junio C Hamano @ 2026-06-26 0:30 UTC (permalink / raw)
To: git
Here are the topics that have been cooking in my tree. Commits
prefixed with '+' are in 'next' (being in 'next' is a sign that a
topic is stable enough to be used and is a candidate to be in a
future release). Commits prefixed with '-' are only in 'seen', and
aren't considered "accepted" at all and may be annotated with a URL
to a message that raises issues but they are by no means exhaustive.
A topic without enough support may be discarded after a long period
of no activity (of course they can be resubmitted when new interests
arise).
Git 2.55-rc2 has been tagged. The tree is in deep feature-freeze,
and remaining topics in 'next' will stay in "Will cook in 'next'"
instead of "Will merge to 'master'" state, until Git 2.55 final.
Copies of the source code to Git live in many repositories, and the
following is a list of the ones I push into or their mirrors. Some
repositories have only a subset of branches.
With maint, master, next, seen, todo:
git://git.kernel.org/pub/scm/git/git.git/
git://repo.or.cz/alt-git.git/
https://kernel.googlesource.com/pub/scm/git/git/
https://github.com/git/git/
https://gitlab.com/git-scm/git/
With all the integration branches and topics broken out:
https://github.com/gitster/git/
Even though the preformatted documentation in HTML and man format
are not sources, they are published in these repositories for
convenience (replace "htmldocs" with "manpages" for the manual
pages):
git://git.kernel.org/pub/scm/git/git-htmldocs.git/
https://github.com/gitster/git-htmldocs.git/
Release tarballs are available at:
https://www.kernel.org/pub/software/scm/git/
--------------------------------------------------
[New Topics]
* ad/gpg-strip-cr-before-lf (2026-06-24) 1 commit
- gpg-interface: fix strip_cr_before_lf to only remove CR before LF
The GPG and SSH signature parsing code has been corrected to strip
carriage return characters only when they immediately precede line
feeds, instead of unconditionally stripping all carriage returns.
Needs review.
source: <20260624093618.17456-1-antonio.destefani08@gmail.com>
* jt/receive-pack-use-odb-transactions (2026-06-23) 6 commits
- builtin/receive-pack: stage incoming objects via ODB transactions
- odb/transaction: add transaction env interface
- odb/transaction: propagate commit errors
- odb/transaction: propagate begin errors
- object-file: propagate files transaction errors
- object-file: rename files transaction prepare function
git-receive-pack has been refactored to use ODB transaction
interfaces instead of directly managing tmp_objdir for staging
incoming objects, bringing it closer to being ODB backend agnostic.
Waiting for response(s) to review comment(s).
cf. <aju_AmlKVi5UZaiQ@pks.im>
source: <20260624041920.2601961-1-jltobler@gmail.com>
* ps/odb-drop-whence (2026-06-24) 7 commits
- odb: document object info fields
- odb: drop `whence` field from object info
- treewide: convert users of `whence` to the new source field
- odb: add `source` field to struct object_info_source
- odb: make backend-specific fields optional
- packfile: thread odb_source_packed through packed_object_info()
- Merge branch 'ps/odb-source-packed' into ps/odb-drop-whence
(this branch uses ps/odb-source-packed.)
The whence field in struct object_info has been removed,
refactoring backend-specific object information retrieval into an
opt-in struct object_info_source structure.
Needs review.
source: <20260624-b4-pks-odb-drop-whence-v1-0-8d1877b790ac@pks.im>
* ps/reftable-hardening (2026-06-24) 11 commits
- reftable/table: fix OOB read on truncated table
- reftable/table: fix NULL pointer access when seeking to bogus offsets
- reftable/block: fix OOB read with bogus restart offset
- reftable/block: fix use of uninitialized memory when binsearch fails
- reftable/block: fix OOB read with bogus restart count
- reftable/block: fix OOB read with bogus block size
- reftable/block: fix OOB write with bogus inflated log size
- reftable/record: don't abort when decoding invalid ref value type
- reftable/basics: fix OOB read on binary search of empty range
- oss-fuzz: add fuzzer for parsing reftables
- meson: support building fuzzers with libFuzzer
The reftable code has been hardened against corrupted tables by
fixing out-of-bounds writes, out-of-bounds reads, and abort calls
during parsing.
Needs review.
source: <20260624-pks-reftable-hardening-v1-0-66e4ce87c6b9@pks.im>
* hn/branch-push-slip-advice (2026-06-24) 3 commits
- SQUASH??? use test_grep
- push: suggest <remote> <branch> for a slash slip
- branch: suggest <remote>/<branch> on upstream slip
"git push origin/main" and "git branch origin main" could both be
an obvious typo, in which case offer the obvious typofix.
Waiting for response(s) to review comment(s).
cf. <xmqqfr2ae2wp.fsf@gitster.g>
source: <pull.2331.v2.git.git.1782338114.gitgitgadget@gmail.com>
* jc/history-message-prep-fix (2026-06-25) 1 commit
- history: streamline message preparation and plug file stream leak
Code clean-up with leakfix for a write file stream.
Needs review.
source: <xmqqh5mqfkpv.fsf@gitster.g>
* ty/migrate-excludes-file (2026-06-25) 2 commits
- environment: move excludes_file into repo_config_values
- dir: encapsulate excludes_file lazy-load
Move excludes_file global variable into per-repository structure.
Waiting for response(s) to review comment(s).
cf. <xmqqwlvme4lz.fsf@gitster.g>
source: <20260625161845.7543-1-cat@malon.dev>
--------------------------------------------------
[Stalled]
* jt/config-lock-timeout (2026-05-17) 1 commit
- config: retry acquiring config.lock, configurable via core.configLockTimeout
Configuration file locking now retries for a short period, avoiding
failures when multiple processes attempt to update the configuration
simultaneously.
Waiting for response(s) to review comment(s) for too long, stalled.
cf. <agrIrGwSMFlKTx9x@pks.im>
source: <20260517132111.1014901-1-joerg@thalheim.io>
* js/parseopt-subcommand-autocorrection (2026-04-27) 11 commits
- SQUASH???
- doc: document autocorrect API
- parseopt: add tests for subcommand autocorrection
- parseopt: enable subcommand autocorrection for git-remote and git-notes
- parseopt: autocorrect mistyped subcommands
- autocorrect: provide config resolution API
- autocorrect: rename AUTOCORRECT_SHOW to AUTOCORRECT_HINT
- autocorrect: use mode and delay instead of magic numbers
- help: move tty check for autocorrection to autocorrect.c
- help: make autocorrect handling reusable
- parseopt: extract subcommand handling from parse_options_step()
The parse-options library learned to auto-correct misspelled
subcommand names.
Waiting for response(s) to review comment(s) for too long, stalled.
cf. <xmqq33yzd9yf.fsf@gitster.g>
cf. <SY0P300MB0801E50FCB7EB2F45CD15208CE042@SY0P300MB0801.AUSP300.PROD.OUTLOOK.COM>
source: <SY0P300MB0801677A2A1E0FD38D06A841CE2A2@SY0P300MB0801.AUSP300.PROD.OUTLOOK.COM>
* cl/conditional-config-on-worktree-path (2026-05-24) 2 commits
- config: add "worktree" and "worktree/i" includeIf conditions
- config: refactor include_by_gitdir() into include_by_path()
The [includeIf "condition"] conditional inclusion facility for
configuration files has learned to use the location of worktree
in its condition.
Waiting for response(s) to review comment(s) for too long, stalled.
cf. <xmqq8q97et9b.fsf@gitster.g>
source: <20260525-includeif-worktree-v5-0-1efe525d025a@black-desk.cn>
--------------------------------------------------
[Cooking]
* kk/merge-base-exhaustion (2026-06-24) 7 commits
- commit-reach: terminate merge-base walk when one paint side is exhausted
- commit-reach: remove unused nonstale_queue dedup wrappers
- commit-reach: introduce struct paint_state with per-side counters
- commit-reach: add trace2 instrumentation to paint_down_to_common()
- t6099, t6600: add side-exhaustion regression tests
- t6600: add test cases for side-exhaustion edge cases
- Documentation/technical: add paint-down-to-common doc
The merge-base computation has been optimized by stopping the walk
early when one side's exclusive commits in the queue are exhausted,
yielding significant speedups for queries with one-sided histories.
Expecting a reroll.
cf. <CAL71e4MnA36ZchLaUsMSoLcb9LO77aac274jES8+oV=yxuigOA@mail.gmail.com>
source: <pull.2149.v2.git.1782303254.gitgitgadget@gmail.com>
* dk/meson-enable-use-nsec-build (2026-06-20) 1 commit
- meson: wire up USE_NSEC build knob
The USE_NSEC build knob, which enables support for sub-second file
timestamp resolution, has been wired up to the Meson build system.
Waiting for response(s) to review comment(s).
cf. <ajjuoS5Qc3K0nCRl@pks.im>
source: <c4c5ade901ff95b0f95939ea818870e4f3d59da1.1781971201.git.ben.knoble+github@gmail.com>
* ps/connected-generic-promisor-checks (2026-06-25) 5 commits
- connected: search promisor objects generically
- connected: split out promisor-based connectivity check
- odb/source-packed: support flags when iterating an object prefix
- odb/source-packed: extract logic to skip certain packs
- Merge branch 'ps/odb-source-packed' into ps/connected-generic-promisor-checks
(this branch uses ps/odb-source-packed.)
The connectivity check has been refactored to search for promisor
objects in a generic way using the object database interface,
rather than iterating packfiles directly. This allows connectivity
checks to work properly in repositories that do not use packfiles.
Will merge to 'next'?
cf. <xmqq4iiqfk0l.fsf@gitster.g>
source: <20260625-pks-connected-generic-promisor-checks-v3-0-7308f3b9dc44@pks.im>
* ps/libgit-in-subdir (2026-06-22) 3 commits
- Move libgit.a sources into separate "lib/" directory
- t/helper: prepare "test-example-tap.c" for introduction of "lib/"
- Merge branch 'ps/odb-source-packed' into ps/libgit-in-subdir
(this branch uses ps/odb-source-packed.)
The source files for libgit.a have been moved into a new "lib/"
directory to clean up the top-level directory and clearly separate
library code.
Needs review.
source: <20260622-pks-libgit-in-subdir-v2-0-cb946c51ee7b@pks.im>
* ps/odb-generalize-prepare (2026-06-22) 3 commits
- odb: introduce `odb_prepare()`
- odb/source: generalize `reprepare()` callback
- Merge branch 'ps/odb-source-packed' into ps/odb-generalize-prepare
(this branch uses ps/odb-source-packed.)
The `reprepare()` callback for object database sources has been
generalized into a `prepare()` callback with an optional flush cache
flag, and a new `odb_prepare()` wrapper has been introduced to
allow pre-opening object database sources.
Needs review.
source: <20260622-b4-pks-odb-generalize-prepare-v1-0-d2a5c5d13144@pks.im>
* jc/submittingpatches-design-critiques (2026-06-20) 1 commit
(merged to 'next' on 2026-06-22 at 7495b5f9d6)
+ SubmittingPatches: address design critiques
The documentation in SubmittingPatches has been updated to clarify how
patch contributors should respond to design and viability critiques,
and how the resolution of such critiques should be recorded in the
final commit messages.
Will cook in 'next'.
cf. <ajjwYGWZ6hQWr600@pks.im>
source: <xmqqeci0g4mz.fsf@gitster.g>
* wy/doc-clarify-review-replies (2026-06-21) 2 commits
- doc: advise batching patch rerolls
- doc: encourage review replies before rerolling
Documentation on community contribution guidelines has been updated to
encourage replying to review comments before rerolling, and to advise
a default limit of at most one reroll per day to give reviewers across
different time zones enough time to participate.
Will merge to 'next'?
cf. <ajvDuUiDsmyf5LnX@pks.im>
source: <cover.1782028813.git.wy@wyuan.org>
* ty/migrate-ignorecase (2026-06-19) 2 commits
- config: use repo_ignore_case() to access core.ignorecase
- environment: move ignore_case into repo_config_values
The global configuration variable ignore_case (representing the
core.ignorecase configuration) has been migrated into struct
repo_config_values to tie it to a specific repository instance.
Waiting for comments from Johannes.
cf. <xmqqzf0mzc7j.fsf@gitster.g>
source: <20260619155152.642760-1-cat@malon.dev>
* mm/line-log-limited-ops (2026-06-18) 7 commits
- diffcore-pickaxe: scope -G to the -L tracked range
- diff: support --check with -L line ranges
- line-log: support diff stat formats with -L
- diff: extract a line-range diff helper for reuse
- diff: emit -L hunk headers via xdiff's formatter
- diff: simplify the line-range filter by classifying removals immediately
- diff: rename and group the line-range filter for clarity
"git log -L<range>:<path>" learned to limit various "diff" operations
like --stat, --check, -G, to the specified range:path.
Expecting a reroll.
cf. <CAC2QwmKEHb+LL4ZkQwq+Rw8eyDXzdBp_nxa_d+Ecx0K1icNqQA@mail.gmail.com>
source: <pull.2152.git.1781806593.gitgitgadget@gmail.com>
* hn/history-squash (2026-06-24) 4 commits
- history: re-edit a squash with every message
- history: add squash subcommand to fold a range
- history: give commit_tree_ext a message template
- history: extract helper for a commit's parent tree
The experimental "git history" command has been taught a new
"squash" subcommand to fold a range of commits into a single commit,
replaying any descendants on top.
Needs review.
source: <pull.2337.v5.git.git.1782338102.gitgitgadget@gmail.com>
* ps/t4216-tap-fix (2026-06-19) 1 commit
(merged to 'next' on 2026-06-25 at 42296fc12e)
+ t4216: fix no-op test that breaks TAP output
TAP output breakage fix.
Will merge to 'master'.
cf. <xmqq8q82fk8r.fsf@gitster.g>
source: <20260619-pks-t4216-drop-unused-prereq-v1-1-2ce0d7bea088@pks.im>
* mh/fetch-follow-remote-head-config (2026-06-19) 8 commits
(merged to 'next' on 2026-06-22 at 423079e1c8)
+ fetch: fixup a misaligned comment
+ fetch: add configuration variable fetch.followRemoteHEAD
+ fetch: refactor do_fetch handling of followRemoteHEAD
+ fetch: return 0 on known git_fetch_config
+ fetch: rename function report_set_head
+ t5510: cleanup remote in followRemoteHEAD dangling ref test
+ doc: explain fetchRemoteHEADWarn advice
+ fetch: fixup set_head advice for warn-if-not-branch
The `fetch.followRemoteHEAD` configuration variable has been added to
provide a default for the per-remote `remote.<name>.followRemoteHEAD`
setting.
Will cook in 'next'.
cf. <xmqqcxxp1j2t.fsf@gitster.g>
source: <20260619094751.2996804-1-m@lfurio.us>
* ps/refs-writing-subcommands (2026-06-17) 5 commits
- builtin/refs: add "rename" subcommand
- builtin/refs: add "create" subcommand
- builtin/refs: add "update" subcommand
- builtin/refs: add "delete" subcommand
- builtin/refs: drop `the_repository`
The "git refs" toolbox has been extended with new "create", "delete",
"update", and "rename" subcommands to create, delete, update, and
rename references, respectively.
Needs review.
source: <20260617-pks-refs-writing-subcommands-v2-0-07f3d18336f9@pks.im>
* po/hash-object-size-t (2026-06-16) 6 commits
(merged to 'next' on 2026-06-21 at b780a276b9)
+ hash-object: add a >4GB/LLP64 test case using filtered input
+ hash-object: add another >4GB/LLP64 test case
+ hash-object --stdin: verify that it works with >4GB/LLP64
+ hash algorithms: use size_t for section lengths
+ object-file.c: use size_t for header lengths
+ hash-object: demonstrate a >4GB/LLP64 problem
Support for hashing loose or packed objects larger than 4GB on Windows
and other LLP64 platforms has been improved by converting object header
buffers and data-handling functions from 'unsigned long' to 'size_t'.
Will cook in 'next'.
cf. <ajOQthRjhD3hRM9w@pks.im>
source: <pull.2138.v2.git.1781621398.gitgitgadget@gmail.com>
* kh/submittingpatches-trailers (2026-06-18) 5 commits
(merged to 'next' on 2026-06-22 at 2cd4a152c9)
+ SubmittingPatches: note that trailer order matters
+ SubmittingPatches: be consistent with trailer markup
+ SubmittingPatches: document Based-on-patch-by trailer
+ SubmittingPatches: discourage common Linux trailers
+ SubmittingPatches: encourage trailer use for substantial help
The trailer sections in SubmittingPatches have been updated to
encourage use of standard trailers.
Will cook in 'next'.
cf. <xmqq4ij0vo8f.fsf@gitster.g>
source: <V3_CV_SubPatches_trailers.9ec@msgid.xyz>
* mv/log-follow-mergy (2026-06-21) 1 commit
(merged to 'next' on 2026-06-22 at f7e984a003)
+ log: improve --follow following renames for non-linear history
"git log --follow" has been updated to handle non-linear history, in
which the path being tracked gets renamed differently in multiple
history lines, better.
Will cook in 'next'.
source: <ajjU4w2B0NlZffw1@collabora.com>
* wy/doc-myfirstcontribution-trim-quotes (2026-06-11) 1 commit
- MyFirstContribution: mention trimming quoted text in replies
The contributor guide has been updated to advise new contributors to
trim irrelevant quoted text when replying to review comments, matching
the existing advice given to reviewers.
Comments?
cf. <xmqqcxxwljue.fsf@gitster.g>
source: <080402ff0ac8127b654dccea59a1bf643df62a5c.1781186476.git.wy@wyuan.org>
* tb/midx-incremental-custom-base (2026-06-12) 3 commits
- midx-write: include packs above custom incremental base
- midx: pass custom '--base' through incremental writes
- t5334: expose shared `nth_line()` helper
The `git multi-pack-index write --incremental` command has been
corrected to properly honor the `--base` option. Previously, the
custom base was ignored by the normal write path, and the pack
exclusion logic incorrectly skipped packs from layers above the
selected base, breaking reachability closure for bitmaps.
Needs review.
source: <cover.1781294771.git.me@ttaylorr.com>
* mm/test-grep-lint (2026-06-12) 6 commits
- t: add greplint to detect bare grep assertions
- t: convert grep assertions to test_grep
- t: fix Lexer line count for $() inside double-quoted strings
- t: extract chainlint's parser into shared module
- t: fix grep assertions missing file arguments
- t/README: document test_grep helper
Needs review.
source: <pull.2135.v2.git.1781323575.gitgitgadget@gmail.com>
* rs/cat-file-default-format-optim (2026-06-14) 1 commit
(merged to 'next' on 2026-06-17 at 43ed8b3969)
+ cat-file: speed up default format
Will cook in 'next'.
cf. <20260615165326.GA91269@coredump.intra.peff.net>
source: <5a7ed929-6fe0-496c-83bd-65dee57c2241@web.de>
* kk/prio-queue-get-put-fusion (2026-06-08) 2 commits
- prio-queue: fold lazy_queue into prio_queue for automatic get+put fusion
- prio-queue: rename .nr to .nr_ and add accessor helpers
The lazy priority queue optimization pattern (deferring actual removal
in prio_queue_get() to allow get+put fusion) has been folded directly
into prio_queue itself, speeding up commit traversal workflows and
simplifying callers.
On hold, waiting for kk/prio-queue-get-put-fusion to land first.
cf. <CAL71e4MYNiScZjTwkApjDAjRh2LM0_SP59h5HCTywV-Pua03tw@mail.gmail.com>
source: <pull.2140.v4.git.1780945851.gitgitgadget@gmail.com>
* td/ref-filter-memoize-contains (2026-06-12) 3 commits
- commit-reach: die on contains walk errors
- ref-filter: memoize --contains with generations
- commit-reach: reject cycles in contains walk
'git branch --contains' and 'git for-each-ref --contains' have
been optimized to use the memoized commit traversal previously
used only by 'git tag --contains', significantly speeding up
connectivity checks across many candidate refs with shared
history.
Needs review.
source: <20260612-ref-filter-memoized-contains-v4-0-5ed39fd001dd@gmail.com>
* tc/replay-linearize (2026-06-22) 3 commits
- replay: offer an option to linearize the commit topology
- replay: add helper to put entry into mapped_commits
- replay: refactor enum replay_mode into a bool
git replay learns --linearize option to drop merge commits and
linearize the replayed history, mimicking git rebase
--no-rebase-merges.
Expecting a reroll.
cf. <87tsqrycke.fsf@emacs.iotcl.com>
source: <20260622-toon-git-replay-drop-merges-v4-0-ff257f534319@iotcl.com>
* ps/setup-drop-global-state (2026-06-10) 8 commits
(merged to 'next' on 2026-06-15 at d9a8b88d47)
+ treewide: drop USE_THE_REPOSITORY_VARIABLE
+ environment: stop using `the_repository` in `is_bare_repository()`
+ environment: split up concerns of `is_bare_repository_cfg`
+ builtin/init: stop modifying `is_bare_repository_cfg`
+ setup: remove global `git_work_tree_cfg` variable
+ builtin/init: simplify logic to configure worktree
+ builtin/init: stop modifying global `git_work_tree_cfg` variable
+ Merge branch 'ps/setup-centralize-odb-creation' into ps/setup-drop-global-state
Continuation of "setup.c" refactoring to drop remaining global state
(`git_work_tree_cfg`, `is_bare_repository_cfg`). The most notable
outcome is that `is_bare_repository()` has been updated to no longer
implicitly rely on `the_repository`.
Will cook in 'next'.
cf. <airVOrTboNDDGBak@denethor>
cf. <87ldckyygk.fsf@emacs.iotcl.com>
source: <20260611-b4-pks-setup-drop-global-state-v2-0-a6f7269c841d@pks.im>
* ps/refs-avoid-chdir-notify-reparent (2026-06-25) 12 commits
- refs: protect against chicken-and-egg recursion
- refs/reftable: lazy-load configuration to fix chicken-and-egg
- reftable: split up write options
- refs/files: lazy-load configuration to fix chicken-and-egg
- refs: move parsing of "core.logAllRefUpdates" back into ref stores
- repository: free main reference database
- chdir-notify: drop unused `chdir_notify_reparent()`
- refs: unregister reference stores from "chdir_notify"
- setup: don't apply "GIT_REFERENCE_BACKEND" without a repository
- setup: stop applying repository format twice
- setup: inline `check_and_apply_repository_format()`
- Merge branch 'ps/setup-centralize-odb-creation' into ps/refs-avoid-chdir-notify-reparent
The reference backends have been converted to always use absolute
paths internally. This allows dropping the calls to
`chdir_notify_reparent()` and fixes a memory leak in how the
reference database is constructed with an "onbranch" condition.
Will merge to 'next'?
cf. <aj1DuUzusBUqmF_C@denethor>
source: <20260625-b4-pks-refs-avoid-chdir-notify-reparent-v6-0-41fbca3cf5e3@pks.im>
* ps/odb-source-packed (2026-06-16) 18 commits
(merged to 'next' on 2026-06-19 at dcf0c084e4)
+ odb/source-packed: drop pointer to "files" parent source
+ midx: refactor interfaces to work on "packed" source
+ odb/source-packed: stub out remaining functions
+ odb/source-packed: wire up `freshen_object()` callback
+ odb/source-packed: wire up `find_abbrev_len()` callback
+ odb/source-packed: wire up `count_objects()` callback
+ odb/source-packed: wire up `for_each_object()` callback
+ odb/source-packed: wire up `read_object_stream()` callback
+ odb/source-packed: wire up `read_object_info()` callback
+ packfile: use higher-level interface to implement `has_object_pack()`
+ odb/source-packed: wire up `reprepare()` callback
+ odb/source-packed: wire up `close()` callback
+ odb/source-packed: start converting to a proper `struct odb_source`
+ odb/source-packed: store pointer to "files" instead of generic source
+ packfile: move packed source into "odb/" subsystem
+ packfile: split out packfile list logic
+ packfile: rename `struct packfile_store` to `odb_source_packed`
+ Merge branch 'ps/odb-source-loose' into ps/odb-source-packed
(this branch is used by ps/connected-generic-promisor-checks, ps/libgit-in-subdir, ps/odb-drop-whence and ps/odb-generalize-prepare.)
The packed object source has been refactored into a proper struct
odb_source.
Will cook in 'next'.
cf. <ajK2QKdW-TdflfR0@denethor>
source: <20260617-pks-odb-source-packed-v3-0-b5c7583cd795@pks.im>
* td/ref-filter-restore-prefix-iteration (2026-06-12) 1 commit
(merged to 'next' on 2026-06-19 at a19dbb4193)
+ ref-filter: restore prefix-scoped iteration
Commands that list branches and tags (like git branch and git tag)
have been optimized to pass the namespace prefix when initializing
their ref iterator, avoiding a loose-ref scaling regression in
repositories with many unrelated loose references.
Will cook in 'next'.
cf. <xmqqik7fsv2m.fsf@gitster.g>
source: <20260612-fix-git-branch-regression-v4-1-f150038c02f4@gmail.com>
* ty/move-protect-hfs-ntfs (2026-06-20) 2 commits
(merged to 'next' on 2026-06-20 at d8ca0d5180)
+ environment: use 'repo->initialized' for repo_protect_hfs() and repo_protect_ntfs()
(merged to 'next' on 2026-06-15 at c2a30ca954)
+ environment: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values'
The global configuration variables protect_hfs and protect_ntfs have
been migrated into struct repo_config_values to tie them to
per-repository configuration state.
Will cook in 'next'.
cf. <CAP8UFD35Tiy1_fqpjq8P-z=ZhzR3MTiThqfCs977652umRoSEQ@mail.gmail.com>
cf. <xmqqse6uwdnz.fsf@gitster.g>
source: <20260610124353.149874-2-cat@malon.dev>
source: <20260620140957.667820-1-cat@malon.dev>
* ps/cat-file-remote-object-info (2026-06-25) 13 commits
- cat-file: make remote-object-info allow-list dynamic
- cat-file: validate remote atoms with allow_list
- cat-file: add remote-object-info to batch-command
- transport: add client support for object-info
- serve: advertise object-info feature
- fetch-pack: move fetch initialization
- connect: refactor packet writing
- fetch-pack: move function to connect.c
- fetch-pack: prepare function to be moved
- t1006: split test utility functions into new "lib-cat-file.sh"
- cat-file: declare loop counter inside for()
- git-compat-util: add strtoul_szt() with error handling
- transport-helper: fix memory leak of helper on disconnect
The `remote-object-info` command has been added to `git cat-file
--batch-command`, allowing clients to request object metadata
(currently size) from a remote server via protocol v2 without
downloading the entire object.
The client dynamically filters format placeholders based on
server-advertised capabilities and safely returns empty strings for
inapplicable or unsupported fields.
Waiting for response(s) to review comment(s).
cf. <xmqqjyrme393.fsf@gitster.g>
source: <20260625-ps-eric-work-rebase-v14-0-09f7ffe21a53@gmail.com>
* ap/http-redirect-wwwauth-fix (2026-06-02) 1 commit
- http: preserve wwwauth_headers across redirects
When cURL follows a redirect, the WWW-Authenticate headers from the
redirect target were lost because credential_from_url() cleared the
credential state. This has been fixed by preserving the collected
headers across the redirect update.
Expecting a reroll.
cf. <5144a29d-a53f-4446-beff-e1f549345bf9@nvidia.com>
source: <20260602161150.1527493-1-aplattner@nvidia.com>
* ps/doc-recommend-b4 (2026-06-15) 3 commits
(merged to 'next' on 2026-06-17 at dd9a463369)
+ b4: introduce configuration for the Git project
+ MyFirstContribution: recommend the use of b4
+ MyFirstContribution: recommend shallow threading of cover letters
Project-specific configuration for b4 has been introduced, and the
documentation has been updated to recommend using it as a
streamlined method for submitting patches.
Will cook in 'next'.
cf. <87eci7yomp.fsf@emacs.iotcl.com>
source: <20260615-pks-b4-v4-0-22cfca8f19c5@pks.im>
* sn/rebase-update-refs-symrefs (2026-06-03) 1 commit
- rebase: skip branch symref aliases
"git rebase --update-refs" has been taught to resolve local branch
symrefs to their referents before queuing updates. This correctly
skips aliases of the current branch and avoids duplicate updates for
underlying real branches, fixing failures when branch aliases (like a
default branch rename) are present.
Waiting for response(s) to review comment(s).
cf. <f982c386-e329-4ab0-b695-e540bcb9de3d@gmail.com>
source: <pull.2126.v2.git.1780482436865.gitgitgadget@gmail.com>
* mm/diff-process-hunks (2026-06-14) 6 commits
- blame: consult diff process for no-hunk detection
- diff: bypass diff process with --no-ext-diff and in format-patch
- diff: add long-running diff process via diff.<driver>.process
- sub-process: separate process lifecycle from hashmap management
- userdiff: add diff.<driver>.process config
- xdiff: support external hunks via xpparam_t
A new `diff.<driver>.process` configuration has been introduced to
allow a long-running external process to act as a hunk provider to
allows external tools to control which lines Git considers changed
while leaving all output formatting (word diff, color, blame, etc.) to
Git's standard pipeline.
Expecting a reroll.
cf. <CAC2Qwm+P=fZOtpfMPeMiSXf3Afk6OLYpTP8Br78_PRA8WNL1Wg@mail.gmail.com>
source: <pull.2120.v4.git.1781463564.gitgitgadget@gmail.com>
* tb/pack-path-walk-bitmap-delta-islands (2026-06-21) 5 commits
(merged to 'next' on 2026-06-22 at 59cf1663e7)
+ pack-objects: support `--delta-islands` with `--path-walk`
+ pack-objects: extract `record_tree_depth()` helper
+ pack-objects: support reachability bitmaps with `--path-walk`
+ t/perf: drop p5311's lookup-table permutation
+ Merge branch 'ds/path-walk-filters' into tb/pack-path-walk-bitmap-delta-islands
The pack-objects command now supports using reachability bitmaps and
delta-islands concurrently with the `--path-walk` option, allowing
faster packaging by falling back to path-walk when bitmaps cannot
fully satisfy the request.
Will cook in 'next'.
cf. <xmqqwlvq1qyy.fsf@gitster.g>
source: <cover.1782082975.git.me@ttaylorr.com>
* ty/migrate-trust-executable-bit (2026-06-19) 3 commits
- environment: move trust_executable_bit into repo_config_values
- read-cache: move 'ce_mode_from_stat()' to 'read-cache.c'
- read-cache: remove redundant extern declarations
The 'trust_executable_bit' (coming from 'core.filemode'
configuration) has been migrated into 'repo_config_values' to tie it
to a specific repository instance.
Needs review.
source: <20260619162105.648495-1-cat@malon.dev>
* kk/prio-queue-cascade-sift (2026-06-01) 1 commit
- prio-queue: use cascade-down for faster extract-min
prio_queue_get() has been optimized by using a cascade-down approach
(promoting the smaller child at each level and sifting up the last
element from the leaf vacancy), which halves the number of comparisons
per extract-min operation in the common case.
On hold, waiting for kk/prio-queue-get-put-fusion to land first.
cf. <CAL71e4MYNiScZjTwkApjDAjRh2LM0_SP59h5HCTywV-Pua03tw@mail.gmail.com>
source: <pull.2132.v2.git.1780301856444.gitgitgadget@gmail.com>
* jk/repo-info-path-keys (2026-06-23) 3 commits
- repo: add path.gitdir with absolute and relative suffix formatting
- repo: add path.commondir with absolute and relative suffix formatting
- path: extract format_path() and use in rev-parse
The "git repo info" command has been taught new keys to output both
absolute and relative paths for "gitdir" and "commondir", supported by
a new path-formatting helper extracted from "git rev-parse".
Will merge to 'next'?
cf. <xmqqy0g3iz38.fsf@gitster.g>
source: <20260624033748.108281-1-jayatheerthkulkarni2005@gmail.com>
* ps/history-drop (2026-06-15) 10 commits
- builtin/history: implement "drop" subcommand
- builtin/history: split handling of ref updates into two phases
- reset: stop assuming that the caller passes in a clean index
- reset: allow the caller to specify the current HEAD object
- reset: introduce ability to skip updating HEAD
- reset: introduce dry-run mode
- reset: modernize flags passed to `reset_working_tree()`
- reset: rename `reset_head()`
- reset: drop `USE_THE_REPOSITORY_VARIABLE`
- read-cache: split out function to drop unmerged entries to stage 0
The experimental "git history" command has been taught a new "drop"
subcommand to remove a commit and replay its descendants onto its
parent.
Waiting for response(s) to review comment(s).
cf. <CAP8UFD1evTZqj1ymW9g5g2RmMkYMaE0rPa0Hzt+irH94M6LD6A@mail.gmail.com>
source: <20260615-b4-pks-history-drop-v6-0-2e329e536d78@pks.im>
* jk/setup-gitfile-diag-fix (2026-06-16) 1 commit
(merged to 'next' on 2026-06-18 at b63b3d1f25)
+ read_gitfile(): simplify NOT_A_REPO error message
A regression in the error diagnosis code for invalid .git files has
been fixed, avoiding a potential NULL-pointer crash when reporting
that a .git file does not point to a valid repository.
Will cook in 'next'.
cf. <xmqqjyry4hax.fsf@gitster.g>
source: <20260616123516.GA2301231@coredump.intra.peff.net>
* kh/doc-trailers (2026-06-10) 10 commits
- doc: interpret-trailers: document comment line treatment
- doc: interpret-trailers: commit to “trailer block” term
- doc: interpret-trailers: join new-trailers again
- doc: interpret-trailers: add key format example
- doc: interpret-trailers: explain key format
- doc: interpret-trailers: explain the format after the intro
- doc: interpret-trailers: not just for commit messages
- doc: interpret-trailers: use “metadata” in Name as well
- doc: interpret-trailers: replace “lines” with “metadata”
- doc: interpret-trailers: stop fixating on RFC 822
Documentation updates.
Expecting a reroll.
cf. <729baf6b-53ea-4e8d-95ab-5935667e66c2@app.fastmail.com>
source: <V3_CV_doc_int-tr_key_format.8a3@msgid.xyz>
* za/completion-hide-dotfiles (2026-06-20) 2 commits
- completion: hide dotfiles by default for path completion
- completion: hide dotfiles for selected path completion
The path completion for commands like `git rm` and `git mv`, is being
updated to hide dotfiles by default, unless the user explicitly starts
the path with a dot, matching standard shell-completion behavior.
Waiting for response(s) to review comment(s).
cf. <xmqq1pe0g08t.fsf@gitster.g>
source: <pull.2311.v3.git.git.1781978156.gitgitgadget@gmail.com>
* ec/commit-fixup-options (2026-05-26) 2 commits
- commit: allow -c/-C for all kinds of --fixup
- commit: allow -m/-F for all kinds of --fixup
The -m/-F/-c/-C options to supply commit log message from outside the
editor are now supported for all "git commit --fixup" variations.
Needs review.
source: <cover.1779792311.git.erik@cervined.in>
* kh/doc-replay-config (2026-06-05) 4 commits
- doc: replay: move “default” to the right-hand side
- doc: replay: use a nested description list
- doc: replay: improve config description
- doc: link to config for git-replay(1)
Doc update for "git replay" to actually refer to its configuration
variables.
Needs review.
source: <V3_CV_doc_replay_config.780@msgid.xyz>
* hn/status-pull-advice-qualified (2026-05-21) 1 commit
(merged to 'next' on 2026-06-15 at 898a4df940)
+ remote: qualify "git pull" advice for non-upstream compareBranches
Advice shown by "git status" when the local branch is behind or has
diverged from its push branch has been updated to suggest "git pull
<remote> <branch>".
Will cook in 'next'.
cf. <xmqq7bo6xuok.fsf@gitster.g>
source: <pull.2301.v4.git.git.1779372367317.gitgitgadget@gmail.com>
* hn/branch-delete-merged (2026-06-24) 7 commits
- branch: add --dry-run for --delete-merged
- branch: add branch.<name>.deleteMerged opt-out
- branch: add --delete-merged <branch>
- branch: prepare delete_branches for a bulk caller
- branch: let delete_branches skip unmerged branches on bulk refusal
- branch: convert delete_branches() to a flags argument
- branch: add --forked filter for --list mode
"git branch" command learned "--delete-merged" option to remove
local branches that have already been merged to the remote-tracking
branches they track.
Needs review.
source: <pull.2285.v18.git.git.1782338106.gitgitgadget@gmail.com>
* cc/promisor-auto-config-url-more (2026-05-27) 8 commits
(merged to 'next' on 2026-06-15 at d1c99e75cc)
+ doc: promisor: improve acceptFromServer entry
+ promisor-remote: auto-configure unknown remotes
+ promisor-remote: trust known remotes matching acceptFromServerUrl
+ promisor-remote: introduce promisor.acceptFromServerUrl
+ promisor-remote: add 'local_name' to 'struct promisor_info'
+ urlmatch: add url_normalize_pattern() helper
+ urlmatch: change 'allow_globs' arg to bool
+ t5710: simplify 'mkdir X' followed by 'git -C X init'
The handling of promisor-remote protocol capability has been
loosened to allow the other side to add to the list of promisor
remotes via the promisor.acceptFromServerURL configuration
variable.
Will cook in 'next'.
cf. <877bo7294j.fsf@emacs.iotcl.com>
cf. <xmqqh5naxwfc.fsf@gitster.g>
source: <20260527140820.1438165-1-christian.couder@gmail.com>
* hn/checkout-track-fetch (2026-06-24) 2 commits
- checkout: extend --track with a "fetch" mode to refresh start-point
- branch: expose helpers for finding the remote owning a tracking ref
"git checkout --track=..." learned to optionally fetch the branch
from the remote the new branch will work with.
Waiting for response(s) to review comment(s).
cf. <12998c3a-ff69-4a98-9ed6-18aa0224e75e@gmail.com>
source: <pull.2281.v15.git.git.1782338098.gitgitgadget@gmail.com>
* en/ort-harden-against-corrupt-trees (2026-06-13) 5 commits
(merged to 'next' on 2026-06-18 at e51bee59ca)
+ cache-tree: fix verify_cache() to catch non-adjacent D/F conflicts
+ merge-ort: abort merge when trees have duplicate entries
+ merge-ort: free diff pairs queue in clear_or_reinit_internal_opts()
+ merge-ort: drop unnecessary show_all_errors from collect_merge_info()
+ merge-ort: propagate callback errors from traverse_trees_wrapper()
"ort" merge backend handles merging corrupt trees better by
aborting when it should.
Will cook in 'next'.
cf. <xmqq5x3ldu4h.fsf@gitster.g>
source: <pull.2096.v2.git.1781419047.gitgitgadget@gmail.com>
* pw/status-rebase-todo (2026-06-23) 2 commits
(merged to 'next' on 2026-06-23 at a0fcde09dc)
+ status: improve rebase todo list parsing
+ sequencer: factor out parsing of todo commands
The display of the rebase todo list in "git status" has been
improved to correctly abbreviate object IDs for more commands and
avoid misinterpreting refs as object IDs.
Will cook in 'next'.
source: <cover.1782230024.git.phillip.wood@dunelm.org.uk>
* ps/shift-root-in-graph (2026-06-20) 3 commits
- graph: indent visual root in graph
- revision: add peek functions for lookahead
- lib-log-graph: move check_graph function
"git log --graph" has been modified to visually distinguish
parentless "root" commits (and commits that become roots due to
history simplification) by indenting them, preventing them from
appearing falsely related to unrelated commits rendered immediately
above them.
Waiting for response(s) to review comment(s).
The peek-ahead approach may need to be scratched.
cf. <CAN5EUNSj-2hkEBF7N_M6RLsuujDNFNUF3w53zR7SN1_5i2BRyg@mail.gmail.com>
cf. <CAL71e4OQ_kGb+UwHgikHG236-8BVtc7P9OdpV4i4UzYRCoPczw@mail.gmail.com>
source: <20260620-ps-pre-commit-indent-v6-0-cdc6d8fd5fbc@gmail.com>
^ permalink raw reply
* Re: [RFH] Why do osx CI jobs so unreliable?
From: Michael Montalbo @ 2026-06-26 3:27 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: Jeff King, git, Junio C Hamano
In-Reply-To: <ajkOoRhqaAcy6gBg@pks.im>
Patrick Steinhardt <ps@pks.im> writes:
> I think the issue is rather simple: we're hitting timeouts in Apache.
> [...]
> This is because our keepalive mechanisms aren't helping [...]
> Whether that's the same issue like we see in macOS sometimes is a
> different question.
I think that is the trigger for issues we've been seeing. I spent
some time investigating the Apache side over the last week and maybe
found a mod_http2 bug, which I filed upstream with a potential fix:
bug: https://bz.apache.org/bugzilla/show_bug.cgi?id=70131
fix: https://github.com/mmontalbo/httpd/pull/2
To Patrick's earlier question of whether this is a Git, curl, or Apache
bug: as best I can tell it's Apache. I could reproduce it with no Git
involved at all (just Apache and a small CGI that goes quiet past the
Timeout), and across several curl versions (8.6.0, which is what the
GitHub runners use, up to 8.20.0), so I don't think bumping curl would
help. It also seems to wear two faces from the same trigger: over
HTTP/1.1 Apache closes the connection and curl bails with the
"transfer closed" error (which looks like what you hit with Timeout=1,
and the recent failures on both macOS and Linux), and over HTTP/2 it
does not reliably reset the stream, so the client just waits, which is
the six-hour macOS hang. I share the pessimism from earlier in the
thread, though: I think the real fix is upstream in Apache, and
anything we do on our side mostly just bounds the symptom in the
meantime.
Given there could be a potential reliability issue with an upstream
dependency like Apache, I was considering what mitigation strategies
might help:
- Enforce some kind of lower bound speed limit and a client-side
timeout so runs that wedge fail fast (and loudly) instead of
hanging.
- Potentially provide some affordance for retrying flaky tests
that might fail due to upstream dependencies. Git already has
some HTTP retry support (http.maxRetries and friends, added
recently), but as far as I can tell it only triggers on HTTP 429
rate limiting, so it would not catch a stall like this on its
own. A test-level retry is not something I like that much, since
it might encourage papering over flakiness that should be
resolved, but it was a consideration vs requiring a fresh CI run
to resolve the flake.
- Make slow tests faster by optimizing the test itself and/or
the test runner configuration (e.g., job number matching
cores) so wedges become less likely.
For the first one, I think Git already provides some affordances. There
is a stall-based timeout that just ships disabled: as I understand it
http.lowSpeedLimit sets a bytes/sec floor and http.lowSpeedTime how long
a transfer can sit below it before curl gives up, so it would catch a
wedged connection without punishing one that is just slow. Enabling it
for the http tests might look something like:
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
@@ GIT_TRACE=$GIT_TRACE; export GIT_TRACE
+# Abort a transfer that makes essentially no progress for a while,
+# so a wedged connection fails in seconds instead of hanging to the
+# job cap. Tiny limit, generous window, so it only trips on a true
+# stall; override either var, or set the limit to 0, to disable.
+GIT_HTTP_LOW_SPEED_LIMIT=${GIT_HTTP_LOW_SPEED_LIMIT-1}
+GIT_HTTP_LOW_SPEED_TIME=${GIT_HTTP_LOW_SPEED_TIME-60}
+export GIT_HTTP_LOW_SPEED_LIMIT GIT_HTTP_LOW_SPEED_TIME
I went conservative on the values on purpose: a floor of 1 byte/sec
should only really fire on a true zero-progress stall, not on something
that is just crawling on a slow runner, and the 60s window is generous
for the same reason. When I tried it locally against a stall-proxy it
did turn an otherwise indefinite hang into a bounded abort (a tighter
limit/window brings that down to single-digit seconds). It probably does
not need to be suite-wide either; it could be scoped per-command with
git -c, which the http tests already lean on for this kind of thing
(t5551 passes http.postbuffer and http.extraheader that way), if a
narrower blast radius feels safer.
I only dug into the first option in any depth, since I wanted to
sanity-check the direction before writing patches. Does turning on a
stall timeout for the http tests seem reasonable? Are there other
strategies that we should implement?
^ permalink raw reply
* Re: [PATCH v6 00/11] refs: fix "onbranch" conditions
From: Jeff King @ 2026-06-26 5:06 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: git, Karthik Nayak, Justin Tobler
In-Reply-To: <20260625-b4-pks-refs-avoid-chdir-notify-reparent-v6-0-41fbca3cf5e3@pks.im>
On Thu, Jun 25, 2026 at 11:19:58AM +0200, Patrick Steinhardt wrote:
> - Fix the "onbranch" recursion properly: instead of papering over the
> issue, this series now refactors reference store initialization to
> not read any configuration at all anymore. Instead, the config is
> now parsed lazily. This fixes the recursion, but also makes us
> respect configuration guarded by "onbranch" conditions properly.
Sorry, I was offline and missed reviewing some of the intermediate
stages.
The approach you take in v6 looks good to me, and I'm glad the result
does not look too painful to maintain. If we ever add a config option
that is absolutely required for initializing the reading side of the
backends, we'll be back to our chicken-and-egg problem. But I won't be
surprised if that never happens, and if it does, we can decide on the
user-visible interaction with onbranch includes then (and whatever the
result is, document it).
Thanks for taking the time to re-work all of this.
-Peff
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox