Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
f584f9d
promisor-remote: prevent lazy-fetch recursion in child fetch
ptarjan Mar 11, 2026
386fe44
parseopt: extract subcommand handling from parse_options_step()
barroit Mar 16, 2026
e0245a1
help: make autocorrect handling reusable
barroit Mar 16, 2026
916b96c
help: move tty check for autocorrection to autocorrect.c
barroit Mar 16, 2026
a6e0ccb
autocorrect: use mode and delay instead of magic numbers
barroit Mar 16, 2026
f06f1f0
autocorrect: rename AUTOCORRECT_SHOW to AUTOCORRECT_HINT
barroit Mar 16, 2026
7cd07f1
autocorrect: provide config resolution API
barroit Mar 16, 2026
be9df6d
parseopt: autocorrect mistyped subcommands
barroit Mar 16, 2026
ae8b7e1
parseopt: enable subcommand autocorrection for git-remote and git-notes
barroit Mar 16, 2026
273faab
parseopt: add tests for subcommand autocorrection
barroit Mar 16, 2026
916b450
doc: document autocorrect API
barroit Mar 16, 2026
ee832e3
remote: move remote group resolution to remote.c
Unique-Usman Mar 25, 2026
aac9bf0
push: support pushing to a remote group
Unique-Usman Mar 25, 2026
5f82f4b
SQUASH??? - futureproof against the attack of the "main"
gitster Mar 27, 2026
0df739e
unpack-trees: use repository from index instead of global
jayesh0104 Mar 31, 2026
c74767b
unpack-trees: use repository from index instead of global
jayesh0104 Mar 31, 2026
f7d92bc
config: refactor include_by_gitdir() into include_by_path()
black-desk Apr 3, 2026
da1f520
config: add "worktree" and "worktree/i" includeIf conditions
black-desk Apr 3, 2026
ab16b9a
config: retry acquiring config.lock for 100ms
Mic92 Apr 3, 2026
fa1468a
promisor-remote: fix promisor.quiet to use the correct repository
trieu1162000 Apr 6, 2026
da1a90e
xdiff/xdl_cleanup_records: delete local recs pointer
ezekielnewren Apr 8, 2026
e85a416
xdiff: use unambiguous types in xdl_bogo_sqrt()
ezekielnewren Apr 8, 2026
042cefe
xdiff/xdl_cleanup_records: use unambiguous types
ezekielnewren Apr 8, 2026
59cb212
xdiff/xdl_cleanup_records: make limits more clear
ezekielnewren Apr 8, 2026
e7e8d80
xdiff/xdl_cleanup_records: make setting action easier to follow
ezekielnewren Apr 8, 2026
0ee3c64
xdiff/xdl_cleanup_records: put braces around the else clause
ezekielnewren Apr 8, 2026
c97ac79
Merge branch 'en/xdiff-cleanup-3' into pw/xdiff-shrink-memory-consump…
gitster Apr 8, 2026
9232a7a
xdiff: reduce size of action arrays
phillipwood Apr 2, 2026
77c188e
xdiff: cleanup xdl_clean_mmatch()
phillipwood Apr 2, 2026
8c9d203
xprepare: simplify error handling
phillipwood Apr 2, 2026
40c92ff
xdiff: reduce the size of array
phillipwood Apr 2, 2026
880636f
pack-write: add explanation to promisor file content
LorenzoPegorari Apr 10, 2026
1be8807
repack-promisor add helper to fill promisor file after repack
LorenzoPegorari Apr 10, 2026
a7b1056
repack-promisor: preserve content of promisor files after repack
LorenzoPegorari Apr 10, 2026
15567ce
t7700: test for promisor file content after repack
LorenzoPegorari Apr 10, 2026
e69bf3d
t7703: test for promisor file content after geometric repack
LorenzoPegorari Apr 10, 2026
174e24a
repack-promisor: add missing headers
LorenzoPegorari Apr 10, 2026
1e288cc
SQUASH???
gitster Apr 10, 2026
efbb763
t5516: fix test order flakiness
derrickstolee Apr 15, 2026
d542ba8
fetch: add --negotiation-restrict option
derrickstolee Apr 15, 2026
9596a1c
transport: rename negotiation_tips
derrickstolee Apr 15, 2026
203275d
remote: add remote.*.negotiationRestrict config
derrickstolee Apr 15, 2026
18d5475
fetch: add --negotiation-require option for negotiation
derrickstolee Apr 15, 2026
288ea6c
remote: add negotiationRequire config as default for --negotiation-re…
derrickstolee Apr 15, 2026
9f67318
send-pack: pass negotiation config in push
derrickstolee Apr 15, 2026
6da647d
cat-file: add mailmap subcommand to --batch-command
edith007 Apr 16, 2026
166ba56
Merge branch 'jc/neuter-sideband-fixup' into jch
gitster Apr 17, 2026
7280faf
Merge branch 'sp/refs-reduce-the-repository' into jch
gitster Apr 17, 2026
a81715f
Merge branch 'ja/doc-difftool-synopsis-style' into jch
gitster Apr 17, 2026
60f7633
Merge branch 'dl/cache-tree-fully-valid-fix' into jch
gitster Apr 17, 2026
76fd325
Merge branch 'cc/promisor-auto-config-url' into jch
gitster Apr 17, 2026
ce94859
Merge branch 'ar/parallel-hooks' into jch
gitster Apr 17, 2026
57e01e5
### match next
gitster Apr 17, 2026
2b89582
Merge branch 'en/xdiff-cleanup-3' into jch
gitster Apr 17, 2026
676593c
Merge branch 'pw/xdiff-shrink-memory-consumption' into jch
gitster Apr 17, 2026
78bbd63
Merge branch 'lp/repack-propagate-promisor-debugging-info' into jch
gitster Apr 17, 2026
085f5c5
Merge branch 'bc/rust-by-default' into jch
gitster Apr 17, 2026
dfe931f
Merge branch 'jd/unpack-trees-wo-the-repository' into jch
gitster Apr 17, 2026
26056e8
Merge branch 'pt/promisor-lazy-fetch-no-recurse' into jch
gitster Apr 17, 2026
8dd4eed
Merge branch 'js/parseopt-subcommand-autocorrection' into jch
gitster Apr 17, 2026
23f10a7
Merge branch 'ua/push-remote-group' (early part) into jch
gitster Apr 17, 2026
b8191b7
Merge branch 'ua/push-remote-group' into jch
gitster Apr 17, 2026
e7d77ec
Merge branch 'sa/cat-file-batch-mailmap-switch' into jch
gitster Apr 17, 2026
878809d
Merge branch 'ds/fetch-negotiation-options' into jch
gitster Apr 17, 2026
91fd8d6
Merge branch 'cl/conditional-config-on-worktree-path' into jch
gitster Apr 17, 2026
c2c4c4c
Merge branch 'jt/config-lock-timeout' into jch
gitster Apr 17, 2026
4e88311
Merge branch 'th/promisor-quiet-per-repo' into jch
gitster Apr 17, 2026
588220a
Merge branch 'jch' of https://github.com/git/git into jch
hub966 Apr 22, 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
50 changes: 50 additions & 0 deletions Documentation/config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,48 @@ refer to linkgit:gitignore[5] for details. For convenience:
This is the same as `gitdir` except that matching is done
case-insensitively (e.g. on case-insensitive file systems)

`worktree`::
The data that follows the keyword `worktree` and a colon is used as a
glob pattern. If the working directory of the current worktree matches
the pattern, the include condition is met.
+
The worktree location is the path where files are checked out (as returned
by `git rev-parse --show-toplevel`). This is different from `gitdir`, which
matches the `.git` directory path. In a linked worktree, the worktree path
is the directory where that worktree's files are located, not the main
repository's `.git` directory.
+
The pattern can contain standard globbing wildcards and two additional
ones, `**/` and `/**`, that can match multiple path components. Please
refer to linkgit:gitignore[5] for details. For convenience:

* If the pattern starts with `~/`, `~` will be substituted with the
content of the environment variable `HOME`.

* If the pattern starts with `./`, it is replaced with the directory
containing the current config file.

* If the pattern does not start with either `~/`, `./` or `/`, `**/`
will be automatically prepended. For example, the pattern `foo/bar`
becomes `**/foo/bar` and would match `/any/path/to/foo/bar`.

* If the pattern ends with `/`, `**` will be automatically added. For
example, the pattern `foo/` becomes `foo/**`. In other words, it
matches "foo" and everything inside, recursively.
+
This condition will never match in a bare repository (which has no worktree).
+
This is useful when you need to use different `user.name`, `user.email`, or
GPG keys in different worktrees of the same repository. While
`extensions.worktreeConfig` also allows per-worktree configuration, it
requires changes inside each repository. This condition can be set in the
user's global configuration file (e.g. `~/.config/git/config`) and applies
to multiple repositories at once.

`worktree/i`::
This is the same as `worktree` except that matching is done
case-insensitively (e.g. on case-insensitive file systems)

`onbranch`::
The data that follows the keyword `onbranch` and a colon is taken to be a
pattern with standard globbing wildcards and two additional
Expand Down Expand Up @@ -244,6 +286,14 @@ Example
[includeIf "gitdir:~/to/group/"]
path = /path/to/foo.inc

; include if the worktree is at /path/to/project-build
[includeIf "worktree:/path/to/project-build"]
path = build-config.inc

; include for all worktrees inside /path/to/group
[includeIf "worktree:/path/to/group/"]
path = group-config.inc

; relative paths are always relative to the including
; file (if the condition is true); their location is not
; affected by the condition
Expand Down
40 changes: 40 additions & 0 deletions Documentation/config/remote.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,46 @@ priority configuration file (e.g. `.git/config` in a repository) to clear
the values inherited from a lower priority configuration files (e.g.
`$HOME/.gitconfig`).

remote.<name>.negotiationRestrict::
When negotiating with this remote during `git fetch` and `git push`,
restrict the commits advertised as "have" lines to only those
reachable from refs matching the given patterns. This multi-valued
config option behaves like `--negotiation-restrict` on the command
line.
+
Each value is either an exact ref name (e.g. `refs/heads/release`) or a
glob pattern (e.g. `refs/heads/release/*`). The pattern syntax is the
same as for `--negotiation-restrict`.
+
These config values are used as defaults for the `--negotiation-restrict`
command-line option. If `--negotiation-restrict` (or its synonym
`--negotiation-tip`) is specified on the command line, then the config
values are not used.

remote.<name>.negotiationRequire::
When negotiating with this remote during `git fetch` and `git push`,
the client advertises a list of commits that exist locally. In
repos with many references, this list of "haves" can be truncated.
Depending on data shape, dropping certain references may be
expensive. This multi-valued config option specifies ref patterns
whose tips should always be sent as "have" commits during fetch
negotiation with this remote.
+
Each value is either an exact ref name (e.g. `refs/heads/release`) or a
glob pattern (e.g. `refs/heads/release/*`). The pattern syntax is the same
as for `--negotiation-restrict`.
+
These config values are used as defaults for the `--negotiation-require`
command-line option. If `--negotiation-require` is specified on the
command line, then the config values are not used.
+
This option is additive with the normal negotiation process: the
negotiation algorithm still runs and advertises its own selected commits,
but the refs matching `remote.<name>.negotiationRequire` are sent
unconditionally on top of those heuristically selected commits. This
option is also used during push negotiation when `push.negotiate` is
enabled.

remote.<name>.followRemoteHEAD::
How linkgit:git-fetch[1] should handle updates to `remotes/<name>/HEAD`
when fetching using the configured refspecs of a remote.
Expand Down
27 changes: 27 additions & 0 deletions Documentation/fetch-options.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ the current repository has the same history as the source repository.
`.git/shallow`. This option updates `.git/shallow` and accepts such
refs.

`--negotiation-restrict=(<commit>|<glob>)`::
`--negotiation-tip=(<commit>|<glob>)`::
By default, Git will report, to the server, commits reachable
from all local refs to find common commits in an attempt to
Expand All @@ -58,6 +59,9 @@ the current repository has the same history as the source repository.
local ref is likely to have commits in common with the
upstream ref being fetched.
+
`--negotiation-restrict` is the preferred name for this option;
`--negotiation-tip` is accepted as a synonym.
+
This option may be specified more than once; if so, Git will report
commits reachable from any of the given commits.
+
Expand All @@ -69,6 +73,29 @@ See also the `fetch.negotiationAlgorithm` and `push.negotiate`
configuration variables documented in linkgit:git-config[1], and the
`--negotiate-only` option below.

`--negotiation-require=<revision>`::
Ensure that the given ref tip is always sent as a "have" line
during fetch negotiation, regardless of what the negotiation
algorithm selects. This is useful to guarantee that common
history reachable from specific refs is always considered, even
when `--negotiation-restrict` restricts the set of tips or when
the negotiation algorithm would otherwise skip them.
+
This option may be specified more than once; if so, each ref is sent
unconditionally.
+
The argument may be an exact ref name (e.g. `refs/heads/release`) or a
glob pattern (e.g. `refs/heads/release/{asterisk}`). The pattern syntax
is the same as for `--negotiation-restrict`.
+
If `--negotiation-restrict` is used, the have set is first restricted by
that option and then increased to include the tips specified by
`--negotiation-require`.
+
If this option is not specified on the command line, then any
`remote.<name>.negotiationRequire` config values for the current remote
are used instead.

`--negotiate-only`::
Do not fetch anything from the server, and instead print the
ancestors of the provided `--negotiation-tip=` arguments,
Expand Down
5 changes: 5 additions & 0 deletions Documentation/git-cat-file.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,11 @@ flush::
since the beginning or since the last flush was issued. When `--buffer`
is used, no output will come until a `flush` is issued. When `--buffer`
is not used, commands are flushed each time without issuing `flush`.

`mailmap (<bool>)`::
Enable or disable mailmap for subsequent commands. The `<bool>`
argument accepts the same boolean values as linkgit:git-config[1].
The mailmap data is read upon the first use and only once.
--
+

Expand Down
73 changes: 65 additions & 8 deletions Documentation/git-push.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,28 @@ git push [--all | --branches | --mirror | --tags] [--follow-tags] [--atomic] [-n

DESCRIPTION
-----------

Updates one or more branches, tags, or other references in a remote
repository from your local repository, and sends all necessary data
that isn't already on the remote.
Updates one or more branches, tags, or other references in one or more
remote repositories from your local repository, and sends all necessary
data that isn't already on the remote.

The simplest way to push is `git push <remote> <branch>`.
`git push origin main` will push the local `main` branch to the `main`
branch on the remote named `origin`.

The `<repository>` argument defaults to the upstream for the current branch,
or `origin` if there's no configured upstream.
You can also push to multiple remotes at once by using a remote group.
A remote group is a named list of remotes configured via `remotes.<name>`
in your git config:

$ git config remotes.all-remotes "origin gitlab backup"

Then `git push all-remotes` will push to `origin`, `gitlab`, and
`backup` in turn, as if you had run `git push` against each one
individually. Each remote is pushed independently using its own
push mapping configuration. There is a `remotes.<group>` entry in
the configuration file. (See linkgit:git-config[1]).

The `<repository>` argument defaults to the upstream for the current
branch, or `origin` if there's no configured upstream.

To decide which branches, tags, or other refs to push, Git uses
(in order of precedence):
Expand All @@ -55,8 +66,10 @@ OPTIONS
_<repository>_::
The "remote" repository that is the destination of a push
operation. This parameter can be either a URL
(see the section <<URLS,GIT URLS>> below) or the name
of a remote (see the section <<REMOTES,REMOTES>> below).
(see the section <<URLS,GIT URLS>> below), the name
of a remote (see the section <<REMOTES,REMOTES>> below),
or the name of a remote group
(see the section <<REMOTE-GROUPS,REMOTE GROUPS>> below).

`<refspec>...`::
Specify what destination ref to update with what source object.
Expand Down Expand Up @@ -430,6 +443,50 @@ further recursion will occur. In this case, `only` is treated as `on-demand`.

include::urls-remotes.adoc[]

[[REMOTE-GROUPS]]
REMOTE GROUPS
-------------

A remote group is a named list of remotes configured via `remotes.<name>`
in your git config:

$ git config remotes.all-remotes "r1 r2 r3"

When a group name is given as the `<repository>` argument, the push is
performed to each member remote in turn. The defining principle is:

git push <options> all-remotes <args>

is exactly equivalent to:

git push <options> r1 <args>
git push <options> r2 <args>
...
git push <options> rN <args>

where r1, r2, ..., rN are the members of `all-remotes`. No special
behaviour is added or removed — the group is purely a shorthand for
running the same push command against each member remote individually.

The behaviour upon failure depends on the kind of error encountered:

If a member remote rejects the push, for example due to a
non-fast-forward update, force needed but not given, an existing tag,
or a server-side hook refusing a ref, Git reports the error and continues
pushing to the remaining remotes in the group. The overall exit code is
non-zero if any member push fails.

If a member remote cannot be contacted at all, for example because the
repository does not exist, authentication fails, or the network is
unreachable, the push stops at that point and the remaining remotes
are not attempted.

This means the user is responsible for ensuring that the sequence of
individual pushes makes sense. If `git push r1`` would fail for a given
set of options and arguments, then `git push all-remotes` will fail in
the same way when it reaches r1. The group push does not do anything
special to make a failing individual push succeed.

OUTPUT
------

Expand Down
4 changes: 2 additions & 2 deletions Documentation/git-repack.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ other objects in that pack they already have locally.
+
Promisor packfiles are repacked separately: if there are packfiles that
have an associated ".promisor" file, these packfiles will be repacked
into another separate pack, and an empty ".promisor" file corresponding
to the new separate pack will be written.
into another separate pack, and a ".promisor" file corresponding to the
new separate pack will be written (with arbitrary contents).

-A::
Same as `-a`, unless `-d` is used. Then any unreachable
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,7 @@ LIB_OBJS += archive-tar.o
LIB_OBJS += archive-zip.o
LIB_OBJS += archive.o
LIB_OBJS += attr.o
LIB_OBJS += autocorrect.o
LIB_OBJS += base85.o
LIB_OBJS += bisect.o
LIB_OBJS += blame.o
Expand Down
89 changes: 89 additions & 0 deletions autocorrect.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#define USE_THE_REPOSITORY_VARIABLE

#include "git-compat-util.h"
#include "autocorrect.h"
#include "config.h"
#include "parse.h"
#include "strbuf.h"
#include "prompt.h"
#include "gettext.h"

static enum autocorrect_mode parse_autocorrect(const char *value)
{
switch (git_parse_maybe_bool_text(value)) {
case 1:
return AUTOCORRECT_IMMEDIATELY;
case 0:
return AUTOCORRECT_HINT;
default: /* other random text */
break;
}

if (!strcmp(value, "prompt"))
return AUTOCORRECT_PROMPT;
else if (!strcmp(value, "never"))
return AUTOCORRECT_NEVER;
else if (!strcmp(value, "immediate"))
return AUTOCORRECT_IMMEDIATELY;
else if (!strcmp(value, "show"))
return AUTOCORRECT_HINT;
else
return AUTOCORRECT_DELAY;
}

static int resolve_autocorrect(const char *var, const char *value,
const struct config_context *ctx, void *data)
{
struct autocorrect *conf = data;

if (strcmp(var, "help.autocorrect"))
return 0;

conf->mode = parse_autocorrect(value);

/*
* Disable autocorrection prompt in a non-interactive session
*/
if (conf->mode == AUTOCORRECT_PROMPT && (!isatty(0) || !isatty(2)))
conf->mode = AUTOCORRECT_NEVER;

if (conf->mode == AUTOCORRECT_DELAY) {
conf->delay = git_config_int(var, value, ctx->kvi);

if (!conf->delay)
conf->mode = AUTOCORRECT_HINT;
else if (conf->delay < 0 || conf->delay == 1)
conf->mode = AUTOCORRECT_IMMEDIATELY;
}

return 0;
}

void autocorrect_resolve(struct autocorrect *conf)
{
read_early_config(the_repository, resolve_autocorrect, conf);
}

void autocorrect_confirm(struct autocorrect *conf, const char *assumed)
{
if (conf->mode == AUTOCORRECT_IMMEDIATELY) {
fprintf_ln(stderr,
_("Continuing under the assumption that you meant '%s'."),
assumed);
} else if (conf->mode == AUTOCORRECT_PROMPT) {
char *answer;
struct strbuf msg = STRBUF_INIT;

strbuf_addf(&msg, _("Run '%s' instead [y/N]? "), assumed);
answer = git_prompt(msg.buf, PROMPT_ECHO);
strbuf_release(&msg);

if (!(starts_with(answer, "y") || starts_with(answer, "Y")))
exit(1);
} else if (conf->mode == AUTOCORRECT_DELAY) {
fprintf_ln(stderr,
_("Continuing in %0.1f seconds, assuming that you meant '%s'."),
conf->delay / 10.0, assumed);
sleep_millisec(conf->delay * 100);
}
}
Loading