Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
c9ef360
t1800: add hook output stream tests
10ne1 Jan 28, 2026
dee8286
run-command: add helper for pp child states
10ne1 Jan 28, 2026
ec0beca
run-command: add stdin callback for parallelization
nasamuffin Jan 28, 2026
33e5914
hook: provide stdin via callback
nasamuffin Jan 28, 2026
e8ee80c
hook: convert 'post-rewrite' hook in sequencer.c to hook API
nasamuffin Jan 28, 2026
d816637
hook: allow separate std[out|err] streams
10ne1 Jan 28, 2026
9ac9612
transport: convert pre-push to hook API
nasamuffin Jan 28, 2026
b7b2157
reference-transaction: use hook API instead of run-command
10ne1 Jan 28, 2026
c549a40
hook: add jobs option
10ne1 Jan 28, 2026
c45a34e
run-command: poll child input in addition to output
10ne1 Jan 28, 2026
fc148b1
receive-pack: convert update hooks to new API
nasamuffin Jan 28, 2026
b5e9ad5
receive-pack: convert receive hooks to hook API
nasamuffin Jan 28, 2026
37196d8
read-cache: update add_files_to_cache take param ignored_too
bicschneider Feb 6, 2026
a16c4a2
read-cache: submodule add need --force given ignore=all configuration
bicschneider Feb 6, 2026
297a27f
tests: t2206-add-submodule-ignored: ignore=all and add --force tests
bicschneider Feb 6, 2026
9020132
tests: fix existing tests when add an ignore=all submodule
bicschneider Feb 6, 2026
6cc6d1b
Documentation: update add --force option + ignore=all config
bicschneider Feb 6, 2026
4fa8cfd
Merge branch 'ps/for-each-ref-in-fixes' into ps/refs-for-each
gitster Feb 20, 2026
57fa316
refs: remove unused `refs_for_each_include_root_ref()`
pks-t Feb 23, 2026
7543920
refs: move `refs_head_ref_namespaced()`
pks-t Feb 23, 2026
1c3aff3
refs: move `do_for_each_ref_flags` further up
pks-t Feb 23, 2026
8f0720a
refs: rename `do_for_each_ref_flags`
pks-t Feb 23, 2026
635f08b
refs: rename `each_ref_fn`
pks-t Feb 23, 2026
aefcc9b
refs: introduce `refs_for_each_ref_ext`
pks-t Feb 23, 2026
daf01b1
refs: speed up `refs_for_each_glob_ref_in()`
pks-t Feb 23, 2026
5387919
refs: generalize `refs_for_each_namespaced_ref()`
pks-t Feb 23, 2026
f503bb7
refs: generalize `refs_for_each_fullref_in_prefixes()`
pks-t Feb 23, 2026
5507200
refs: improve verification for-each-ref options
pks-t Feb 23, 2026
00be226
refs: replace `refs_for_each_ref_in()`
pks-t Feb 23, 2026
6703408
refs: replace `refs_for_each_rawref()`
pks-t Feb 23, 2026
5ef6d59
refs: replace `refs_for_each_rawref_in()`
pks-t Feb 23, 2026
4091d29
refs: replace `refs_for_each_glob_ref_in()`
pks-t Feb 23, 2026
3fc1ad0
refs: replace `refs_for_each_glob_ref()`
pks-t Feb 23, 2026
96c35a9
refs: replace `refs_for_each_namespaced_ref()`
pks-t Feb 23, 2026
1dd4f1e
refs: replace `refs_for_each_fullref_in()`
pks-t Feb 23, 2026
a66c8c7
repo: remove unnecessary variable shadow
jayatheerthkulkarni Feb 23, 2026
1a9df8d
diff: handle ANSI escape codes in prefix when calculating diffstat width
LorenzoPegorari Feb 27, 2026
064b869
t4052: test for diffstat width when prefix contains ANSI escape codes
LorenzoPegorari Feb 27, 2026
005f3fb
builtin/receive-pack: avoid spinning no-op sideband async threads
10ne1 Mar 2, 2026
4aa72ea
.mailmap: update email address for Tian Yuchen
malon7782 Mar 8, 2026
5c56c72
Merge branch 'ar/run-command-hook-take-2'
gitster Mar 9, 2026
d445aec
Merge branch 'ps/refs-for-each'
gitster Mar 9, 2026
3fe08b8
Merge branch 'cs/add-skip-submodule-ignore-all'
gitster Mar 9, 2026
e757df8
Merge branch 'lp/diff-stat-utf8-display-width-fix'
gitster Mar 9, 2026
676c145
Merge branch 'jk/repo-structure-cleanup'
gitster Mar 9, 2026
d181b93
The 13th batch
gitster Mar 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .mailmap
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ Thomas Ackermann <th.acker@arcor.de> <th.acker66@arcor.de>
Thomas Rast <tr@thomasrast.ch> <trast@student.ethz.ch>
Thomas Rast <tr@thomasrast.ch> <trast@inf.ethz.ch>
Thomas Rast <tr@thomasrast.ch> <trast@google.com>
Tian Yuchen <cat@malon.dev> <a3205153416@gmail.com>
Timo Hirvonen <tihirvon@gmail.com> <tihirvon@ee.oulu.fi>
Toby Allsopp <Toby.Allsopp@navman.co.nz> <toby.allsopp@navman.co.nz>
Tom Grennan <tmgrennan@gmail.com> <tgrennan@redback.com>
Expand Down
14 changes: 14 additions & 0 deletions Documentation/RelNotes/2.54.0.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ UI, Workflows & Features
* "git config list" is taught to show the values interpreted for
specific type with "--type=<X>" option.

* "git add <submodule>" has been taught to honor
submodule.<name>.ignore that is set to "all" (and requires "git add
-f" to override it).


Performance, Internal Implementation, Development Support etc.
--------------------------------------------------------------
Expand Down Expand Up @@ -143,6 +147,11 @@ Performance, Internal Implementation, Development Support etc.
were kept track of by a single global variable in-core, which has
been corrected by moving it to per-repository data structure.

* Use the hook API to replace ad-hoc invocation of hook scripts via
the run_command() API.

* Code refactoring around refs-for-each-* API functions.


Fixes since v2.53
-----------------
Expand Down Expand Up @@ -234,6 +243,10 @@ Fixes since v2.53
to access pack data by "fsck" has been updated to avoid this.
(merge 13eb65d366 ps/fsck-stream-from-the-right-object-instance later to maint).

* "git log --graph --stat" did not count the display width of colored
graph part of its own output correctly, which has been corrected.
(merge 064b869efc lp/diff-stat-utf8-display-width-fix later to maint).

* Other code cleanup, docfix, build fix, etc.
(merge d79fff4a11 jk/remote-tracking-ref-leakfix later to maint).
(merge 7a747f972d dd/t5403-modernise later to maint).
Expand Down Expand Up @@ -264,3 +277,4 @@ Fixes since v2.53
(merge ed84bc1c0d kh/doc-patch-id-4 later to maint).
(merge 7451864bfa sc/pack-redundant-leakfix later to maint).
(merge f87593ab1a cx/fetch-display-ubfix later to maint).
(merge a66c8c7f91 jk/repo-structure-cleanup later to maint).
13 changes: 7 additions & 6 deletions Documentation/config/submodule.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,16 @@ submodule.<name>.fetchRecurseSubmodules::

submodule.<name>.ignore::
Defines under what circumstances "git status" and the diff family show
a submodule as modified. When set to "all", it will never be considered
modified (but it will nonetheless show up in the output of status and
commit when it has been staged), "dirty" will ignore all changes
to the submodule's work tree and
a submodule as modified.
When set to "all" will never consider the submodule modified. It can
nevertheless be staged using the option --force and it will then show up
in the output of status.
When set to "dirty" will ignore all changes to the submodule's work tree and
takes only differences between the HEAD of the submodule and the commit
recorded in the superproject into account. "untracked" will additionally
let submodules with modified tracked files in their work tree show up.
Using "none" (the default when this option is not set) also shows
submodules that have untracked files in their work tree as changed.
When set to "none"(default) It also show submodules as changed if they have
untracked files in their work tree.
This setting overrides any setting made in .gitmodules for this submodule,
both settings can be overridden on the command line by using the
"--ignore-submodules" option. The 'git submodule' commands are not
Expand Down
5 changes: 4 additions & 1 deletion Documentation/git-add.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ in linkgit:gitglossary[7].

`-f`::
`--force`::
Allow adding otherwise ignored files.
Allow adding otherwise ignored files. The option is also used when
`submodule.<name>.ignore=all` is set, but you want to stage an
update of the submodule. The `path` to the submodule must be explicitly
specified.

`--sparse`::
Allow updating index entries outside of the sparse-checkout cone.
Expand Down
5 changes: 4 additions & 1 deletion Documentation/gitmodules.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ submodule.<name>.ignore::
--
all;; The submodule will never be considered modified (but will
nonetheless show up in the output of status and commit when it has
been staged).
been staged). Add `(new commits)` can be overruled using the
`git add --force <submodule.path>`.
The setting affects `status`, `update-index`, `diff` and `log`(due
to underlaying `diff`).

dirty;; All changes to the submodule's work tree will be ignored, only
committed differences between the `HEAD` of the submodule and its
Expand Down
16 changes: 11 additions & 5 deletions bisect.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,8 +473,12 @@ static int register_ref(const struct reference *ref, void *cb_data UNUSED)

static int read_bisect_refs(void)
{
return refs_for_each_ref_in(get_main_ref_store(the_repository),
"refs/bisect/", register_ref, NULL);
struct refs_for_each_ref_options opts = {
.prefix = "refs/bisect/",
.trim_prefix = strlen("refs/bisect/"),
};
return refs_for_each_ref_ext(get_main_ref_store(the_repository),
register_ref, NULL, &opts);
}

static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")
Expand Down Expand Up @@ -1186,13 +1190,15 @@ static int mark_for_removal(const struct reference *ref, void *cb_data)

int bisect_clean_state(void)
{
struct refs_for_each_ref_options opts = {
.prefix = "refs/bisect/",
};
int result = 0;

/* There may be some refs packed during bisection */
struct string_list refs_for_removal = STRING_LIST_INIT_DUP;
refs_for_each_fullref_in(get_main_ref_store(the_repository),
"refs/bisect/", NULL, mark_for_removal,
&refs_for_removal);
refs_for_each_ref_ext(get_main_ref_store(the_repository),
mark_for_removal, &refs_for_removal, &opts);
string_list_append(&refs_for_removal, "BISECT_HEAD");
string_list_append(&refs_for_removal, "BISECT_EXPECTED_REV");
result = refs_delete_refs(get_main_ref_store(the_repository),
Expand Down
2 changes: 1 addition & 1 deletion builtin/add.c
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ int cmd_add(int argc,
else
exit_status |= add_files_to_cache(repo, prefix,
&pathspec, ps_matched,
include_sparse, flags);
include_sparse, flags, ignored_too);

if (take_worktree_changes && !add_renormalize && !ignore_add_errors &&
report_path_error(ps_matched, &pathspec))
Expand Down
37 changes: 27 additions & 10 deletions builtin/bisect.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,13 +422,17 @@ static void bisect_status(struct bisect_state *state,
{
char *bad_ref = xstrfmt("refs/bisect/%s", terms->term_bad);
char *good_glob = xstrfmt("%s-*", terms->term_good);
struct refs_for_each_ref_options opts = {
.pattern = good_glob,
.prefix = "refs/bisect/",
.trim_prefix = strlen("refs/bisect/"),
};

if (refs_ref_exists(get_main_ref_store(the_repository), bad_ref))
state->nr_bad = 1;

refs_for_each_glob_ref_in(get_main_ref_store(the_repository), inc_nr,
good_glob, "refs/bisect/",
(void *) &state->nr_good);
refs_for_each_ref_ext(get_main_ref_store(the_repository),
inc_nr, &state->nr_good, &opts);

free(good_glob);
free(bad_ref);
Expand Down Expand Up @@ -562,6 +566,10 @@ static int add_bisect_ref(const struct reference *ref, void *cb)

static int prepare_revs(struct bisect_terms *terms, struct rev_info *revs)
{
struct refs_for_each_ref_options opts = {
.prefix = "refs/bisect/",
.trim_prefix = strlen("refs/bisect/"),
};
int res = 0;
struct add_bisect_ref_data cb = { revs };
char *good = xstrfmt("%s-*", terms->term_good);
Expand All @@ -581,11 +589,16 @@ static int prepare_revs(struct bisect_terms *terms, struct rev_info *revs)
reset_revision_walk();
repo_init_revisions(the_repository, revs, NULL);
setup_revisions(0, NULL, revs, NULL);
refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
add_bisect_ref, bad, "refs/bisect/", &cb);

opts.pattern = bad;
refs_for_each_ref_ext(get_main_ref_store(the_repository),
add_bisect_ref, &cb, &opts);

cb.object_flags = UNINTERESTING;
refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
add_bisect_ref, good, "refs/bisect/", &cb);
opts.pattern = good;
refs_for_each_ref_ext(get_main_ref_store(the_repository),
add_bisect_ref, &cb, &opts);

if (prepare_revision_walk(revs))
res = error(_("revision walk setup failed"));

Expand Down Expand Up @@ -1191,10 +1204,14 @@ static int verify_good(const struct bisect_terms *terms, const char *command)
char *good_glob = xstrfmt("%s-*", terms->term_good);
int no_checkout = refs_ref_exists(get_main_ref_store(the_repository),
"BISECT_HEAD");
struct refs_for_each_ref_options opts = {
.pattern = good_glob,
.prefix = "refs/bisect/",
.trim_prefix = strlen("refs/bisect/"),
};

refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
get_first_good, good_glob, "refs/bisect/",
&good_rev);
refs_for_each_ref_ext(get_main_ref_store(the_repository),
get_first_good, &good_rev, &opts);
free(good_glob);

if (refs_read_ref(get_main_ref_store(the_repository), no_checkout ? "BISECT_HEAD" : "HEAD", &current_rev))
Expand Down
2 changes: 1 addition & 1 deletion builtin/checkout.c
Original file line number Diff line number Diff line change
Expand Up @@ -888,7 +888,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
*/

add_files_to_cache(the_repository, NULL, NULL, NULL, 0,
0);
0, 0);
init_ui_merge_options(&o, the_repository);
o.verbosity = 0;
work = write_in_core_index_as_tree(the_repository);
Expand Down
2 changes: 1 addition & 1 deletion builtin/commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
repo_hold_locked_index(the_repository, &index_lock,
LOCK_DIE_ON_ERROR);
add_files_to_cache(the_repository, also ? prefix : NULL,
&pathspec, ps_matched, 0, 0);
&pathspec, ps_matched, 0, 0, 0 );
if (!all && report_path_error(ps_matched, &pathspec))
exit(128);

Expand Down
7 changes: 5 additions & 2 deletions builtin/describe.c
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,9 @@ int cmd_describe(int argc,
const char *prefix,
struct repository *repo UNUSED )
{
struct refs_for_each_ref_options for_each_ref_opts = {
.flags = REFS_FOR_EACH_INCLUDE_BROKEN,
};
int contains = 0;
struct option options[] = {
OPT_BOOL(0, "contains", &contains, N_("find the tag that comes after the commit")),
Expand Down Expand Up @@ -738,8 +741,8 @@ int cmd_describe(int argc,
}

hashmap_init(&names, commit_name_neq, NULL, 0);
refs_for_each_rawref(get_main_ref_store(the_repository), get_name,
NULL);
refs_for_each_ref_ext(get_main_ref_store(the_repository),
get_name, NULL, &for_each_ref_opts);
if (!hashmap_get_size(&names) && !always)
die(_("No names found, cannot describe anything."));

Expand Down
7 changes: 5 additions & 2 deletions builtin/fetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -1541,6 +1541,9 @@ static void add_negotiation_tips(struct git_transport_options *smart_options)

for (i = 0; i < negotiation_tip.nr; i++) {
const char *s = negotiation_tip.items[i].string;
struct refs_for_each_ref_options opts = {
.pattern = s,
};
int old_nr;
if (!has_glob_specials(s)) {
struct object_id oid;
Expand All @@ -1552,8 +1555,8 @@ static void add_negotiation_tips(struct git_transport_options *smart_options)
continue;
}
old_nr = oids->nr;
refs_for_each_glob_ref(get_main_ref_store(the_repository),
add_oid, s, oids);
refs_for_each_ref_ext(get_main_ref_store(the_repository),
add_oid, oids, &opts);
if (old_nr == oids->nr)
warning("ignoring --negotiation-tip=%s because it does not match any refs",
s);
Expand Down
7 changes: 5 additions & 2 deletions builtin/fsck.c
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,9 @@ static int fsck_handle_ref(const struct reference *ref, void *cb_data UNUSED)

static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
{
struct refs_for_each_ref_options opts = {
.flags = REFS_FOR_EACH_INCLUDE_BROKEN,
};
struct worktree **worktrees, **p;
const char *head_points_at;
struct object_id head_oid;
Expand All @@ -607,8 +610,8 @@ static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
return;
}

refs_for_each_rawref(get_main_ref_store(the_repository),
snapshot_ref, snap);
refs_for_each_ref_ext(get_main_ref_store(the_repository),
snapshot_ref, snap, &opts);

worktrees = get_worktrees();
for (p = worktrees; *p; p++) {
Expand Down
Loading