Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
8cafc30
add -p: show user's hunk decision when selecting hunks
devdekunle Jan 8, 2026
b60f7d8
submodule--helper: use submodule_name_to_gitdir in add_submodule
10ne1 Jan 12, 2026
05a1cdb
submodule: always validate gitdirs inside submodule_name_to_gitdir
10ne1 Jan 12, 2026
34206ca
builtin/submodule--helper: add gitdir command
10ne1 Jan 12, 2026
4173df5
submodule: introduce extensions.submodulePathConfig
10ne1 Jan 12, 2026
c349bad
submodule: allow runtime enabling extensions.submodulePathConfig
10ne1 Jan 12, 2026
e14349d
submodule--helper: add gitdir migration command
10ne1 Jan 12, 2026
226694b
builtin/credential-store: move is_rfc3986_unreserved to url.[ch]
10ne1 Jan 12, 2026
920fbe4
submodule--helper: fix filesystem collisions by encoding gitdir paths
10ne1 Jan 12, 2026
1685bba
submodule: fix case-folding gitdir filesystem collisions
10ne1 Jan 12, 2026
82c36fa
submodule: hash the submodule name for the gitdir path
10ne1 Jan 12, 2026
e897c9b
submodule: detect conflicts with existing gitdir configs
10ne1 Jan 12, 2026
1954b94
t5403: introduce check_post_checkout helper function
deveshidwivedi Jan 12, 2026
7a747f9
t5403: use test_cmp for post-checkout argument checks
deveshidwivedi Jan 12, 2026
8102187
doc: MyFirstContribution: fix missing dependencies and clarify build …
shreyp135 Jan 12, 2026
ed0f7a6
remote-curl: use auth for probe_rpc() requests too
aaronp24 Jan 14, 2026
f85b49f
diff: improve scaling of filenames in diffstat to handle UTF-8 chars
LorenzoPegorari Jan 16, 2026
04f5d95
t4073: add test for diffstat paths length when containing UTF-8 chars
LorenzoPegorari Jan 16, 2026
9500b21
remote: return non-const pointer from error_buf()
peff Jan 19, 2026
782a719
remote: drop const return of tracking_for_push_dest()
peff Jan 19, 2026
9bf9eed
remote: fix leak in branch_get_push_1() with invalid "simple" config
peff Jan 19, 2026
d79fff4
remote: always allocate branch.push_tracking_ref
peff Jan 19, 2026
b143f0f
last-modified: clarify in the docs the command takes a pathspec
To1ne Jan 20, 2026
209574d
last-modified: document option '-z'
To1ne Jan 20, 2026
9bfaf78
last-modified: document option '--max-depth'
To1ne Jan 20, 2026
9dcc09b
last-modified: change default max-depth to 0
To1ne Jan 20, 2026
4922359
sparse-checkout: optimize string_list construction and add tests to v…
amishhaa Jan 21, 2026
a824421
t5500: simplify test implementation and fix git exit code suppression
shreyp135 Jan 21, 2026
2b53e8b
Merge branch 'jk/remote-tracking-ref-leakfix'
gitster Feb 5, 2026
ae78735
Merge branch 'aa/add-p-previous-decisions'
gitster Feb 5, 2026
c3a5261
Merge branch 'ar/submodule-gitdir-tweak'
gitster Feb 5, 2026
4ae96a4
Merge branch 'ap/http-probe-rpc-use-auth'
gitster Feb 5, 2026
d62717b
Merge branch 'dd/t5403-modernise'
gitster Feb 5, 2026
b77c91a
Merge branch 'sp/myfirstcontribution-include-update'
gitster Feb 5, 2026
d83491a
Merge branch 'ac/sparse-checkout-string-list-cleanup'
gitster Feb 5, 2026
1f17604
Merge branch 'lp/diff-stat-utf8-display-width-fix'
gitster Feb 5, 2026
7758f84
Merge branch 'tc/last-modified-options-cleanup'
gitster Feb 5, 2026
96614e7
Merge branch 'sp/t5500-cleanup'
gitster Feb 5, 2026
3e0db84
Start 2.54 cycle
gitster Feb 5, 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
15 changes: 9 additions & 6 deletions Documentation/MyFirstContribution.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,8 @@ on the command line, including the name of our command. (If `prefix` is empty
for you, try `cd Documentation/ && ../bin-wrappers/git psuh`). That's not so
helpful. So what other context can we get?

Add a line to `#include "config.h"` and `#include "repository.h"`.
Add a line to `#include "config.h"`, `#include "repository.h"` and
`#include "environment.h"`.
Then, add the following bits to the function body:
function body:

Expand Down Expand Up @@ -429,6 +430,7 @@ Add the following includes:
----
#include "commit.h"
#include "pretty.h"
#include "strbuf.h"
----

Then, add the following lines within your implementation of `cmd_psuh()` near
Expand Down Expand Up @@ -503,8 +505,8 @@ git-psuh - Delight users' typo with a shy horse

SYNOPSIS
--------
[verse]
'git-psuh [<arg>...]'
[synopsis]
git psuh [<arg>...]

DESCRIPTION
-----------
Expand Down Expand Up @@ -726,9 +728,10 @@ $ prove -j$(nproc) --shuffle t[0-9]*.sh
----

NOTE: You can also do this with `make test` or use any testing harness which can
speak TAP. `prove` can run concurrently. `shuffle` randomizes the order the
tests are run in, which makes them resilient against unwanted inter-test
dependencies. `prove` also makes the output nicer.
speak TAP. `prove` can run concurrently. `-j$(nproc)` runs tests using all
available CPUs in parallel, but the job count can be adjusted as needed.
`shuffle` randomizes the order the tests are run in, which makes them resilient
against unwanted inter-test dependencies. `prove` also makes the output nicer.

Go ahead and commit this change, as well.

Expand Down
39 changes: 39 additions & 0 deletions Documentation/RelNotes/2.54.0.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Git v2.54 Release Notes
=======================

UI, Workflows & Features
------------------------

* "git add -p" and friends note what the current status of the hunk
being shown is.


Performance, Internal Implementation, Development Support etc.
--------------------------------------------------------------

* Avoid local submodule repository directory paths overlapping with
each other by encoding submodule names before using them as path
components.


Fixes since v2.53
-----------------

* HTTP transport failed to authenticate in some code paths, which has
been corrected.
(merge ed0f7a62f7 ap/http-probe-rpc-use-auth later to maint).

* The computation of column width made by "git diff --stat" was
confused when pathnames contain non-ASCII characters.
(merge 04f5d95ef7 lp/diff-stat-utf8-display-width-fix later to maint).

* The "-z" and "--max-depth" documentation (and implementation of
"-z") in the "git last-modified" command have been updated.
(merge 9dcc09bed1 tc/last-modified-options-cleanup 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).
(merge 81021871ea sp/myfirstcontribution-include-update later to maint).
(merge 49223593fd ac/sparse-checkout-string-list-cleanup later to maint).
(merge a824421d36 sp/t5500-cleanup later to maint).
29 changes: 29 additions & 0 deletions Documentation/config/extensions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,35 @@ relativeWorktrees:::
repaired with either the `--relative-paths` option or with the
`worktree.useRelativePaths` config set to `true`.

submodulePathConfig:::
This extension is for the minority of users who:
+
--
* Encounter errors like `refusing to create ... in another submodule's git dir`
due to a number of reasons, like case-insensitive filesystem conflicts when
creating modules named `foo` and `Foo`.
* Require more flexible submodule layouts, for example due to nested names like
`foo`, `foo/bar` and `foo/baz` not supported by the default gitdir mechanism
which uses `.git/modules/<plain-name>` locations, causing further conflicts.
--
+
When `extensions.submodulePathConfig` is enabled, the `submodule.<name>.gitdir`
config becomes the single source of truth for all submodule gitdir paths and is
automatically set for all new submodules both during clone and init operations.
+
Git will error out if a module does not have a corresponding
`submodule.<name>.gitdir` set.
+
Existing (pre-extension) submodules need to be migrated by adding the missing
config entries. This can be done manually, e.g. for each submodule:
`git config submodule.<name>.gitdir .git/modules/<name>`, or via the
`git submodule--helper migrate-gitdir-configs` command which iterates over all
submodules and attempts to migrate them.
+
The extension can be enabled automatically for new repositories by setting
`init.defaultSubmodulePathConfig` to `true`, for example by running
`git config --global init.defaultSubmodulePathConfig true`.

worktreeConfig:::
If enabled, then worktrees will load config settings from the
`$GIT_DIR/config.worktree` file in addition to the
Expand Down
6 changes: 6 additions & 0 deletions Documentation/config/init.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ endif::[]
See `--ref-format=` in linkgit:git-init[1]. Both the command line
option and the `GIT_DEFAULT_REF_FORMAT` environment variable take
precedence over this config.

init.defaultSubmodulePathConfig::
A boolean that specifies if `git init` and `git clone` should
automatically set `extensions.submodulePathConfig` to `true`. This
allows all new repositories to automatically use the submodule path
extension. Defaults to `false` when unset.
7 changes: 7 additions & 0 deletions Documentation/config/submodule.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ submodule.<name>.active::
submodule.active config option. See linkgit:gitsubmodules[7] for
details.

submodule.<name>.gitdir::
This sets the gitdir path for submodule <name>. This configuration is
respected when `extensions.submodulePathConfig` is enabled, otherwise it
has no effect. When enabled, this config becomes the single source of
truth for submodule gitdir paths and Git will error if it is missing.
See linkgit:git-config[1] for details.

submodule.active::
A repeated field which contains a pathspec used to match against a
submodule's path to determine if the submodule is of interest to git
Expand Down
45 changes: 36 additions & 9 deletions Documentation/git-last-modified.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ git-last-modified - EXPERIMENTAL: Show when files were last modified
SYNOPSIS
--------
[synopsis]
git last-modified [--recursive] [--show-trees] [<revision-range>] [[--] <path>...]
git last-modified [--recursive] [--show-trees] [--max-depth=<depth>] [-z]
[<revision-range>] [[--] <pathspec>...]

DESCRIPTION
-----------
Expand All @@ -24,13 +25,23 @@ OPTIONS

`-r`::
`--recursive`::
Instead of showing tree entries, step into subtrees and show all entries
inside them recursively.
Recursively traverse into all subtrees. By default, the command only
shows tree entries matching the `<pathspec>`. With this option, it
descends into subtrees and displays all entries within them.
Equivalent to `--max-depth=-1`.

`-t`::
`--show-trees`::
Show tree entries even when recursing into them. It has no effect
without `--recursive`.
Show tree entries even when recursing into them.

`--max-depth=<depth>`::
For each pathspec given on the command line, traverse at most `<depth>`
levels into subtrees. A negative value means no limit.
The default is 0, which shows all paths matching the pathspec
without descending into subtrees.

`-z`::
Terminate each line with a _NUL_ character rather than a newline.

`<revision-range>`::
Only traverse commits in the specified revision range. When no
Expand All @@ -39,10 +50,26 @@ OPTIONS
spell `<revision-range>`, see the 'Specifying Ranges' section of
linkgit:gitrevisions[7].

`[--] <path>...`::
For each _<path>_ given, the commit which last modified it is returned.
Without an optional path parameter, all files and subdirectories
in path traversal the are included in the output.
`[--] <pathspec>...`::
Show the commit that last modified each path matching _<pathspec>_.
If no _<pathspec>_ is given, all files and subdirectories are included.
See linkgit:gitglossary[7] for details on pathspec syntax.

OUTPUT
------

The output is in the format:

------------
<oid> TAB <path> LF
------------

If a path contains any special characters, the path is C-style quoted. To
avoid quoting, pass option `-z` to terminate each line with a NUL.

------------
<oid> TAB <path> NUL
------------

SEE ALSO
--------
Expand Down
2 changes: 1 addition & 1 deletion GIT-VERSION-GEN
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/sh

DEF_VER=v2.53.0
DEF_VER=v2.53.GIT

LF='
'
Expand Down
2 changes: 1 addition & 1 deletion RelNotes
81 changes: 44 additions & 37 deletions add-patch.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ static struct patch_mode patch_mode_add = {
.apply_args = { "--cached", NULL },
.apply_check_args = { "--cached", NULL },
.prompt_mode = {
N_("Stage mode change [y,n,q,a,d%s,?]? "),
N_("Stage deletion [y,n,q,a,d%s,?]? "),
N_("Stage addition [y,n,q,a,d%s,?]? "),
N_("Stage this hunk [y,n,q,a,d%s,?]? ")
N_("Stage mode change%s [y,n,q,a,d%s,?]? "),
N_("Stage deletion%s [y,n,q,a,d%s,?]? "),
N_("Stage addition%s [y,n,q,a,d%s,?]? "),
N_("Stage this hunk%s [y,n,q,a,d%s,?]? ")
},
.edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
"will immediately be marked for staging."),
Expand All @@ -64,10 +64,10 @@ static struct patch_mode patch_mode_stash = {
.apply_args = { "--cached", NULL },
.apply_check_args = { "--cached", NULL },
.prompt_mode = {
N_("Stash mode change [y,n,q,a,d%s,?]? "),
N_("Stash deletion [y,n,q,a,d%s,?]? "),
N_("Stash addition [y,n,q,a,d%s,?]? "),
N_("Stash this hunk [y,n,q,a,d%s,?]? "),
N_("Stash mode change%s [y,n,q,a,d%s,?]? "),
N_("Stash deletion%s [y,n,q,a,d%s,?]? "),
N_("Stash addition%s [y,n,q,a,d%s,?]? "),
N_("Stash this hunk%s [y,n,q,a,d%s,?]? "),
},
.edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
"will immediately be marked for stashing."),
Expand All @@ -88,10 +88,10 @@ static struct patch_mode patch_mode_reset_head = {
.is_reverse = 1,
.index_only = 1,
.prompt_mode = {
N_("Unstage mode change [y,n,q,a,d%s,?]? "),
N_("Unstage deletion [y,n,q,a,d%s,?]? "),
N_("Unstage addition [y,n,q,a,d%s,?]? "),
N_("Unstage this hunk [y,n,q,a,d%s,?]? "),
N_("Unstage mode change%s [y,n,q,a,d%s,?]? "),
N_("Unstage deletion%s [y,n,q,a,d%s,?]? "),
N_("Unstage addition%s [y,n,q,a,d%s,?]? "),
N_("Unstage this hunk%s [y,n,q,a,d%s,?]? "),
},
.edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
"will immediately be marked for unstaging."),
Expand All @@ -111,10 +111,10 @@ static struct patch_mode patch_mode_reset_nothead = {
.apply_check_args = { "--cached", NULL },
.index_only = 1,
.prompt_mode = {
N_("Apply mode change to index [y,n,q,a,d%s,?]? "),
N_("Apply deletion to index [y,n,q,a,d%s,?]? "),
N_("Apply addition to index [y,n,q,a,d%s,?]? "),
N_("Apply this hunk to index [y,n,q,a,d%s,?]? "),
N_("Apply mode change to index%s [y,n,q,a,d%s,?]? "),
N_("Apply deletion to index%s [y,n,q,a,d%s,?]? "),
N_("Apply addition to index%s [y,n,q,a,d%s,?]? "),
N_("Apply this hunk to index%s [y,n,q,a,d%s,?]? "),
},
.edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
"will immediately be marked for applying."),
Expand All @@ -134,10 +134,10 @@ static struct patch_mode patch_mode_checkout_index = {
.apply_check_args = { "-R", NULL },
.is_reverse = 1,
.prompt_mode = {
N_("Discard mode change from worktree [y,n,q,a,d%s,?]? "),
N_("Discard deletion from worktree [y,n,q,a,d%s,?]? "),
N_("Discard addition from worktree [y,n,q,a,d%s,?]? "),
N_("Discard this hunk from worktree [y,n,q,a,d%s,?]? "),
N_("Discard mode change from worktree%s [y,n,q,a,d%s,?]? "),
N_("Discard deletion from worktree%s [y,n,q,a,d%s,?]? "),
N_("Discard addition from worktree%s [y,n,q,a,d%s,?]? "),
N_("Discard this hunk from worktree%s [y,n,q,a,d%s,?]? "),
},
.edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
"will immediately be marked for discarding."),
Expand All @@ -157,10 +157,10 @@ static struct patch_mode patch_mode_checkout_head = {
.apply_check_args = { "-R", NULL },
.is_reverse = 1,
.prompt_mode = {
N_("Discard mode change from index and worktree [y,n,q,a,d%s,?]? "),
N_("Discard deletion from index and worktree [y,n,q,a,d%s,?]? "),
N_("Discard addition from index and worktree [y,n,q,a,d%s,?]? "),
N_("Discard this hunk from index and worktree [y,n,q,a,d%s,?]? "),
N_("Discard mode change from index and worktree%s [y,n,q,a,d%s,?]? "),
N_("Discard deletion from index and worktree%s [y,n,q,a,d%s,?]? "),
N_("Discard addition from index and worktree%s [y,n,q,a,d%s,?]? "),
N_("Discard this hunk from index and worktree%s [y,n,q,a,d%s,?]? "),
},
.edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
"will immediately be marked for discarding."),
Expand All @@ -179,10 +179,10 @@ static struct patch_mode patch_mode_checkout_nothead = {
.apply_for_checkout = 1,
.apply_check_args = { NULL },
.prompt_mode = {
N_("Apply mode change to index and worktree [y,n,q,a,d%s,?]? "),
N_("Apply deletion to index and worktree [y,n,q,a,d%s,?]? "),
N_("Apply addition to index and worktree [y,n,q,a,d%s,?]? "),
N_("Apply this hunk to index and worktree [y,n,q,a,d%s,?]? "),
N_("Apply mode change to index and worktree%s [y,n,q,a,d%s,?]? "),
N_("Apply deletion to index and worktree%s [y,n,q,a,d%s,?]? "),
N_("Apply addition to index and worktree%s [y,n,q,a,d%s,?]? "),
N_("Apply this hunk to index and worktree%s [y,n,q,a,d%s,?]? "),
},
.edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
"will immediately be marked for applying."),
Expand All @@ -202,10 +202,10 @@ static struct patch_mode patch_mode_worktree_head = {
.apply_check_args = { "-R", NULL },
.is_reverse = 1,
.prompt_mode = {
N_("Discard mode change from worktree [y,n,q,a,d%s,?]? "),
N_("Discard deletion from worktree [y,n,q,a,d%s,?]? "),
N_("Discard addition from worktree [y,n,q,a,d%s,?]? "),
N_("Discard this hunk from worktree [y,n,q,a,d%s,?]? "),
N_("Discard mode change from worktree%s [y,n,q,a,d%s,?]? "),
N_("Discard deletion from worktree%s [y,n,q,a,d%s,?]? "),
N_("Discard addition from worktree%s [y,n,q,a,d%s,?]? "),
N_("Discard this hunk from worktree%s [y,n,q,a,d%s,?]? "),
},
.edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
"will immediately be marked for discarding."),
Expand All @@ -224,10 +224,10 @@ static struct patch_mode patch_mode_worktree_nothead = {
.apply_args = { NULL },
.apply_check_args = { NULL },
.prompt_mode = {
N_("Apply mode change to worktree [y,n,q,a,d%s,?]? "),
N_("Apply deletion to worktree [y,n,q,a,d%s,?]? "),
N_("Apply addition to worktree [y,n,q,a,d%s,?]? "),
N_("Apply this hunk to worktree [y,n,q,a,d%s,?]? "),
N_("Apply mode change to worktree%s [y,n,q,a,d%s,?]? "),
N_("Apply deletion to worktree%s [y,n,q,a,d%s,?]? "),
N_("Apply addition to worktree%s [y,n,q,a,d%s,?]? "),
N_("Apply this hunk to worktree%s [y,n,q,a,d%s,?]? "),
},
.edit_hunk_hint = N_("If the patch applies cleanly, the edited hunk "
"will immediately be marked for applying."),
Expand Down Expand Up @@ -1460,6 +1460,7 @@ static int patch_update_file(struct add_p_state *s,
render_diff_header(s, file_diff, colored, &s->buf);
fputs(s->buf.buf, stdout);
for (;;) {
const char *hunk_use_decision = "";
enum {
ALLOW_GOTO_PREVIOUS_HUNK = 1 << 0,
ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK = 1 << 1,
Expand Down Expand Up @@ -1564,8 +1565,14 @@ static int patch_update_file(struct add_p_state *s,
(uintmax_t)(file_diff->hunk_nr
? file_diff->hunk_nr
: 1));
if (hunk->use != UNDECIDED_HUNK) {
if (hunk->use == USE_HUNK)
hunk_use_decision = _(" (was: y)");
else
hunk_use_decision = _(" (was: n)");
}
printf(_(s->mode->prompt_mode[prompt_mode_type]),
s->buf.buf);
hunk_use_decision, s->buf.buf);
if (*s->s.reset_color_interactive)
fputs(s->s.reset_color_interactive, stdout);
fflush(stdout);
Expand Down
Loading