* Re: 10.26
From: Aa Kk @ 2026-05-04 9:38 UTC (permalink / raw)
To: git
In-Reply-To: <05948FB0-CE3E-4111-8B20-623AE2924267@icloud.com>
Sent from my iPhone
> On 4 May 2569 BE, at 4:38 PM, Aa Kk <ahya0000@icloud.com> wrote:
>
>
> Sent from my iPhone
>
>
>> On 4 May 2569 BE, at 4:37 PM, Aa Kk <ahya0000@icloud.com> wrote:
>>
>> 524152
>> Sent from my iPhone
>>
>>
>>>> On 4 May 2569 BE, at 12:05 AM, Aa Kk <ahya0000@icloud.com> wrote:
>>>
>>>
>>> Sent from my iPhone
> <Contact 3.vcf>
>>>
>>>
^ permalink raw reply
* Re: 10.26
From: Aa Kk @ 2026-05-04 9:38 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: text/plain, Size: 252 bytes --]
Sent from my iPhone
> On 4 May 2569 BE, at 4:37 PM, Aa Kk <ahya0000@icloud.com> wrote:
>
> 524152
> Sent from my iPhone
>
>
>> On 4 May 2569 BE, at 12:05 AM, Aa Kk <ahya0000@icloud.com> wrote:
>>
>>
>> Sent from my iPhone
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Contact 3.vcf --]
[-- Type: text/directory; name="Contact 3.vcf"; x-apple-part-url=8E4FD26D-4950-4AF9-A314-5C52EB1A373C, Size: 38968 bytes --]
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iPhone OS 26.4//EN
N:;;;;
PHOTO;ENCODING=b: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
rF34wiyVFLBynCLo9qbzEmBuwA==
END:VCARD
[-- Attachment #3: Type: text/plain, Size: 8 bytes --]
>>
>>
^ permalink raw reply
* Re: 10.26
From: Aa Kk @ 2026-05-04 9:36 UTC (permalink / raw)
To: git
In-Reply-To: <4160301E-113E-4F4D-A0F4-C9D1847C1057@icloud.com>
524152
Sent from my iPhone
> On 4 May 2569 BE, at 12:05 AM, Aa Kk <ahya0000@icloud.com> wrote:
>
>
> Sent from my iPhone
>
^ permalink raw reply
* Re: [PATCH] name-rev: fix an 'may be used uninitialized' error
From: Kristoffer Haugsbakk @ 2026-05-04 8:55 UTC (permalink / raw)
To: Junio C Hamano, Ramsay Jones; +Cc: GIT Mailing-list
In-Reply-To: <xmqqv7d4ou3m.fsf@gitster.g>
Hi Junio
On Mon, May 4, 2026, at 03:13, Junio C Hamano wrote:
> Ramsay Jones <ramsay@ramsayjones.plus.com> writes:
>
>> Today's seen branch fails to build (with DEVELOPER=1), like so:
>>
>> CC builtin/name-rev.o
>> builtin/name-rev.c: In function ‘cmd_format_rev’:
>> builtin/name-rev.c:885:28: error: ‘commit’ may be used uninitialized [-Werror=maybe-uninitialized]
>> 885 | if (!commit) {
>> | ^
>> builtin/name-rev.c:867:40: note: ‘commit’ was declared here
>> 867 | struct commit *commit;
>> | ^~~~~~
>> cc1: all warnings being treated as errors
>> make: *** [Makefile:2932: builtin/name-rev.o] Error 1
>> ...
>> diff --git a/builtin/name-rev.c b/builtin/name-rev.c
>> index b941e93834..5b7f7a00e5 100644
>> --- a/builtin/name-rev.c
>> +++ b/builtin/name-rev.c
>> @@ -882,6 +882,8 @@ int cmd_format_rev(int argc,
>> peeled = deref_tag(the_repository, object, scratch_buf.buf, 0);
>> if (peeled && peeled->type == OBJ_COMMIT)
>> commit = (struct commit *)peeled;
>> + else
>> + commit = NULL;
>> if (!commit) {
>> fprintf(stderr, "Could not get commit for %s. Skipping.\n",
>> *argv);
>
> Why not
>
> if (peeled && peeled->type == OBJ_COMMIT) {
> commit = (struct commit *)peeled;
> } else {
> fprintf(stderr, "... skipping ...");
> continue;
> }
>
> get_format_rev(commit, &format_pp, &scratch);
>
> or even
>
> if (!peeled || peeled->type != OBJ_COMMIT) {
> fprintf(stderr, "... skipping ...");
> continue;
> }
>
> get_format_rev((struct commit *)peeled->type,
> &format_pp, &scratch);
>
> and dropping the variable "struct commit *commit" altogether?
I see that you added this as one of two “SQUASH???” commits on your
kh/name-rev-custom-format branch. I will squash both of them in for the
next round.
Thanks to both of you.
^ permalink raw reply
* git clone with --dissociate sometimes fails to check out target commit
From: Rasmus Villemoes @ 2026-05-04 8:20 UTC (permalink / raw)
To: git; +Cc: emkan
Hi
We have now seen this error a couple of times in our CI, and this time I
managed to grab a snapshot of the local mirror for which it fails. The
failing command is
git clone --verbose --depth=20 --branch=whinlatter --reference-if-able=/yocto/meta-mirrors/core --dissociate https://git.openembedded.org/openembedded-core core
Cloning into 'core'...
POST git-upload-pack (388 bytes)
POST git-upload-pack (986 bytes)
POST git-upload-pack (gzip 1836 to 958 bytes)
fatal: unable to parse commit 8751ec83421192fc0f8495fb95798f9eb7be77a0
warning: Clone succeeded, but checkout failed.
You can inspect what was checked out with 'git status'
and retry with 'git restore --source=HEAD :/'
I wrapped up that local copy /yocto/meta-mirrors/core in a tarball, but
it's ~200M, and I don't know another way of reproducing. I also don't
have a better way of sharing such a file than [1], apologies.
Using that repository as both the remote url to clone and the local
reference, I can consistently reproduce the problem. That is:
cd /tmp
# fetch that core.tar.gz
mkdir upstream-core local-core
tar -xf core.tar.gz -C upstream-core/
tar -xf core.tar.gz -C local-core/
git clone --verbose --branch=whinlatter --reference-if-able=/tmp/local-core --dissociate --depth=20 file:///tmp/upstream-core core
fails in the same way, with both git 2.47.3 (Debian trixie) and 2.53.0
(Arch). Removing --depth=20 doesn't change anything, neither does
removing --branch=whinlatter (except of course for the commit it tries
to check out). But dropping --dissociate, the clone works as expected.
It doesn't happen very often, the last time was around January 30, where
it was for another repository
(https://github.com/openembedded/meta-openembedded.git), but exactly the
same symptoms, so about 100 nightly pipelines ago.
Are we using --dissociate wrongly, or are we perhaps not maintaining
those local mirror repos properly? They are essentially just created
with 'git clone --mirror', with 'git remote update' run periodically.
Naively, I'd expect the effects of --dissociate to only happen after
everything else the clone command does has been done, but it seems that
the ties to the reference repo are cut too soon.
Rasmus
[1] https://prevasonline-my.sharepoint.com/:u:/g/personal/rasmus_villemoes_prevas_dk/IQCRaxpwj5NfQYZNQJWc9PJTAY0C33XvXn8CnqPEdPAbpDA?e=zQAfg7
^ permalink raw reply
* Re: [PATCH v5] revision.c: implement --max-count-oldest
From: Junio C Hamano @ 2026-05-04 5:19 UTC (permalink / raw)
To: Mirko Faina
Cc: git, Jeff King, Jean-Noël Avila, Patrick Steinhardt,
Tian Yuchen, Ben Knoble, Johannes Sixt, Chris Torek
In-Reply-To: <2f71a00b035e25b971641b77a6fa7626f1e2459c.1777578676.git.mroik@delayed.space>
Mirko Faina <mroik@delayed.space> writes:
> --max-count is a commit limiting option sets a maximum amount of commits
> to be shown. If a user wants to see only the first N commits of the
> history (the oldest commits) they'd have to combine --max-count with
> --skip. This is not very user-friendly.
To use "--skip=<n>" for this purose, you'd need to know how many
records are going to be omitted to begin with, but that means you'd
run the command without count limitation once only to find out how
many records there are. "not very user-friendly" sounds like an
understatement of the year.
They can do with something silly like
git rev-list ... |
tail -n N |
xargs -n1 git show ...
and that does count as "not very user-friendly", I would think.
> Teach get_revision() the --max-count-oldest option.
>
> Signed-off-by: Mirko Faina <mroik@delayed.space>
> ---
> Documentation/rev-list-options.adoc | 3 ++
> revision.c | 77 +++++++++++++++++++++++++++--
> revision.h | 2 +
> t/t4202-log.sh | 14 ++++++
> 4 files changed, 93 insertions(+), 3 deletions(-)
It looks like this needs measurably smaller damage to the codebase
than the other --reverse=before approach ;-).
> diff --git a/Documentation/rev-list-options.adoc b/Documentation/rev-list-options.adoc
> index 2d195a1474..736f34efab 100644
> --- a/Documentation/rev-list-options.adoc
> +++ b/Documentation/rev-list-options.adoc
> @@ -18,6 +18,9 @@ ordering and formatting options, such as `--reverse`.
> `--max-count=<number>`::
> Limit the output to _<number>_ commits.
>
> +`--max-count-oldest=<number>`::
> + Limit the output to the _<number>_ oldest commits.
> +
> `--skip=<number>`::
> Skip _<number>_ commits before starting to show the commit output.
>
> diff --git a/revision.c b/revision.c
> index 599b3a66c3..3aaa77ced5 100644
> --- a/revision.c
> +++ b/revision.c
> @@ -2339,10 +2339,24 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
> }
>
> if ((argcount = parse_long_opt("max-count", argv, &optarg))) {
> + if (revs->max_count_type == 1)
> + die(_("can't use --max-count with --max-count-oldest"));
> revs->max_count = parse_count(optarg);
> revs->no_walk = 0;
> + revs->max_count_type = 0;
> return argcount;
> + } else if ((argcount = parse_long_opt("max-count-oldest", argv, &optarg))) {
> + if (revs->max_count_type == 0 && revs->max_count != -1)
> + die(_("can't use --max-count with --max-count-oldest"));
> + if (revs->skip_count > 0)
> + die(_("con't use --max-count-oldest with --skip"));
> + revs->max_count = parse_count(optarg);
> + revs->no_walk = 0;
> + revs->max_count_type = 1;
> + revs->max_count_stage = 0;
> } else if ((argcount = parse_long_opt("skip", argv, &optarg))) {
> + if (revs->max_count_type == 1)
> + die(_("con't use --max-count-oldest with --skip"));
> revs->skip_count = parse_count(optarg);
> return argcount;
> } else if ((*arg == '-') && isdigit(arg[1])) {
> @@ -4521,15 +4535,68 @@ static struct commit *get_revision_internal(struct rev_info *revs)
> return c;
> }
>
> +static void retrieve_oldest_commits(struct rev_info *revs,
> + struct commit_list **queue)
> +{
> + struct commit *c;
> + int max_count = revs->max_count;
> + int queuei_count = 0;
> + int queueo_count = 0;
> + struct commit_list *queueo = NULL;
> + struct commit_list *queuei = NULL;
> + struct commit_list *reversed_queue = NULL;
> +
> + revs->max_count = -1;
> + while ((c = get_revision_internal(revs))) {
> + c->object.flags &= ~SHOWN;
> + commit_list_insert(c, &queuei);
> + queuei_count++;
> + while (queuei_count + queueo_count > max_count) {
> + if (!queueo_count) {
> + while (queuei_count > 0) {
> + c = pop_commit(&queuei);
> + queuei_count--;
> + commit_list_insert(c, &queueo);
> + queueo_count++;
> + }
> + }
> + pop_commit(&queueo);
> + queueo_count--;
> + }
> + }
> +
> + while ((c = pop_commit(&queueo)))
> + commit_list_insert(c, &reversed_queue);
> + while ((c = pop_commit(&queuei)))
> + commit_list_insert(c, &queueo);
> + while ((c = pop_commit(&queueo)))
> + commit_list_insert(c, &reversed_queue);
> +
> + while ((c = pop_commit(&reversed_queue)))
> + commit_list_insert(c, queue);
> +}
> +
> struct commit *get_revision(struct rev_info *revs)
> {
> struct commit *c;
> struct commit_list *reversed;
> + struct commit_list *queue = NULL;
> +
> + if (revs->max_count_type == 1 && !revs->max_count_stage) {
> + retrieve_oldest_commits(revs, &queue);
> + commit_list_free(revs->commits);
> + revs->commits = queue;
> + revs->max_count_stage = 1;
> + }
>
> if (revs->reverse) {
> reversed = NULL;
> - while ((c = get_revision_internal(revs)))
> - commit_list_insert(c, &reversed);
> + if (revs->max_count_type == 1)
> + while ((c = pop_commit(&revs->commits)))
> + commit_list_insert(c, &reversed);
> + else
> + while ((c = get_revision_internal(revs)))
> + commit_list_insert(c, &reversed);
> commit_list_free(revs->commits);
> revs->commits = reversed;
> revs->reverse = 0;
> @@ -4543,7 +4610,11 @@ struct commit *get_revision(struct rev_info *revs)
> return c;
> }
>
> - c = get_revision_internal(revs);
> + if (revs->max_count_stage)
> + c = pop_commit(&revs->commits);
> + else
> + c = get_revision_internal(revs);
> +
> if (c && revs->graph)
> graph_update(revs->graph, c);
> if (!c) {
> diff --git a/revision.h b/revision.h
> index 584f1338b5..e157463cb1 100644
> --- a/revision.h
> +++ b/revision.h
> @@ -309,6 +309,8 @@ struct rev_info {
> /* special limits */
> int skip_count;
> int max_count;
> + unsigned int max_count_type:1;
> + unsigned int max_count_stage:1;
> timestamp_t max_age;
> timestamp_t max_age_as_filter;
> timestamp_t min_age;
> diff --git a/t/t4202-log.sh b/t/t4202-log.sh
> index 05cee9e41b..668c231cf1 100755
> --- a/t/t4202-log.sh
> +++ b/t/t4202-log.sh
> @@ -1882,6 +1882,20 @@ test_expect_success 'log --graph with --name-status' '
> test_cmp_graph --name-status tangle..reach
> '
>
> +test_expect_success 'log --max-count-oldest=3 --oneline' '
> + test_when_finished rm expect &&
> + git log --oneline | tail -n3 >expect &&
> + git log --oneline --max-count-oldest=3 >actual &&
> + test_cmp expect actual
> +'
> +
> +test_expect_success 'log --max-count-oldest=3 --reverse --oneline' '
> + test_when_finished rm expect &&
> + git log --oneline | tail -n3 | tac >expect &&
> + git log --oneline --max-count-oldest=3 --reverse >actual &&
> + test_cmp expect actual
> +'
> +
> cat >expect <<-\EOF
> * reach
> |
^ permalink raw reply
* Re: [PATCH] pretty: add diff-stat log placeholders
From: Junio C Hamano @ 2026-05-04 5:09 UTC (permalink / raw)
To: Andrey Zarubin via GitGitGadget; +Cc: git, Andrey Zarubin
In-Reply-To: <pull.2284.git.git.1777578903593.gitgitgadget@gmail.com>
"Andrey Zarubin via GitGitGadget" <gitgitgadget@gmail.com> writes:
> From: Andrey Zarubin <zarandr@gmail.com>
>
> Currently, users who want per-commit line/file change counts in
> a custom log format must post-process `git log --shortstat`
> output because the pretty formatter exposes no equivalent
> placeholders.
>
> Introduce `%(diff-stat:files)`, `%(diff-stat:insertions)`,
> `%(diff-stat:deletions)`, and `%(diff-stat:lines)`, computed
> from the same diffstat machinery as `--shortstat` and cached
> once per commit during format expansion.
>
> Short aliases are provided as `%aF`, `%aA`, and `%aR`. The
> requested `%aI` and `%aD` forms are unavailable because those
> names already expand to author dates, so use additions/removals
> mnemonics instead.
>
> When log output is already walking a diff, the formatter reuses
> the current diff queue. Otherwise it computes a private summary
> lazily, so formats without these placeholders still pay no diff
> cost.
>
> Signed-off-by: Andrey Zarubin <zarandr@gmail.com>
> ---
> pretty: add diff-stat log placeholders
Personally I find this a bit on the other side of the line between
sensible and insanity. Will we next be adding a new placeholder to
show the summary (i.e. list of created, deleted, and renamed paths)
and another placeholder to show the entire patch text?
^ permalink raw reply
* Re: [PATCH] compat/posix.h: enable UNUSED warning messages for Clang
From: Junio C Hamano @ 2026-05-04 1:41 UTC (permalink / raw)
To: Dominik Loidolt
Cc: git, Alejandro R Sedeño, Alejandro R. Sedeño,
Ævar Arnfjörð Bjarmason
In-Reply-To: <xmqq1pfsq8sd.fsf@gitster.g>
Junio C Hamano <gitster@pobox.com> writes:
>> I am not familiar with git's minimum compiler version but this patch
>> drops support for Clang < 2.9 from 2011.
>
> Does this "drop support" because you force _all_ versions of Clang
> to use the "deprecated" attribute, even though you _know_ some older
> versions do not understand it? Don't these versions identify
> themselves so that you can do
>
> #if defined(__clang__) && CLANG_VERSION >= 2.9
>
> I do not know if the userbase of GCC and Clang upgrade with a
> similar cadence, or we seem to say that we care about GCC 4.5
> (2010), so giving a similar version detection for Clang and exclude
> ones older than 2.9 sounds more appropriate.
IOW, something like this, perhaps?
compat/posix.h | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git c/compat/posix.h w/compat/posix.h
index faaae1b655..0dd0637fc9 100644
--- c/compat/posix.h
+++ w/compat/posix.h
@@ -22,6 +22,17 @@
#define GIT_GNUC_PREREQ(maj, min) 0
#endif
+/*
+ * Similar for clang
+ */
+#if defined(__clang__) && defined(__clang_minor__) && defined(__clang_major__)
+# define GIT_CLANG_PREREQ(maj, min) \
+ ((__clang_major__ > (maj)) || \
+ (__clang_major__ == (maj) && (__clang_minor__ >= (min))))
+#else
+# define GIT_CLANG_PREREQ(maj, min) 0
+#endif
+
/*
* UNUSED marks a function parameter that is always unused. It also
* can be used to annotate a function, a variable, or a type that is
@@ -35,7 +46,7 @@
* When a parameter may be used or unused, depending on conditional
* compilation, consider using MAYBE_UNUSED instead.
*/
-#if GIT_GNUC_PREREQ(4, 5)
+#if GIT_GNUC_PREREQ(4, 5) || GIT_CLANG_PREREQ(2, 9)
#define UNUSED __attribute__((unused)) \
__attribute__((deprecated ("parameter declared as UNUSED")))
#elif defined(__GNUC__)
^ permalink raw reply related
* Re: [PATCH] name-rev: fix an 'may be used uninitialized' error
From: Junio C Hamano @ 2026-05-04 1:13 UTC (permalink / raw)
To: Ramsay Jones; +Cc: Kristoffer Haugsbakk, GIT Mailing-list
In-Reply-To: <e74a8fd8-0617-46a8-8bef-a454d51a99c1@ramsayjones.plus.com>
Ramsay Jones <ramsay@ramsayjones.plus.com> writes:
> Today's seen branch fails to build (with DEVELOPER=1), like so:
>
> CC builtin/name-rev.o
> builtin/name-rev.c: In function ‘cmd_format_rev’:
> builtin/name-rev.c:885:28: error: ‘commit’ may be used uninitialized [-Werror=maybe-uninitialized]
> 885 | if (!commit) {
> | ^
> builtin/name-rev.c:867:40: note: ‘commit’ was declared here
> 867 | struct commit *commit;
> | ^~~~~~
> cc1: all warnings being treated as errors
> make: *** [Makefile:2932: builtin/name-rev.o] Error 1
> ...
> diff --git a/builtin/name-rev.c b/builtin/name-rev.c
> index b941e93834..5b7f7a00e5 100644
> --- a/builtin/name-rev.c
> +++ b/builtin/name-rev.c
> @@ -882,6 +882,8 @@ int cmd_format_rev(int argc,
> peeled = deref_tag(the_repository, object, scratch_buf.buf, 0);
> if (peeled && peeled->type == OBJ_COMMIT)
> commit = (struct commit *)peeled;
> + else
> + commit = NULL;
> if (!commit) {
> fprintf(stderr, "Could not get commit for %s. Skipping.\n",
> *argv);
Why not
if (peeled && peeled->type == OBJ_COMMIT) {
commit = (struct commit *)peeled;
} else {
fprintf(stderr, "... skipping ...");
continue;
}
get_format_rev(commit, &format_pp, &scratch);
or even
if (!peeled || peeled->type != OBJ_COMMIT) {
fprintf(stderr, "... skipping ...");
continue;
}
get_format_rev((struct commit *)peeled->type,
&format_pp, &scratch);
and dropping the variable "struct commit *commit" altogether?
^ permalink raw reply
* Re: [PATCH] compat/posix.h: enable UNUSED warning messages for Clang
From: Junio C Hamano @ 2026-05-04 1:10 UTC (permalink / raw)
To: Dominik Loidolt
Cc: git, Alejandro R Sedeño, Alejandro R. Sedeño,
Ævar Arnfjörð Bjarmason
In-Reply-To: <20260503151210.36036-1-dominik.loidolt@univie.ac.at>
Dominik Loidolt <dominik.loidolt@univie.ac.at> writes:
> Treat Clang like GCC 4.5+ so using an UNUSED parameter emits the
> intended warning message.
>
> Commit 7c07f36ad2 (git-compat-util.h: GCC deprecated message arg only in
> GCC 4.5+, 2022-10-05) restricted use of the deprecated attribute's
> message argument in the UNUSED macro to GCC 4.5 or newer.
>
> Clang identifies itself as GNUC 4.2.1 for compatibility, causing the
> current check to use the deprecated attribute without a message, even
> though Clang supports deprecated("...") since version 2.9 (2011).
>
> Signed-off-by: Dominik Loidolt <dominik.loidolt@univie.ac.at>
> ---
> I am not familiar with git's minimum compiler version but this patch
> drops support for Clang < 2.9 from 2011.
Does this "drop support" because you force _all_ versions of Clang
to use the "deprecated" attribute, even though you _know_ some older
versions do not understand it? Don't these versions identify
themselves so that you can do
#if defined(__clang__) && CLANG_VERSION >= 2.9
I do not know if the userbase of GCC and Clang upgrade with a
similar cadence, or we seem to say that we care about GCC 4.5
(2010), so giving a similar version detection for Clang and exclude
ones older than 2.9 sounds more appropriate.
> Dominik
> P.S. This is my first patch sent by email. Please let me know if I
> missed something.
>
> compat/posix.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/compat/posix.h b/compat/posix.h
> index 245386fa4a..ed83a4d9d4 100644
> --- a/compat/posix.h
> +++ b/compat/posix.h
> @@ -35,7 +35,7 @@
> * When a parameter may be used or unused, depending on conditional
> * compilation, consider using MAYBE_UNUSED instead.
> */
> -#if GIT_GNUC_PREREQ(4, 5)
> +#if GIT_GNUC_PREREQ(4, 5) || defined(__clang__)
> #define UNUSED __attribute__((unused)) \
> __attribute__((deprecated ("parameter declared as UNUSED")))
> #elif defined(__GNUC__)
>
> base-commit: 67ad42147a7acc2af6074753ebd03d904476118f
> --
> 2.54.0
^ permalink raw reply
* Re: [PATCH v6 0/6] Xdiff cleanup part 3
From: Junio C Hamano @ 2026-05-04 0:59 UTC (permalink / raw)
To: Phillip Wood
Cc: Ezekiel Newren via GitGitGadget, git, Yee Cheng Chin,
René Scharfe, Jeff King, D. Ben Knoble, SZEDER Gábor,
Ezekiel Newren
In-Reply-To: <c8b48c6a-5a20-4981-9cd4-999b40c618fc@gmail.com>
Phillip Wood <phillip.wood123@gmail.com> writes:
> Juino - are you happy to rebase pw/xdiff-shrink-memory-consumption, or
> do you want be to send a re-roll?
I'd rather not risk botched rebase by a third-party and prefer to
take a fresh submission by the original author. Thanks.
^ permalink raw reply
* Re: [PATCH 1/7] pack-objects: pass --objects with --path-walk
From: Junio C Hamano @ 2026-05-04 0:49 UTC (permalink / raw)
To: Derrick Stolee via GitGitGadget
Cc: git, christian.couder, johannes.schindelin, johncai86,
karthik.188, kristofferhaugsbakk, me, newren, peff, ps,
Derrick Stolee
In-Reply-To: <29d2797440412bfec85be7b6a6439350b9ebf5e8.1777731354.git.gitgitgadget@gmail.com>
"Derrick Stolee via GitGitGadget" <gitgitgadget@gmail.com> writes:
> From: Derrick Stolee <stolee@gmail.com>
>
> When 'git pack-objects' has the --path-walk option enabled, it uses a
> different set of revision walk parameters than normal. For once,
"once" -> "one" (or "instance")?
> --objects was previously assumed by the path-walk API and was not needed
> to be added. We also needed --boundary to allow discovering
> UNINTERESTING objects to use as delta bases.
>
> We will be updating the path-walk API soon to work with some filter
> options. However, the revision machinery will trigger a fatal error:
>
> fatal: object filtering requires --objects
>
> The fix is easy: add the --objects option as an argument. This has no
> effect on the path-walk API but does simplify the revision option
> parsing for the objects filter.
>
> We can remove the comment about "removing" the options because they were
> never removed and instead not added. We still need to disable using
> bitmaps.
In the old code, there was a valid reason why bitmaps were not used
(i.e., "--objects" not enabled), but that no longer holds (i.e., now
we add "--objects" ourselves). Do we need to give an updated
rationale to keep bitmap disabled?
> Signed-off-by: Derrick Stolee <stolee@gmail.com>
> ---
> builtin/pack-objects.c | 5 +----
> 1 file changed, 1 insertion(+), 4 deletions(-)
>
> diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
> index dd2480a73d..4338962904 100644
> --- a/builtin/pack-objects.c
> +++ b/builtin/pack-objects.c
> @@ -5190,10 +5190,7 @@ int cmd_pack_objects(int argc,
> }
> if (path_walk) {
> strvec_push(&rp, "--boundary");
> - /*
> - * We must disable the bitmaps because we are removing
> - * the --objects / --objects-edge[-aggressive] options.
> - */
> + strvec_push(&rp, "--objects");
> use_bitmap_index = 0;
> } else if (thin) {
> use_internal_rev_list = 1;
^ permalink raw reply
* Re: git 2.54 fails to build for rhel 6 (2.53 builds fine)
From: brian m. carlson @ 2026-05-04 0:34 UTC (permalink / raw)
To: Азат Усманов
Cc: git
In-Reply-To: <9692091777837852@4991cc90-7cef-4f92-9de9-e195e7f2c04c>
[-- Attachment #1: Type: text/plain, Size: 1645 bytes --]
On 2026-05-03 at 19:50:52, Азат Усманов wrote:
> Hi everyone! I have noticed a problem when trying to build latest git
> 2.54 in rhel 6,(2.53 builds fine ) nothing has changed on this machine
> since I successfully installed 2.53 . My openssl version is 3.5.6. Any
> Ideas? Below is the log
We no longer support RHEL 6. It lacks security support and
Documentation/technical/platform-support.adoc states the following
requirement, among others:
* Has active security support (taking security releases of dependencies, etc)
We normally do not consider extended support time frames in this regard,
but even if we were to do so, RHEL 6 lost security support in 2024[0],
so it's not supported. I would recommend you upgrade this system
immediately to a supported OS to avoid it being compromised and becoming
a hazard to the rest of the Internet.
> /usr/local/bin/ld: warning: libssl.so.3, needed by /usr/local/lib/libcurl.so, may conflict with libssl.so.10
> LINK git-http-fetch
> /usr/local/bin/ld: warning: libcrypto.so.3, needed by /usr/local/lib/libcurl.so,may conflict with libcrypto.so.10
> /usr/local/bin/ld: imap-send.o: undefined reference to symbol 'ASN1_STRING_get0_data@@OPENSSL_3.0.0'
> /usr/local/bin/ld: /usr/local/openssl/lib/libcrypto.so.3: error adding symbols:DSO missing from command line
> collect2: error: ld returned 1 exit status
It looks like there's either a conflict between various versions of
OpenSSL which are being linked into Git or perhaps the wrong one is
being linked in.
[0] https://endoflife.date/rhel
--
brian m. carlson (they/them)
Toronto, Ontario, CA
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 325 bytes --]
^ permalink raw reply
* [RFC PATCH 7/7] pack-objects: support `--delta-islands` with `--path-walk`
From: Taylor Blau @ 2026-05-04 0:11 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Derrick Stolee, Jeff King, Elijah Newren
In-Reply-To: <cover.1777853408.git.me@ttaylorr.com>
Since the inception of `--path-walk`, this option has a documented
incompatibility with `--delta-islands`.
When discussing those original patches on the list, a message from
Stolee in [1] noted the following:
this could be remedied by [...] doing a separate walk to identify
islands using the normal method
In a related portion of the thread, Peff explains[2]:
The delta islands code already does its own tree walk to propagate
the bits down (it does rely on the base walk's show_commit() to
propagate through the commits).
Once each object has its island bitmaps, I think however you
choose to come up with delta candidates [...] you should be able
to use it. It's fundamentally just answering the question of "am
I allowed to delta between these two objects".
That is similar to what this patch does, and it turns out the cheaper
option (do the side-effects inside the path-walk callback rather than
via a second walk) is sufficient.
Recall how delta-islands are computed during a normal repack:
- `show_commit()` calls `propagate_island_marks()` for each commit,
which merges the commit's island bitset onto its root tree object and
onto each of its parent commits.
- `show_object()` for a tree records the tree's depth derived from the
slash-separated pathname. Subsequent `resolve_tree_islands()` uses
that depth to walk trees in increasing-depth order, propagating each
tree's marks to its children.
- At delta-search time, `in_same_island()` enforces that a delta
target's island bitmap is a subset of its base's: every island
that reaches the target must also reach the base.
Path-walk's enumeration callback is `add_objects_by_path()`. It already
adds objects to `to_pack', but until now did not perform any of the
island-related side effects. Two things are needed:
- For each commit batch, call `propagate_island_marks()` on the commit,
exactly as show_commit() does.
Order matters here. `mark_remote_island_1()` only seeds marks on
tip commits, so a non-tip commit has marks in the `island_marks` map
only after some descendant has already had `propagate_island_marks()`
run on it. If we see a commit before its descendants, its
`island_marks` entry would still be empty, the call would be a no-op,
and that commit's root tree would never receive any marks at all.
As a consequence, `resolve_tree_islands()` would later look up the
tree, find nothing, and propagate nothing. The traversal must visit
children before parents.
The path-walk batch preserves that order mechanically. Path-walk
appends commits to its `OBJ_COMMIT` batch as they come back from the
same `get_revision()` loop the regular traversal uses, and
`add_objects_by_path()` iterates the batch in array order. So every
commit reaches `propagate_island_marks()` in the same sequence that
`show_commit()` would have seen it, and the descendant-first chain
that the algorithm relies on is intact.
Skip the call for boundary commits to match `show_commit()`, which is
only invoked for interesting commits (this call is a no-op anyway for
boundary commits since they are not in 'island_marks', but matching
`show_commit()` exactly keeps the two enumeration modes tidy).
- For each tree batch, record the tree's depth from the path. Use the
`record_tree_depth()` helper from the previous commit so both
callbacks behave identically, including the "max-depth-wins" behavior
when a tree is reached via more than one path. The helper accepts
both the show_object() path shape ("foo", "foo/bar") and the
path-walk shape with a trailing '/' ("foo/", "foo/bar/"), so depths
recorded from either traversal mode are directly comparable.
This is implicit in the implementation sketch from Peff above.
`resolve_tree_islands()` sorts trees by `oe->tree_depth` (ascending)
before propagating marks down, so that a parent tree's marks are
finalized before its children inherit them. Without recording the
depth at path-walk time, every path-walk-discovered tree would land
at depth 0 in `to_pack`, the sort would lose its ordering, and
children could inherit marks from parents whose own contributions had
not yet been merged in.
With those two pieces in place, `resolve_tree_islands()` receives
identical input to a normal traversal, so the existing correctness
argument carries over verbatim: depth-ordered processing guarantees that
a parent tree's marks are propagated to a child only after the parent
itself has been finalized, and the "is-this-a-subset" check at delta
time is the same regardless of how the marks got there.
Coverage in t5320 exercises both repack flavors (with and without '-b'),
confirms that cross-island deltas remain forbidden, and that
intra-island deltas are still allowed.
[1]: https://lore.kernel.org/git/9aa2471b-0850-4707-9733-d3b33609f5f2@gmail.com/
[2]: https://lore.kernel.org/git/20240911063203.GA1538586@coredump.intra.peff.net/
Signed-off-by: Taylor Blau <me@ttaylorr.com>
---
Documentation/git-pack-objects.adoc | 15 +++++++--------
builtin/pack-objects.c | 22 ++++++++++++++++++----
t/t5320-delta-islands.sh | 29 +++++++++++++++++++++++++++++
3 files changed, 54 insertions(+), 12 deletions(-)
diff --git a/Documentation/git-pack-objects.adoc b/Documentation/git-pack-objects.adoc
index 60e594c7bc4..aa7a9721203 100644
--- a/Documentation/git-pack-objects.adoc
+++ b/Documentation/git-pack-objects.adoc
@@ -402,14 +402,13 @@ will be automatically changed to version `1`.
of filenames that cause collisions in Git's default name-hash
algorithm.
+
-Incompatible with `--delta-islands`. Path-walk supports
-the `--filter=<spec>` forms `blob:none`, `blob:limit=<n>`,
-`sparse:oid=<blob>`, `tree:0`, `object:type=<type>`, and `combine:`
-over any of those. Other filter forms fall back to the regular object
-traversal. When `--use-bitmap-index` is specified with `--path-walk`, a
-successful bitmap traversal is used for object enumeration, with
-path-walk remaining as the fallback traversal when the bitmap cannot
-satisfy the request.
+Path-walk supports the `--filter=<spec>` forms `blob:none`,
+`blob:limit=<n>`, `sparse:oid=<blob>`, `tree:0`, `object:type=<type>`,
+and `combine:` over any of those. Other filter forms fall back to the
+regular object traversal. When `--use-bitmap-index` is specified with
+`--path-walk`, a successful bitmap traversal is used for object
+enumeration, with path-walk remaining as the fallback traversal when
+the bitmap cannot satisfy the request.
DELTA ISLANDS
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 842d1fcac29..d79366db3de 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -4739,13 +4739,29 @@ static int add_objects_by_path(const char *path,
add_object_entry(oid, type, path, exclude);
- if (type == OBJ_COMMIT && write_bitmap_index) {
+ if (type == OBJ_COMMIT) {
struct commit *commit;
+ if (!write_bitmap_index && !use_delta_islands)
+ continue;
+
commit = lookup_commit(the_repository, oid);
if (!commit)
die(_("could not find commit %s"), oid_to_hex(oid));
- index_commit_for_bitmap(commit);
+ if (write_bitmap_index)
+ index_commit_for_bitmap(commit);
+ /*
+ * Skip island propagation for boundary commits.
+ * The regular traversal's show_commit() is only
+ * called for interesting commits; matching that
+ * here keeps path-walk from doing extra work that
+ * would only be a no-op anyway (boundary commits
+ * are not in island_marks).
+ */
+ if (use_delta_islands && !exclude)
+ propagate_island_marks(the_repository, commit);
+ } else if (type == OBJ_TREE && use_delta_islands) {
+ record_tree_depth(oid, path);
}
}
@@ -5196,8 +5212,6 @@ int cmd_pack_objects(int argc,
const char *option = NULL;
if (!path_walk_filter_compatible(&filter_options))
option = "--filter";
- else if (use_delta_islands)
- option = "--delta-islands";
if (option) {
warning(_("cannot use %s with %s"),
diff --git a/t/t5320-delta-islands.sh b/t/t5320-delta-islands.sh
index 2c961c70963..9b28344a0a3 100755
--- a/t/t5320-delta-islands.sh
+++ b/t/t5320-delta-islands.sh
@@ -53,6 +53,35 @@ test_expect_success 'separate islands disallows delta' '
! is_delta_base $two $one
'
+test_expect_success 'path-walk island repack respects islands' '
+ GIT_TRACE2_EVENT="$(pwd)/trace.path-walk-islands" \
+ git -c "pack.island=refs/heads/(.*)" repack -adfi \
+ --path-walk 2>err &&
+ test_region pack-objects path-walk trace.path-walk-islands &&
+ test_grep ! "cannot use --delta-islands with --path-walk" err &&
+ ! is_delta_base $one $two &&
+ ! is_delta_base $two $one
+'
+
+test_expect_success 'path-walk island bitmap repack respects islands' '
+ GIT_TRACE2_EVENT="$(pwd)/trace.path-walk-island-bitmap" \
+ git -c "pack.island=refs/heads/(.*)" repack -a -d -f -i -b \
+ --path-walk 2>err &&
+ test_region pack-objects path-walk trace.path-walk-island-bitmap &&
+ test_path_is_file .git/objects/pack/*.bitmap &&
+ git rev-list --test-bitmap --use-bitmap-index one &&
+ test_grep ! "cannot use --delta-islands with --path-walk" err &&
+ ! is_delta_base $one $two &&
+ ! is_delta_base $two $one
+'
+
+test_expect_success 'path-walk same island allows delta' '
+ GIT_TRACE2_EVENT="$(pwd)/trace.path-walk-same-island" \
+ git -c "pack.island=refs/heads" repack -adfi --path-walk &&
+ test_region pack-objects path-walk trace.path-walk-same-island &&
+ is_delta_base $one $two
+'
+
test_expect_success 'same island allows delta' '
git -c "pack.island=refs/heads" repack -adfi &&
is_delta_base $one $two
--
2.54.0.4.g6aa0d38a4ec
^ permalink raw reply related
* [RFC PATCH 6/7] pack-objects: extract `record_tree_depth()` helper
From: Taylor Blau @ 2026-05-04 0:11 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Derrick Stolee, Jeff King, Elijah Newren
In-Reply-To: <cover.1777853408.git.me@ttaylorr.com>
Prepare for a future change that needs to record tree depths from a
second call site by factoring out the delta islands-specific portion of
`show_object()` out into a helper, `record_tree_depth()`.
`record_tree_depth()` takes a tree OID along with the path that
`show_object()` received, and computes the directory depth from the
slash count in the path.
While we're in the area, make a few minor clean-ups:
- Gate the call on `obj->type == OBJ_TREE`, as we only care to compute
the depth for tree objects. The sole caller of `oe_tree_depth()`
resides in `delta-islands.c::resolve_tree_islands()`, and only calls
`oe_tree_depth()` behind `oe_type(...) == OBJ_TREE`.
- Defer computing the depth for an object until we know it is in the
`to_pack` list.
Signed-off-by: Taylor Blau <me@ttaylorr.com>
---
builtin/pack-objects.c | 34 ++++++++++++++++++++--------------
1 file changed, 20 insertions(+), 14 deletions(-)
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 1a5f1afd32e..842d1fcac29 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -2722,6 +2722,24 @@ static inline void oe_set_tree_depth(struct packing_data *pack,
pack->tree_depth[e - pack->objects] = tree_depth;
}
+static void record_tree_depth(const struct object_id *oid, const char *name)
+{
+ const char *p;
+ unsigned depth;
+ struct object_entry *ent = packlist_find(&to_pack, oid);
+
+ if (!ent)
+ return;
+
+ /* the empty string is a root tree, which is depth 0 */
+ depth = *name ? 1 : 0;
+ for (p = strchr(name, '/'); p; p = strchr(p + 1, '/'))
+ depth++;
+
+ if (depth > oe_tree_depth(&to_pack, ent))
+ oe_set_tree_depth(&to_pack, ent, depth);
+}
+
/*
* Return the size of the object without doing any delta
* reconstruction (so non-deltas are true object sizes, but deltas
@@ -4375,20 +4393,8 @@ static void show_object(struct object *obj, const char *name,
add_preferred_base_object(name);
add_object_entry(&obj->oid, obj->type, name, 0);
- if (use_delta_islands) {
- const char *p;
- unsigned depth;
- struct object_entry *ent;
-
- /* the empty string is a root tree, which is depth 0 */
- depth = *name ? 1 : 0;
- for (p = strchr(name, '/'); p; p = strchr(p + 1, '/'))
- depth++;
-
- ent = packlist_find(&to_pack, &obj->oid);
- if (ent && depth > oe_tree_depth(&to_pack, ent))
- oe_set_tree_depth(&to_pack, ent, depth);
- }
+ if (use_delta_islands && obj->type == OBJ_TREE)
+ record_tree_depth(&obj->oid, name);
}
static void show_object__ma_allow_any(struct object *obj, const char *name, void *data)
--
2.54.0.4.g6aa0d38a4ec
^ permalink raw reply related
* [RFC PATCH 5/7] pack-objects: support reachability bitmaps with `--path-walk`
From: Taylor Blau @ 2026-05-04 0:11 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Derrick Stolee, Jeff King, Elijah Newren
In-Reply-To: <cover.1777853408.git.me@ttaylorr.com>
When 'pack-objects' is invoked with '--path-walk', it prevents us from
using reachability bitmaps.
This behavior dates back to 70664d2865c (pack-objects: add --path-walk
option, 2025-05-16), which included a comment in the relevant portion of
the command-line arguments handling that read as follows:
/*
* We must disable the bitmaps because we are removing
* the --objects / --objects-edge[-aggressive] options.
*/
In fb2c309b7d3 (pack-objects: pass --objects with --path-walk,
2026-05-02), we adjusted this behavior to also pass "--objects", but
still disable use of reachability bitmaps.
Fortunately, disabling reachability bitmaps is not strictly necessary.
Consider a couple of pack-objects use-cases: one during repacking, when
we would ordinarily generate reachability bitmaps, and another for
serving fetches and clones, when we would ordinarily read existing
bitmaps:
- When attempting to generate reachability bitmaps, we would fail to do
so since path-walk reveals objects through the
`add_objects_by_path()` callback rather than, e.g., `show_commit()`,
so the bitmap selector's `index_commit_for_bitmap()` was never called
for any commit.
The selection routine then had no candidates and bitmap writing was
effectively a no-op.
- On the bitmap-reading side, an invocation like "git pack-objects
--use-bitmap-index --path-walk" never even tried to consult a bitmap,
even when one was sitting on disk that could have answered the
request.
Neither restriction is required. They are discussed in turn:
- For bitmap-writing, all we need is for `index_commit_for_bitmap()` to
see each commit that path-walk visits. The path-walk callback already
groups commits into a single batch keyed by `OBJ_COMMIT`, so invoking
`index_commit_for_bitmap()` from there gives the bitmap selection
routine the same input it would have gotten from `show_commit()` in
the regular traversal.
The candidate set of commits is identical, though the ordering
differs. Bitmap selection is sensitive to commit ordering, but
commits are visited in the same order as we see them from
`get_revision()` so bitmap selection should be identical with or
without `--path-walk`.
- For bitmap-reading, all we need is for `revs->tree_objects` (and so
on for blobs and tags) to be set, otherwise bitmap traversal would
only emit commit objects.
In commit fb2c309b7d3, those flags are set via passing "--objects",
so bitmap traversal under "--path-walk" packs everything just like
any other "--use-bitmap-index" invocation.
If an existing reachability bitmap is unable to satisfy the request (no
bitmap on disk, haves not in the bitmapped pack, etc.) we fall through
to path-walk's own enumeration, just as the regular traversal falls back
when a bitmap is unavailable.
In other words: "--path-walk --use-bitmap-index" uses reachability
bitmaps when available, and otherwise enumerates via path-walk.
The regression in t5310 deserves a word about pack-reuse. With
pack-reuse enabled (the default), the output pack copies whole regions
of the existing bitmapped pack before `traverse_bitmap_commit_list()`
even runs, so a naive test would happily pass even if, say,
`revs->blob_objects` is set to 0. We test both with and without
pack-reuse enabled. When pack-reuse is disabled, pack-objects must
enumerate the resulting bitmap without copying any existing on-disk in
the rev_info setup that pack-reuse would otherwise paper over.
Update Documentation/git-pack-objects.adoc to drop the "ignored"
claim about --use-bitmap-index in favor of describing the new
fallback chain.
Signed-off-by: Taylor Blau <me@ttaylorr.com>
---
Documentation/git-pack-objects.adoc | 6 +++--
builtin/pack-objects.c | 10 +++++++-
t/t5310-pack-bitmaps.sh | 36 +++++++++++++++++++++++++++++
3 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/Documentation/git-pack-objects.adoc b/Documentation/git-pack-objects.adoc
index 6c7bbff5be5..60e594c7bc4 100644
--- a/Documentation/git-pack-objects.adoc
+++ b/Documentation/git-pack-objects.adoc
@@ -406,8 +406,10 @@ Incompatible with `--delta-islands`. Path-walk supports
the `--filter=<spec>` forms `blob:none`, `blob:limit=<n>`,
`sparse:oid=<blob>`, `tree:0`, `object:type=<type>`, and `combine:`
over any of those. Other filter forms fall back to the regular object
-traversal. The `--use-bitmap-index` option will be ignored in the
-presence of `--path-walk`.
+traversal. When `--use-bitmap-index` is specified with `--path-walk`, a
+successful bitmap traversal is used for object enumeration, with
+path-walk remaining as the fallback traversal when the bitmap cannot
+satisfy the request.
DELTA ISLANDS
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index ba00d8148ab..1a5f1afd32e 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -4732,6 +4732,15 @@ static int add_objects_by_path(const char *path,
continue;
add_object_entry(oid, type, path, exclude);
+
+ if (type == OBJ_COMMIT && write_bitmap_index) {
+ struct commit *commit;
+
+ commit = lookup_commit(the_repository, oid);
+ if (!commit)
+ die(_("could not find commit %s"), oid_to_hex(oid));
+ index_commit_for_bitmap(commit);
+ }
}
oe_end = to_pack.nr_objects;
@@ -5193,7 +5202,6 @@ int cmd_pack_objects(int argc,
if (path_walk) {
strvec_push(&rp, "--boundary");
strvec_push(&rp, "--objects");
- use_bitmap_index = 0;
} else if (thin) {
use_internal_rev_list = 1;
strvec_push(&rp, shallow
diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh
index f693cb56691..69c5da1580a 100755
--- a/t/t5310-pack-bitmaps.sh
+++ b/t/t5310-pack-bitmaps.sh
@@ -577,6 +577,42 @@ test_bitmap_cases
sane_unset GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL
+test_expect_success 'path-walk repack can write and use bitmap indexes' '
+ test_when_finished "rm -rf path-walk-bitmap" &&
+ git init path-walk-bitmap &&
+ (
+ cd path-walk-bitmap &&
+ test_commit first &&
+ test_commit second &&
+ test_commit third &&
+
+ git repack -a -d -b --path-walk &&
+ git rev-list --test-bitmap --use-bitmap-index HEAD &&
+
+ git rev-parse HEAD >in &&
+
+ git rev-list --objects --no-object-names HEAD >expect.raw &&
+ sort expect.raw >expect &&
+
+ for reuse in true false
+ do
+ : >trace.txt &&
+
+ GIT_TRACE2_EVENT="$(pwd)/trace.txt" \
+ git -c pack.allowPackReuse=$reuse pack-objects \
+ --stdout --revs --path-walk --use-bitmap-index \
+ <in >out.pack &&
+ grep "\"category\":\"bitmap\",\"key\":\"bitmap/hits\"" trace.txt &&
+
+ git index-pack out.pack &&
+
+ list_packed_objects out.idx >actual.raw &&
+ sort actual.raw >actual &&
+ test_cmp expect actual || return 1
+ done
+ )
+'
+
test_expect_success 'incremental repack fails when bitmaps are requested' '
test_commit more-1 &&
test_must_fail git repack -d 2>err &&
--
2.54.0.4.g6aa0d38a4ec
^ permalink raw reply related
* [RFC PATCH 4/7] path-walk: support `combine` filter
From: Taylor Blau @ 2026-05-04 0:11 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Derrick Stolee, Jeff King, Elijah Newren
In-Reply-To: <cover.1777853408.git.me@ttaylorr.com>
The `combine` filter takes the intersection of its children, that is:
objects are shown only when all child filters would admit the object.
The preceding patches added support for many individual filter types.
Enable users to compose these filters by implementing support for the
`combine` filter type.
Mapping intersection onto path_walk_info works because every supported
child filter is a monotonic restriction:
- `blob:none`, `tree:0` unconditionally clear `info->blobs` and (for
`tree:0`) `info->trees`; clearing an already-cleared flag is a
no-op.
- `object:type=X` is now expressed as an AND of each type flag with the
filtered type, so applying multiple such filters only refines the
existing set rather than overwrites it.
- `blob:limit=N` has to compose too: the intersection of "size < L1"
and "size < L2" is "size < min(L1, L2)".
Update the `LOFC_BLOB_LIMIT` handler to take the running minimum when
`info->blob_limit` is already set, so a combined filter with, e.g.,
both "blob:limit=10" and "blob:limit=5" produces a limit of 5
regardless of ordering.
- `sparse:oid` is left unchanged. A `combine` filter that includes a
`sparse:oid` is allowed at most once, since the existing handler
refuses to overwrite `info->pl`. Two `sparse:oid` filters in a single
`combine` would be unusual and are rejected with a warning, matching
the standalone `sparse:oid` behavior.
Implementation-wise, the existing `prepare_filters()` called
`list_objects_filter_release()` inside each case branch. That works fine
for top-level filters, but `combine` filters need to recurse over its
child filters without releasing each one in turn (since the parent's
release iterates the sub array). Split `prepare_filters()` into a
recursive helper that performs only the mutation, plus a thin wrapper
that calls the helper and then releases the top-level filter once.
The `LOFC_COMBINE` case in the helper just walks `sub_nr` and recurses;
child filters are released by the wrapper's single
`list_objects_filter_release()` call on the parent (which itself
recursively releases each sub-filter, the same way it always has).
If any sub-filter is unsupported (e.g. "tree:1", "sparse:<path>", or a
not-yet-supported choice), the recursion bubbles a failure up and the
existing pack-objects/backfill fallback paths kick in.
Add coverage in t6601:
- "combine:blob:none+tree:0" collapses to "tree:0"
- "combine:object:type=blob+blob:limit=3" yields only the blobs
smaller than three bytes
- "combine:object:type=blob+object:type=tree" intersects to empty
- "combine:tree:1+blob:none" reports the "tree:1" error.
Update Documentation/git-pack-objects.adoc to add combine to the
list of supported --filter forms.
Signed-off-by: Taylor Blau <me@ttaylorr.com>
---
Documentation/git-pack-objects.adoc | 8 ++--
path-walk.c | 31 +++++++++-----
t/t6601-path-walk.sh | 65 +++++++++++++++++++++++++++++
3 files changed, 90 insertions(+), 14 deletions(-)
diff --git a/Documentation/git-pack-objects.adoc b/Documentation/git-pack-objects.adoc
index 22c782611d2..6c7bbff5be5 100644
--- a/Documentation/git-pack-objects.adoc
+++ b/Documentation/git-pack-objects.adoc
@@ -404,10 +404,10 @@ will be automatically changed to version `1`.
+
Incompatible with `--delta-islands`. Path-walk supports
the `--filter=<spec>` forms `blob:none`, `blob:limit=<n>`,
-`sparse:oid=<blob>`, `tree:0`, and `object:type=<type>`. Other filter
-forms fall back to the regular object traversal. The
-`--use-bitmap-index` option will be ignored in the presence of
-`--path-walk`.
+`sparse:oid=<blob>`, `tree:0`, `object:type=<type>`, and `combine:`
+over any of those. Other filter forms fall back to the regular object
+traversal. The `--use-bitmap-index` option will be ignored in the
+presence of `--path-walk`.
DELTA ISLANDS
diff --git a/path-walk.c b/path-walk.c
index b9902abbb75..6d66da3dc3b 100644
--- a/path-walk.c
+++ b/path-walk.c
@@ -539,28 +539,26 @@ static int setup_pending_objects(struct path_walk_info *info,
return 0;
}
-static int prepare_filters(struct path_walk_info *info,
- struct list_objects_filter_options *options)
+static int prepare_filters_one(struct path_walk_info *info,
+ struct list_objects_filter_options *options)
{
switch (options->choice) {
case LOFC_DISABLED:
return 1;
case LOFC_BLOB_NONE:
- if (info) {
+ if (info)
info->blobs = 0;
- list_objects_filter_release(options);
- }
return 1;
case LOFC_BLOB_LIMIT:
if (info) {
if (!options->blob_limit_value) {
info->blobs = 0;
- } else {
+ } else if (!info->blob_limit ||
+ options->blob_limit_value < info->blob_limit) {
info->blob_limit = options->blob_limit_value;
}
- list_objects_filter_release(options);
}
return 1;
@@ -573,7 +571,6 @@ static int prepare_filters(struct path_walk_info *info,
if (info) {
info->trees = 0;
info->blobs = 0;
- list_objects_filter_release(options);
}
return 1;
@@ -583,7 +580,6 @@ static int prepare_filters(struct path_walk_info *info,
info->tags &= options->object_type == OBJ_TAG;
info->trees &= options->object_type == OBJ_TREE;
info->blobs &= options->object_type == OBJ_BLOB;
- list_objects_filter_release(options);
}
return 1;
@@ -624,8 +620,13 @@ static int prepare_filters(struct path_walk_info *info,
warning(_("sparse filter is not cone-mode compatible"));
return 0;
}
+ }
+ return 1;
- list_objects_filter_release(options);
+ case LOFC_COMBINE:
+ for (size_t i = 0; i < options->sub_nr; i++) {
+ if (!prepare_filters_one(info, &options->sub[i]))
+ return 0;
}
return 1;
@@ -636,6 +637,16 @@ static int prepare_filters(struct path_walk_info *info,
}
}
+static int prepare_filters(struct path_walk_info *info,
+ struct list_objects_filter_options *options)
+{
+ if (!prepare_filters_one(info, options))
+ return 0;
+ if (info)
+ list_objects_filter_release(options);
+ return 1;
+}
+
int path_walk_filter_compatible(struct list_objects_filter_options *options)
{
return prepare_filters(NULL, options);
diff --git a/t/t6601-path-walk.sh b/t/t6601-path-walk.sh
index 13016e62ab1..a7d5f0de4ec 100755
--- a/t/t6601-path-walk.sh
+++ b/t/t6601-path-walk.sh
@@ -721,6 +721,71 @@ test_expect_success 'all, object:type=blob filter' '
test_cmp_sorted expect out
'
+test_expect_success 'all, combine:blob:none+tree:0 filter' '
+ test-tool path-walk \
+ --filter=combine:blob:none+tree:0 -- --all >out &&
+
+ cat >expect <<-EOF &&
+ 0:commit::$(git rev-parse topic)
+ 0:commit::$(git rev-parse base)
+ 0:commit::$(git rev-parse base~1)
+ 0:commit::$(git rev-parse base~2)
+ 1:tag:/tags:$(git rev-parse refs/tags/first)
+ 1:tag:/tags:$(git rev-parse refs/tags/second.1)
+ 1:tag:/tags:$(git rev-parse refs/tags/second.2)
+ 1:tag:/tags:$(git rev-parse refs/tags/third)
+ 1:tag:/tags:$(git rev-parse refs/tags/fourth)
+ 1:tag:/tags:$(git rev-parse refs/tags/tree-tag)
+ 1:tag:/tags:$(git rev-parse refs/tags/blob-tag)
+ blobs:0
+ commits:4
+ tags:7
+ trees:0
+ EOF
+
+ test_cmp_sorted expect out
+'
+
+test_expect_success 'all, combine:object:type=blob+blob:limit=3 filter' '
+ test-tool path-walk \
+ --filter=combine:object:type=blob+blob:limit=3 \
+ -- --all >out &&
+
+ cat >expect <<-EOF &&
+ 0:blob:a:$(git rev-parse base~2:a)
+ 1:blob:left/b:$(git rev-parse base~2:left/b)
+ 2:blob:right/c:$(git rev-parse base~2:right/c)
+ 3:blob:right/d:$(git rev-parse base~1:right/d)
+ blobs:4
+ commits:0
+ tags:0
+ trees:0
+ EOF
+
+ test_cmp_sorted expect out
+'
+
+test_expect_success 'all, combine of disjoint object:types is empty' '
+ test-tool path-walk \
+ --filter=combine:object:type=blob+object:type=tree \
+ -- --all >out &&
+
+ cat >expect <<-EOF &&
+ blobs:0
+ commits:0
+ tags:0
+ trees:0
+ EOF
+
+ test_cmp_sorted expect out
+'
+
+test_expect_success 'combine: rejects unsupported subfilters' '
+ test_must_fail test-tool path-walk \
+ --filter=combine:tree:1+blob:none -- --all 2>err &&
+ test_grep "tree:1 filter not supported by the path-walk API" err
+'
+
test_expect_success 'setup sparse filter blob' '
# Cone-mode patterns: include root, exclude all dirs, include left/
cat >patterns <<-\EOF &&
--
2.54.0.4.g6aa0d38a4ec
^ permalink raw reply related
* [RFC PATCH 3/7] path-walk: support `object:type` filter
From: Taylor Blau @ 2026-05-04 0:11 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Derrick Stolee, Jeff King, Elijah Newren
In-Reply-To: <cover.1777853408.git.me@ttaylorr.com>
The `object:type` filter accepts only objects of a single type; it is
the second member of the object-info-only filter family that bitmap
traversal already supports.
Like `blob:none` and `tree:0`, it can be evaluated with nothing more
than the object's type, which is exactly the granularity path-walk's
existing info->{commits,trees,blobs,tags} flags already control.
Map `LOFC_OBJECT_TYPE` in `prepare_filters()` by AND-ing each flag
against the filtered type. A single `object:type=X` filter
applied to the default info (all flags = 1) leaves `info->X = 1` and
all the others 0, which is what we want.
Using an AND rather than straight assignment prepares us for a
subsequent change to implement combined object filters.
The path-walk machinery is mostly already wired for the per-type
distinction:
- `walk_path()` calls `path_fn` for a batch only when the corresponding
`info->X` flag is set, so unwanted types are silently not reported.
- `add_tree_entries()` skips tree entries of type `OBJ_BLOB` when
`info->blobs` is unset, so we don't even allocate paths for them.
- The commit-walk loop short-circuits the root-tree fetch when
`!info->trees && !info->blobs`, so commit-only filters don't descend
into trees at all.
But there are a couple of side effects of the "trees off, blobs on" case
that need fixing:
1. 'setup_pending_objects()' previously skipped pending trees as soon
as `info->trees` was zero. For 'object:type=blob' the call site
needs those pending trees: a lightweight tag pointing to a tree, or
an annotated tag whose peeled target is a tree, can both reach
blobs that are otherwise unreachable from any commit's root tree.
Loosen the gate to "if (!info->trees && !info->blobs) continue" and
similarly retrieve the root_tree_list whenever either trees or
blobs are wanted.
2. The revision machinery's `handle_commit()` drops pending trees when
`revs->tree_objects` is zero (see the 'OBJ_TREE' handler in
revision.c), so by the time path-walk sees the pending list
after `prepare_revision_walk()` the tree-bearing pendings would
already be gone. Fix this by setting
revs->tree_objects = info->trees || info->blobs
so pending trees survive `prepare_revision_walk()` whenever we
need to walk into them. Path-walk still resets tree_objects to
zero immediately after `prepare_revision_walk()` returns, so the
rev-walk itself never enumerates trees redundantly with
path-walk's own descent.
Add coverage in t6601 for each of the four `object:type` values. The
'object:type=blob' test in particular asserts that file2 and child/file
(both reachable only through tag-pointed trees) show up in the output,
exercising the pending-tree fix.
Update Documentation/git-pack-objects.adoc to add object:type to
the list of supported --filter forms.
Signed-off-by: Taylor Blau <me@ttaylorr.com>
---
Documentation/git-pack-objects.adoc | 7 ++-
path-walk.c | 23 +++++++-
t/t6601-path-walk.sh | 86 +++++++++++++++++++++++++++++
3 files changed, 110 insertions(+), 6 deletions(-)
diff --git a/Documentation/git-pack-objects.adoc b/Documentation/git-pack-objects.adoc
index cfb5bc0ae16..22c782611d2 100644
--- a/Documentation/git-pack-objects.adoc
+++ b/Documentation/git-pack-objects.adoc
@@ -404,9 +404,10 @@ will be automatically changed to version `1`.
+
Incompatible with `--delta-islands`. Path-walk supports
the `--filter=<spec>` forms `blob:none`, `blob:limit=<n>`,
-`sparse:oid=<blob>`, and `tree:0`. Other filter forms fall back to the
-regular object traversal. The `--use-bitmap-index` option will be
-ignored in the presence of `--path-walk`.
+`sparse:oid=<blob>`, `tree:0`, and `object:type=<type>`. Other filter
+forms fall back to the regular object traversal. The
+`--use-bitmap-index` option will be ignored in the presence of
+`--path-walk`.
DELTA ISLANDS
diff --git a/path-walk.c b/path-walk.c
index 36a1e5b967a..b9902abbb75 100644
--- a/path-walk.c
+++ b/path-walk.c
@@ -430,7 +430,7 @@ static int setup_pending_objects(struct path_walk_info *info,
CALLOC_ARRAY(tags, 1);
if (info->blobs)
CALLOC_ARRAY(tagged_blobs, 1);
- if (info->trees)
+ if (info->trees || info->blobs)
root_tree_list = strmap_get(&ctx->paths_to_lists, root_path);
/*
@@ -475,7 +475,7 @@ static int setup_pending_objects(struct path_walk_info *info,
switch (obj->type) {
case OBJ_TREE:
- if (!info->trees)
+ if (!info->trees && !info->blobs)
continue;
if (pending->path) {
char *path = *pending->path ? xstrfmt("%s/", pending->path)
@@ -577,6 +577,16 @@ static int prepare_filters(struct path_walk_info *info,
}
return 1;
+ case LOFC_OBJECT_TYPE:
+ if (info) {
+ info->commits &= options->object_type == OBJ_COMMIT;
+ info->tags &= options->object_type == OBJ_TAG;
+ info->trees &= options->object_type == OBJ_TREE;
+ info->blobs &= options->object_type == OBJ_BLOB;
+ list_objects_filter_release(options);
+ }
+ return 1;
+
case LOFC_SPARSE_OID:
if (info) {
struct object_id sparse_oid;
@@ -683,9 +693,16 @@ int walk_objects_by_path(struct path_walk_info *info)
/*
* Set these values before preparing the walk to catch
* lightweight tags pointing to non-commits and indexed objects.
+ *
+ * Keep tree_objects set whenever blobs are wanted: blobs may
+ * be reachable through trees that show up as pending objects
+ * (e.g., via lightweight tags pointing to trees, or annotated
+ * tags whose peeled target is a tree). Without tree_objects,
+ * prepare_revision_walk() would discard those pending trees
+ * and we would never descend into them.
*/
info->revs->blob_objects = info->blobs;
- info->revs->tree_objects = info->trees;
+ info->revs->tree_objects = info->trees || info->blobs;
if (prepare_revision_walk(info->revs))
die(_("failed to setup revision walk"));
diff --git a/t/t6601-path-walk.sh b/t/t6601-path-walk.sh
index 72e09211e63..13016e62ab1 100755
--- a/t/t6601-path-walk.sh
+++ b/t/t6601-path-walk.sh
@@ -635,6 +635,92 @@ test_expect_success 'tree:1 filter is rejected' '
test_grep "tree:1 filter not supported by the path-walk API" err
'
+test_expect_success 'all, object:type=commit filter' '
+ test-tool path-walk --filter=object:type=commit -- --all >out &&
+
+ cat >expect <<-EOF &&
+ 0:commit::$(git rev-parse topic)
+ 0:commit::$(git rev-parse base)
+ 0:commit::$(git rev-parse base~1)
+ 0:commit::$(git rev-parse base~2)
+ blobs:0
+ commits:4
+ tags:0
+ trees:0
+ EOF
+
+ test_cmp_sorted expect out
+'
+
+test_expect_success 'all, object:type=tag filter' '
+ test-tool path-walk --filter=object:type=tag -- --all >out &&
+
+ cat >expect <<-EOF &&
+ 0:tag:/tags:$(git rev-parse refs/tags/first)
+ 0:tag:/tags:$(git rev-parse refs/tags/second.1)
+ 0:tag:/tags:$(git rev-parse refs/tags/second.2)
+ 0:tag:/tags:$(git rev-parse refs/tags/third)
+ 0:tag:/tags:$(git rev-parse refs/tags/fourth)
+ 0:tag:/tags:$(git rev-parse refs/tags/tree-tag)
+ 0:tag:/tags:$(git rev-parse refs/tags/blob-tag)
+ blobs:0
+ commits:0
+ tags:7
+ trees:0
+ EOF
+
+ test_cmp_sorted expect out
+'
+
+test_expect_success 'all, object:type=tree filter' '
+ test-tool path-walk --filter=object:type=tree -- --all >out &&
+
+ cat >expect <<-EOF &&
+ 0:tree::$(git rev-parse topic^{tree})
+ 0:tree::$(git rev-parse base^{tree})
+ 0:tree::$(git rev-parse base~1^{tree})
+ 0:tree::$(git rev-parse base~2^{tree})
+ 0:tree::$(git rev-parse refs/tags/tree-tag^{})
+ 0:tree::$(git rev-parse refs/tags/tree-tag2^{})
+ 1:tree:a/:$(git rev-parse base:a)
+ 2:tree:child/:$(git rev-parse refs/tags/tree-tag:child)
+ 3:tree:left/:$(git rev-parse base:left)
+ 3:tree:left/:$(git rev-parse base~2:left)
+ 4:tree:right/:$(git rev-parse topic:right)
+ 4:tree:right/:$(git rev-parse base~1:right)
+ 4:tree:right/:$(git rev-parse base~2:right)
+ blobs:0
+ commits:0
+ tags:0
+ trees:13
+ EOF
+
+ test_cmp_sorted expect out
+'
+
+test_expect_success 'all, object:type=blob filter' '
+ test-tool path-walk --filter=object:type=blob -- --all >out &&
+
+ cat >expect <<-EOF &&
+ 0:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag^{})
+ 0:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag2^{})
+ 1:blob:a:$(git rev-parse base~2:a)
+ 2:blob:file2:$(git rev-parse refs/tags/tree-tag2^{}:file2)
+ 3:blob:child/file:$(git rev-parse refs/tags/tree-tag:child/file)
+ 4:blob:left/b:$(git rev-parse base:left/b)
+ 4:blob:left/b:$(git rev-parse base~2:left/b)
+ 5:blob:right/c:$(git rev-parse base~2:right/c)
+ 5:blob:right/c:$(git rev-parse topic:right/c)
+ 6:blob:right/d:$(git rev-parse base~1:right/d)
+ blobs:10
+ commits:0
+ tags:0
+ trees:0
+ EOF
+
+ test_cmp_sorted expect out
+'
+
test_expect_success 'setup sparse filter blob' '
# Cone-mode patterns: include root, exclude all dirs, include left/
cat >patterns <<-\EOF &&
--
2.54.0.4.g6aa0d38a4ec
^ permalink raw reply related
* [RFC PATCH 2/7] path-walk: support `tree:0` filter
From: Taylor Blau @ 2026-05-04 0:11 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Derrick Stolee, Jeff King, Elijah Newren
In-Reply-To: <cover.1777853408.git.me@ttaylorr.com>
The `tree:0` object filter omits all trees and blobs from the result,
keeping only commits and tags. Consequently, this filter type should
has a fairly straightforward integration with path-walk, as the decision
to include an object depends only on its type and does not depend on any
path-sensitive state.
Mapping it onto `path_walk_info` is direct: set `info->trees = 0` and
`info->blobs = 0` in `prepare_filters()` when the `LOFC_TREE_DEPTH`
choice is requested with depth zero. The existing code already plumbs
those flags through the rest of the walk:
- 'walk_objects_by_path()' sets `revs->blob_objects = info->blobs` and
`revs->tree_objects = info->trees` before `prepare_revision_walk()`,
so the revision walk doesn't try to enumerate trees or blobs itself.
- The commit-walk loop short-circuits the root-tree fetch with
"if (!info->trees && !info->blobs) continue;", so we never even
look up the root tree, let alone descend into it.
- `setup_pending_objects()` skips pending trees and blobs based on
the same flags.
This means the path-walk doesn't allocate or expand any tree structures
at all under `tree:0`, which matches the intended behavior of the
filter.
Non-zero tree-depth filters are not supported. Those depend on the depth
at which a tree is visited, which is a path-walk concept the filter
machinery doesn't currently share with the path-walk API. Reject them in
`prepare_filters()` with a helpful error and let pack-objects fall back
to the regular traversal, the same way it already does for unsupported
filters.
Add coverage in t6601 for both `--all` and a single-branch case to
confirm that no trees or blobs are emitted, and a separate test that
`tree:1` is rejected with the expected error message. Place the new
tests before "setup sparse filter blob" so they run on the original set
of refs, before the orphan branch that the sparse-tree tests create.
Update Documentation/git-pack-objects.adoc to drop --filter from
the unconditional incompatibility list and call out the supported
subset (which already includes the filters added by Stolee's
earlier patches: blob:none, blob:limit, and sparse:oid).
Signed-off-by: Taylor Blau <me@ttaylorr.com>
---
Documentation/git-pack-objects.adoc | 10 +++----
path-walk.c | 13 +++++++++
t/t6601-path-walk.sh | 45 +++++++++++++++++++++++++++++
3 files changed, 63 insertions(+), 5 deletions(-)
diff --git a/Documentation/git-pack-objects.adoc b/Documentation/git-pack-objects.adoc
index 8dea8259787..cfb5bc0ae16 100644
--- a/Documentation/git-pack-objects.adoc
+++ b/Documentation/git-pack-objects.adoc
@@ -402,11 +402,11 @@ will be automatically changed to version `1`.
of filenames that cause collisions in Git's default name-hash
algorithm.
+
-Incompatible with `--delta-islands`. Path-walk supports the
-`--filter=<spec>` forms `blob:none`, `blob:limit=<n>`, and
-`sparse:oid=<blob>`. Other filter forms fall back to the regular object
-traversal. The `--use-bitmap-index` option will be ignored in the
-presence of `--path-walk`.
+Incompatible with `--delta-islands`. Path-walk supports
+the `--filter=<spec>` forms `blob:none`, `blob:limit=<n>`,
+`sparse:oid=<blob>`, and `tree:0`. Other filter forms fall back to the
+regular object traversal. The `--use-bitmap-index` option will be
+ignored in the presence of `--path-walk`.
DELTA ISLANDS
diff --git a/path-walk.c b/path-walk.c
index 700617ee2fe..36a1e5b967a 100644
--- a/path-walk.c
+++ b/path-walk.c
@@ -564,6 +564,19 @@ static int prepare_filters(struct path_walk_info *info,
}
return 1;
+ case LOFC_TREE_DEPTH:
+ if (options->tree_exclude_depth) {
+ error(_("tree:%lu filter not supported by the path-walk API"),
+ options->tree_exclude_depth);
+ return 0;
+ }
+ if (info) {
+ info->trees = 0;
+ info->blobs = 0;
+ list_objects_filter_release(options);
+ }
+ return 1;
+
case LOFC_SPARSE_OID:
if (info) {
struct object_id sparse_oid;
diff --git a/t/t6601-path-walk.sh b/t/t6601-path-walk.sh
index 520269dfc65..72e09211e63 100755
--- a/t/t6601-path-walk.sh
+++ b/t/t6601-path-walk.sh
@@ -590,6 +590,51 @@ test_expect_success 'all, blob:limit=3 filter' '
test_cmp_sorted expect out
'
+test_expect_success 'all, tree:0 filter' '
+ test-tool path-walk --filter=tree:0 -- --all >out &&
+
+ cat >expect <<-EOF &&
+ 0:commit::$(git rev-parse topic)
+ 0:commit::$(git rev-parse base)
+ 0:commit::$(git rev-parse base~1)
+ 0:commit::$(git rev-parse base~2)
+ 1:tag:/tags:$(git rev-parse refs/tags/first)
+ 1:tag:/tags:$(git rev-parse refs/tags/second.1)
+ 1:tag:/tags:$(git rev-parse refs/tags/second.2)
+ 1:tag:/tags:$(git rev-parse refs/tags/third)
+ 1:tag:/tags:$(git rev-parse refs/tags/fourth)
+ 1:tag:/tags:$(git rev-parse refs/tags/tree-tag)
+ 1:tag:/tags:$(git rev-parse refs/tags/blob-tag)
+ blobs:0
+ commits:4
+ tags:7
+ trees:0
+ EOF
+
+ test_cmp_sorted expect out
+'
+
+test_expect_success 'topic only, tree:0 filter' '
+ test-tool path-walk --filter=tree:0 -- topic >out &&
+
+ cat >expect <<-EOF &&
+ 0:commit::$(git rev-parse topic)
+ 0:commit::$(git rev-parse base~1)
+ 0:commit::$(git rev-parse base~2)
+ blobs:0
+ commits:3
+ tags:0
+ trees:0
+ EOF
+
+ test_cmp_sorted expect out
+'
+
+test_expect_success 'tree:1 filter is rejected' '
+ test_must_fail test-tool path-walk --filter=tree:1 -- --all 2>err &&
+ test_grep "tree:1 filter not supported by the path-walk API" err
+'
+
test_expect_success 'setup sparse filter blob' '
# Cone-mode patterns: include root, exclude all dirs, include left/
cat >patterns <<-\EOF &&
--
2.54.0.4.g6aa0d38a4ec
^ permalink raw reply related
* [RFC PATCH 1/7] pack-objects: update `--path-walk`'s existing incompatibilities
From: Taylor Blau @ 2026-05-04 0:11 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Derrick Stolee, Jeff King, Elijah Newren
In-Reply-To: <cover.1777853408.git.me@ttaylorr.com>
The documentation in git-pack-objects(1) claims that `--path-walk` is
incompatible with `-shallow`. However, commit c178b02e29f (pack-objects:
allow --shallow and --path-walk, 2025-05-16) resolves this
incompatibility, leaving the documentation stale.
Likewise, this documentation claims that `--filter` is incompatible, but
`blob:none`, `blob:limit=<n>`, and `sparse:oid=<blob>` already work via
path-walk.
List the supported `--filter` forms explicitly and note that other forms
fall back to the regular object traversal. Also remove the
incompatibility notice with `--shallow`.
Signed-off-by: Taylor Blau <me@ttaylorr.com>
---
Documentation/git-pack-objects.adoc | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/Documentation/git-pack-objects.adoc b/Documentation/git-pack-objects.adoc
index b78175fbe1b..8dea8259787 100644
--- a/Documentation/git-pack-objects.adoc
+++ b/Documentation/git-pack-objects.adoc
@@ -402,9 +402,11 @@ will be automatically changed to version `1`.
of filenames that cause collisions in Git's default name-hash
algorithm.
+
-Incompatible with `--delta-islands`, `--shallow`, or `--filter`. The
-`--use-bitmap-index` option will be ignored in the presence of
-`--path-walk.`
+Incompatible with `--delta-islands`. Path-walk supports the
+`--filter=<spec>` forms `blob:none`, `blob:limit=<n>`, and
+`sparse:oid=<blob>`. Other filter forms fall back to the regular object
+traversal. The `--use-bitmap-index` option will be ignored in the
+presence of `--path-walk`.
DELTA ISLANDS
--
2.54.0.4.g6aa0d38a4ec
^ permalink raw reply related
* [RFC PATCH 0/7] pack-bitmap: resolve various `--path-walk` incompatibilities
From: Taylor Blau @ 2026-05-04 0:11 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Derrick Stolee, Jeff King, Elijah Newren
(Note to the maintainer, this is built on top of 'ds/path-walk-filters').
Between other tasks, I have been working on trying to integrate
`--path-walk` within GitHub's infrastructure. In order to do this,
`--path-walk` must work with features that GitHub depends on, such as
reachability bitmaps and delta-islands (along with filters, shallow,
etc., though more on that below).
I had been sitting on these patches for a few days in my fork before
Stolee sent his series in [1] which resolves incompatibilities between
the `--path-walk` option and various filter types. Since I figured that
others are working in this area I wanted to send a reworked version of
my series for a couple of reasons:
1. Since reviewers are already looking at this area as a consequence of
Stolee's series, this topic should be slightly easier to review
while the area is fresh.
2. In case Stolee (or others) are working on resolving the
incompatibility between `--path-walk` and either delta-islands or
reachability bitmaps, this series can either combine with those (if
any) or serve as inspiration (if others are in the process of
writing such series).
When writing this originally, I had borrowed the same filter-application
mechanism from bitmaps, which supports trivial filters (e.g., blob:none,
tree:0, and combinations therein). Stolee's series is a strict
improvement on that approach supporting sparse:<oid> filters as well, so
I reworked my filtering-related patches based on that.
The patches surrounding bitmaps and delta-islands are largely
unchanged from when I had originally written them:
* Supporting bitmaps with `--path-walk` is mostly straightforward, and
boils down to ensuring that the path-walk-specific object callback
indexes any commit(s) it sees for bitmapping.
* Supporting delta-islands with `--path-walk` required a bit more
surgery, and involves propagating island marks for commits in the
path-walk-specific callback, as well as recording tree depth
information in the same spot.
I'm submitting these patches as an RFC, since (a) I haven't thought
deeply about the approach taken here and could very well be on the wrong
track, and (b) in case Stolee or others want to combine forces here
and/or coordinate around each other.
Thanks in advance for your review!
[1]: https://lore.kernel.org/git/pull.2101.git.1777731354.gitgitgadget@gmail.com/
Taylor Blau (7):
pack-objects: update `--path-walk`'s existing incompatibilities
path-walk: support `tree:0` filter
path-walk: support `object:type` filter
path-walk: support `combine` filter
pack-objects: support reachability bitmaps with `--path-walk`
pack-objects: extract `record_tree_depth()` helper
pack-objects: support `--delta-islands` with `--path-walk`
Documentation/git-pack-objects.adoc | 10 +-
builtin/pack-objects.c | 62 ++++++---
path-walk.c | 63 +++++++--
t/t5310-pack-bitmaps.sh | 36 +++++
t/t5320-delta-islands.sh | 29 ++++
t/t6601-path-walk.sh | 196 ++++++++++++++++++++++++++++
6 files changed, 365 insertions(+), 31 deletions(-)
base-commit: 465ceb37112ddfc6338727887f4431e755bf1831
--
2.54.0.4.g6aa0d38a4ec
^ permalink raw reply
* Re: [PATCH 4/7] backfill: die on incompatible filter options
From: Junio C Hamano @ 2026-05-03 22:59 UTC (permalink / raw)
To: Derrick Stolee via GitGitGadget
Cc: git, christian.couder, johannes.schindelin, johncai86,
karthik.188, kristofferhaugsbakk, me, newren, peff, ps,
Derrick Stolee
In-Reply-To: <22db528d0c5e6db71664f071dca97ab218f4ba45.1777731354.git.gitgitgadget@gmail.com>
"Derrick Stolee via GitGitGadget" <gitgitgadget@gmail.com> writes:
> From: Derrick Stolee <stolee@gmail.com>
>
> The 'git backfill' command uses the path-walk API in a critical way: it
> uses the objects output from the command to find the batches of missing
> objects that should be requested from the server. Unlike 'git
> pack-objects', we cannot fall back to another mechanism.
>
> The previous change added the path_walk_filter_compatible() method that
> we can reuse here. Use it during argument validation in cmd_backfill().
>
> Signed-off-by: Derrick Stolee <stolee@gmail.com>
> ---
> builtin/backfill.c | 2 ++
> t/t5620-backfill.sh | 8 ++++++++
> 2 files changed, 10 insertions(+)
Another topic adds a helper function to check for many incompatible
options and calls it from here. When I merged this topic, I made an
semi-evil merge to move this call to that function (with necessary
adjustment to the parameter). Please sanity check the resolution I
made in 'seen'. Thanks.
> diff --git a/builtin/backfill.c b/builtin/backfill.c
> index d794dd842f..51eaa42169 100644
> --- a/builtin/backfill.c
> +++ b/builtin/backfill.c
> @@ -144,6 +144,8 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit
>
> if (argc > 1)
> die(_("unrecognized argument: %s"), argv[1]);
> + if (!path_walk_filter_compatible(&ctx.revs.filter))
> + die(_("cannot backfill with these filter options"));
>
> repo_config(repo, git_default_config, NULL);
>
> diff --git a/t/t5620-backfill.sh b/t/t5620-backfill.sh
> index f3b5e39493..3580e10b9c 100755
> --- a/t/t5620-backfill.sh
> +++ b/t/t5620-backfill.sh
> @@ -15,6 +15,14 @@ test_expect_success 'backfill rejects unexpected arguments' '
> test_grep "unrecognized argument: --unexpected-arg" err
> '
>
> +test_expect_success 'backfill rejects incompatible filter options' '
> + test_must_fail git backfill --objects --filter=tree:1 2>err &&
> + test_grep "cannot backfill with these filter options" err &&
> +
> + test_must_fail git backfill --objects --filter=blob:limit=10m 2>err &&
> + test_grep "cannot backfill with these filter options" err
> +'
> +
> # We create objects in the 'src' repo.
> test_expect_success 'setup repo for object creation' '
> echo "{print \$1}" >print_1.awk &&
^ permalink raw reply
* Re: [PATCH] fetch: add fetch.pruneLocalBranches config
From: Junio C Hamano @ 2026-05-03 22:39 UTC (permalink / raw)
To: Harald Nordgren via GitGitGadget; +Cc: git, Harald Nordgren
In-Reply-To: <pull.2285.git.git.1777671337839.gitgitgadget@gmail.com>
"Harald Nordgren via GitGitGadget" <gitgitgadget@gmail.com> writes:
> Introduce a tri-state config option that, when --prune (or
> fetch.prune / remote.<name>.prune) removes a remote-tracking
> ref, also deletes local branches whose configured upstream is
> that ref.
>
> Values:
> - false (default): no change in behavior.
> - safe: delete only if the local tip is reachable from the
> upstream tip, preserving any unpushed work.
> - force: delete unconditionally; recoverable only via reflog.
>
> The currently checked-out branch is always preserved.
I do like the feature that allows you to identify which local
branches are already merged and prune them. It will help users keep
their local branch namespace clean.
I however do not like to see the feature tied to "fetch". By this,
I do not mean I do not want an option to trigger the feature when
"git fetch" is run. What I mean is that users should have an option
to prune merged branches without having to fetch first. And you can
then optionally trigger that machinery from "git fetch".
Of course they aleady can do something silly like
$ git branch -d $(git branch --list | sed -e 's/^..//')
and remove all the merged branches, but compared to what is
presented here, one thing missing is that you allow pruning the
local branches that are merged only to remote-tracking branches from
a single remote.
To break the feature down to make it easier to use by our users with
various needs and workflows, we would benefit from having a
collection of smaller features that can be composed, like these:
* "git branch --forked <remote>" lists local branches that build on
something taken from <remote>s. The option can be given multiple
times to make a union of the results from individual "--forked
<remote>".
- <remote> may be a name of a remote, e.g., "origin" to mean all
the remote-tracking branches "refs/remotes/origin/*",
- <remote> may be "origin/master" to name a specific
remote-tracking branch.
- There may be other handy things to cover with <remote>, like
"--all" that may act as if you listed all the available
<remote> on the command line.
* "git branch --prune-merged <remote>..." is a short-hand for "git
branch -d $(git branch --forked <remote>...".
* "git fetch/pull --prune-merged <remote>" can trigger "git branch
--prune-merged <remote>" after "git fetch" successfully updates
the remote-tracking branches, which should be equivalent to what
you have here..
Some local branches that fork from remote and have their initial
round already merged may not want to be pruned, however. You may
have multi-stage development plans for that topic, and you know
already the second phase would want to build on top of the initial
round, not a random version of the mainline with many topics from
other folks merged in. So you'd rather want to keep the topic
branch around after your initial round has been merged to the
upstream before you start the second phase. This is especially true
if your topic is designed to apply to an existing release (in other
words, a bugfix) and you want to keep the second and subsequent
rounds of the topic to be applicable to the same target version
without contaminating the topic with irrelevant features from others
that happened to have been developed and merged upstream around the
same time.
And we'd need to cater to their needs. By this, I do not mean "they
do not have to use --prune-merged", but by giving them a way to say
"this branch should not be auto-pruned with --prune-merged".
^ permalink raw reply
* [PATCH] checkout: add --autostash option for branch switching
From: Harald Nordgren @ 2026-05-03 22:32 UTC (permalink / raw)
To: gitster
Cc: ben.knoble, git, gitgitgadget, haraldnordgren,
kristofferhaugsbakk, marcnarc, ramsay
In-Reply-To: <xmqqse88ryyk.fsf@gitster.g>
> How about rewriting everything up to and including this "Tie the new
> ..." line perhaps like so:
Done!
Harald
^ permalink raw reply
* [PATCH v6] checkout: extend --track with a "fetch" mode to refresh start-point
From: Harald Nordgren via GitGitGadget @ 2026-05-03 22:31 UTC (permalink / raw)
To: git
Cc: Ramsay Jones, D. Ben Knoble, Kristoffer Haugsbakk, Marc Branchaud,
Harald Nordgren, Harald Nordgren
In-Reply-To: <pull.2281.v5.git.git.1777367012441.gitgitgadget@gmail.com>
From: Harald Nordgren <haraldnordgren@gmail.com>
If you want to fork your topic branch from the very latest of the
tip of a branch your remote has, you would do:
git fetch origin some-branch
git checkout -b new_branch --track origin/some-branch
Extend the "--track" option of "git checkout" and allow users to
write
git checkout -b new_branch --track=fetch origin/some-branch
to (1) fetch 'some-branch' from the remote 'origin', updating the
remote-tracking branch 'origin/some-branch', (2) arrange subsequent
'git pull' on 'new_branch' to interact with 'origin/some-branch' and
(3) fork 'new_branch' from it.
In the value of the '--track' option, 'fetch' can be combined with
the existing 'direct' (default) and 'inherit' modes via a
comma-separated list. Examples:
git checkout -b new_branch --track=fetch,inherit some_local_branch
git switch -c new_branch --track=fetch origin/some-branch
When "fetch" is requested and <start-point> is in <remote>/<branch>
form, run "git fetch <remote> <branch>" before resolving the ref, so
that other remote-tracking branches are left untouched. If
<start-point> is a bare remote name like "origin" (which resolves to
that remote's default branch), "git fetch <remote>" is run instead,
since the target branch is not known up front. Abort the checkout if
the fetch fails.
Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
---
checkout: add --fetch to fetch remote before resolving start-point
Commit message only, no code/doc/test changes. Restructured the opening
around the user-visible workflow before introducing '--track=fetch',
reordered all example invocations to ' -b/-c --track[=...] ', dropped
the "wrong/stale start-point" and "arbitrary commit" framings, and
trimmed the over-explanation of the narrowed fetch.
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2281%2FHaraldNordgren%2Fcheckout-fetch-start-point-v6
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2281/HaraldNordgren/checkout-fetch-start-point-v6
Pull-Request: https://github.com/git/git/pull/2281
Range-diff vs v5:
1: 8ebc2f94b9 ! 1: 1b42c648b9 checkout: extend --track with a "fetch" mode to refresh start-point
@@ Metadata
## Commit message ##
checkout: extend --track with a "fetch" mode to refresh start-point
- A common workflow is:
+ If you want to fork your topic branch from the very latest of the
+ tip of a branch your remote has, you would do:
- git fetch origin
+ git fetch origin some-branch
git checkout -b new_branch --track origin/some-branch
- The first command exists so the second sees an up-to-date view of the
- remote. If it is forgotten, origin/some-branch points at a stale
- commit and the new local branch is created from the wrong start
- point. This only matters when the user is setting up tracking and
- expects the new branch to start at the freshest tip; for a one-off
- checkout of an arbitrary commit there is no reason to "freshen" the
- start-point.
+ Extend the "--track" option of "git checkout" and allow users to
+ write
- Tie the new behavior to --track for that reason: extend its argument
- to take a comma-separated list, where "fetch" can be combined with the
- existing "direct" (default) and "inherit" modes. Examples:
+ git checkout -b new_branch --track=fetch origin/some-branch
- git checkout --track=fetch -b new_branch origin/some-branch
- git checkout --track=fetch,inherit -b new_branch some_local_branch
- git switch --track=fetch -c new_branch origin/some-branch
+ to (1) fetch 'some-branch' from the remote 'origin', updating the
+ remote-tracking branch 'origin/some-branch', (2) arrange subsequent
+ 'git pull' on 'new_branch' to interact with 'origin/some-branch' and
+ (3) fork 'new_branch' from it.
+
+ In the value of the '--track' option, 'fetch' can be combined with
+ the existing 'direct' (default) and 'inherit' modes via a
+ comma-separated list. Examples:
+
+ git checkout -b new_branch --track=fetch,inherit some_local_branch
+ git switch -c new_branch --track=fetch origin/some-branch
When "fetch" is requested and <start-point> is in <remote>/<branch>
- form, run "git fetch <remote> <branch>" before resolving the ref. This
- narrows the fetch to the requested branch so that other
- remote-tracking branches are left untouched -- many tools rely on the
- stability of remote-tracking refs between explicit fetches. If
+ form, run "git fetch <remote> <branch>" before resolving the ref, so
+ that other remote-tracking branches are left untouched. If
<start-point> is a bare remote name like "origin" (which resolves to
that remote's default branch), "git fetch <remote>" is run instead,
since the target branch is not known up front. Abort the checkout if
Documentation/git-checkout.adoc | 10 +++-
Documentation/git-switch.adoc | 10 +++-
builtin/checkout.c | 85 +++++++++++++++++++++++++++++++--
t/t7201-co.sh | 81 +++++++++++++++++++++++++++++++
4 files changed, 179 insertions(+), 7 deletions(-)
diff --git a/Documentation/git-checkout.adoc b/Documentation/git-checkout.adoc
index 43ccf47cf6..3b8292612d 100644
--- a/Documentation/git-checkout.adoc
+++ b/Documentation/git-checkout.adoc
@@ -158,11 +158,19 @@ of it").
resets _<branch>_ to the start point instead of failing.
`-t`::
-`--track[=(direct|inherit)]`::
+`--track[=(direct|inherit|fetch)[,...]]`::
When creating a new branch, set up "upstream" configuration. See
`--track` in linkgit:git-branch[1] for details. As a convenience,
--track without -b implies branch creation.
+
+The argument is a comma-separated list. `direct` (the default) and
+`inherit` select the tracking mode. Adding `fetch` requests that the
+remote be fetched before _<start-point>_ is resolved, so the new branch
+starts from a fresh tip: when _<start-point>_ is in
+_<remote>/<branch>_ form, only that branch is updated; when it is a
+bare remote name (e.g. `origin`), the whole remote is fetched. If the
+fetch fails, the checkout is aborted.
++
If no `-b` option is given, the name of the new branch will be
derived from the remote-tracking branch, by looking at the local part of
the refspec configured for the corresponding remote, and then stripping
diff --git a/Documentation/git-switch.adoc b/Documentation/git-switch.adoc
index 87707e9265..35a03e8a52 100644
--- a/Documentation/git-switch.adoc
+++ b/Documentation/git-switch.adoc
@@ -154,11 +154,19 @@ should result in deletion of the path).
attached to a terminal, regardless of `--quiet`.
`-t`::
-`--track[ (direct|inherit)]`::
+`--track[=(direct|inherit|fetch)[,...]]`::
When creating a new branch, set up "upstream" configuration.
`-c` is implied. See `--track` in linkgit:git-branch[1] for
details.
+
+The argument is a comma-separated list. `direct` (the default) and
+`inherit` select the tracking mode. Adding `fetch` requests that the
+remote be fetched before _<start-point>_ is resolved, so the new branch
+starts from a fresh tip: when _<start-point>_ is in
+_<remote>/<branch>_ form, only that branch is updated; when it is a
+bare remote name (e.g. `origin`), the whole remote is fetched. If the
+fetch fails, the switch is aborted.
++
If no `-c` option is given, the name of the new branch will be derived
from the remote-tracking branch, by looking at the local part of the
refspec configured for the corresponding remote, and then stripping
diff --git a/builtin/checkout.c b/builtin/checkout.c
index e031e61886..de4d7c00c7 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -30,7 +30,9 @@
#include "repo-settings.h"
#include "resolve-undo.h"
#include "revision.h"
+#include "run-command.h"
#include "setup.h"
+#include "strvec.h"
#include "submodule.h"
#include "symlinks.h"
#include "trace2.h"
@@ -61,6 +63,7 @@ struct checkout_opts {
int count_checkout_paths;
int overlay_mode;
int dwim_new_local_branch;
+ int fetch;
int discard_changes;
int accept_ref;
int accept_pathspec;
@@ -112,6 +115,74 @@ struct branch_info {
char *checkout;
};
+static void fetch_remote_for_start_point(const char *arg)
+{
+ const char *slash;
+ char *remote_name;
+ struct remote *remote;
+ struct child_process cmd = CHILD_PROCESS_INIT;
+
+ if (!arg || !*arg)
+ return;
+
+ slash = strchr(arg, '/');
+ if (slash == arg)
+ return;
+ remote_name = slash ? xstrndup(arg, slash - arg) : xstrdup(arg);
+
+ remote = remote_get(remote_name);
+ if (!remote || !remote_is_configured(remote, 1)) {
+ free(remote_name);
+ return;
+ }
+
+ strvec_pushl(&cmd.args, "fetch", remote_name, NULL);
+ if (slash && slash[1])
+ strvec_push(&cmd.args, slash + 1);
+ cmd.git_cmd = 1;
+ free(remote_name);
+ if (run_command(&cmd))
+ die(_("failed to fetch start-point '%s'"), arg);
+}
+
+static int parse_opt_checkout_track(const struct option *opt,
+ const char *arg, int unset)
+{
+ struct checkout_opts *opts = opt->value;
+ struct string_list tokens = STRING_LIST_INIT_DUP;
+ struct string_list_item *item;
+ int ret = 0;
+
+ if (unset) {
+ opts->track = BRANCH_TRACK_NEVER;
+ opts->fetch = 0;
+ return 0;
+ }
+
+ opts->track = BRANCH_TRACK_EXPLICIT;
+ if (!arg)
+ return 0;
+
+ string_list_split(&tokens, arg, ",", -1);
+ for_each_string_list_item(item, &tokens) {
+ if (!strcmp(item->string, "fetch")) {
+ opts->fetch = 1;
+ } else if (!strcmp(item->string, "direct")) {
+ opts->track = BRANCH_TRACK_EXPLICIT;
+ } else if (!strcmp(item->string, "inherit")) {
+ opts->track = BRANCH_TRACK_INHERIT;
+ } else {
+ ret = error(_("option `%s' expects \"%s\", \"%s\", "
+ "or \"%s\""),
+ "--track", "direct", "inherit", "fetch");
+ break;
+ }
+ }
+
+ string_list_clear(&tokens, 0);
+ return ret;
+}
+
static void branch_info_release(struct branch_info *info)
{
free(info->name);
@@ -1237,7 +1308,6 @@ static int git_checkout_config(const char *var, const char *value,
opts->dwim_new_local_branch = git_config_bool(var, value);
return 0;
}
-
if (starts_with(var, "submodule."))
return git_default_submodule_config(var, value, NULL);
@@ -1734,10 +1804,10 @@ static struct option *add_common_switch_branch_options(
{
struct option options[] = {
OPT_BOOL('d', "detach", &opts->force_detach, N_("detach HEAD at named commit")),
- OPT_CALLBACK_F('t', "track", &opts->track, "(direct|inherit)",
+ OPT_CALLBACK_F('t', "track", opts, "(direct|inherit|fetch)[,...]",
N_("set branch tracking configuration"),
PARSE_OPT_OPTARG,
- parse_opt_tracking_mode),
+ parse_opt_checkout_track),
OPT__FORCE(&opts->force, N_("force checkout (throw away local modifications)"),
PARSE_OPT_NOCOMPLETE),
OPT_STRING(0, "orphan", &opts->new_orphan_branch, N_("new-branch"), N_("new unborn branch")),
@@ -1942,8 +2012,13 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
opts->dwim_new_local_branch &&
opts->track == BRANCH_TRACK_UNSPECIFIED &&
!opts->new_branch;
- int n = parse_branchname_arg(argc, argv, dwim_ok, which_command,
- &new_branch_info, opts, &rev);
+ int n;
+
+ if (opts->fetch)
+ fetch_remote_for_start_point(argv[0]);
+
+ n = parse_branchname_arg(argc, argv, dwim_ok, which_command,
+ &new_branch_info, opts, &rev);
argv += n;
argc -= n;
} else if (!opts->accept_ref && opts->from_treeish) {
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 9bcf7c0b40..39236dca12 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -801,4 +801,85 @@ test_expect_success 'tracking info copied with autoSetupMerge=inherit' '
test_cmp_config "" --default "" branch.main2.merge
'
+test_expect_success 'setup upstream for --track=fetch tests' '
+ git checkout main &&
+ git init fetch_upstream &&
+ test_commit -C fetch_upstream u_main &&
+ git remote add fetch_upstream fetch_upstream &&
+ git fetch fetch_upstream &&
+ git -C fetch_upstream checkout -b fetch_new &&
+ test_commit -C fetch_upstream u_new
+'
+
+test_expect_success 'checkout --track=fetch -b picks up branch created upstream after clone' '
+ git checkout main &&
+ test_must_fail git rev-parse --verify refs/remotes/fetch_upstream/fetch_new &&
+ git checkout --track=fetch -b local_new fetch_upstream/fetch_new &&
+ test_cmp_rev refs/remotes/fetch_upstream/fetch_new HEAD &&
+ test_cmp_config fetch_upstream branch.local_new.remote &&
+ test_cmp_config refs/heads/fetch_new branch.local_new.merge
+'
+
+test_expect_success 'checkout --track=fetch <remote>/<branch> leaves other tracking branches untouched' '
+ git checkout main &&
+ git -C fetch_upstream checkout -b fetch_target &&
+ test_commit -C fetch_upstream u_target_pre &&
+ git -C fetch_upstream checkout -b fetch_other &&
+ test_commit -C fetch_upstream u_other_pre &&
+ git fetch fetch_upstream &&
+ other_before=$(git rev-parse refs/remotes/fetch_upstream/fetch_other) &&
+ git -C fetch_upstream checkout fetch_target &&
+ test_commit -C fetch_upstream u_target_post &&
+ git -C fetch_upstream checkout fetch_other &&
+ test_commit -C fetch_upstream u_other_post &&
+ git checkout --track=fetch -b local_target fetch_upstream/fetch_target &&
+ test_cmp_rev refs/remotes/fetch_upstream/fetch_target HEAD &&
+ test "$(git rev-parse refs/remotes/fetch_upstream/fetch_other)" = "$other_before"
+'
+
+test_expect_success 'checkout --track=fetch with bare remote name fetches the remote' '
+ git checkout main &&
+ git -C fetch_upstream checkout -b fetch_new2 &&
+ test_commit -C fetch_upstream u_new2 &&
+ test_must_fail git rev-parse --verify refs/remotes/fetch_upstream/fetch_new2 &&
+ git checkout --track=fetch -b local_from_remote fetch_upstream &&
+ git rev-parse --verify refs/remotes/fetch_upstream/fetch_new2
+'
+
+test_expect_success 'checkout --track=fetch aborts and does not create branch on fetch failure' '
+ git checkout main &&
+ test_might_fail git branch -D bogus &&
+ test_must_fail git checkout --track=fetch -b bogus fetch_upstream/does_not_exist &&
+ test_must_fail git rev-parse --verify refs/heads/bogus
+'
+
+test_expect_success 'checkout --track=fetch,inherit fetches and inherits' '
+ git checkout main &&
+ git -C fetch_upstream checkout -b fetch_inherit &&
+ test_commit -C fetch_upstream u_inherit &&
+ git fetch fetch_upstream fetch_inherit &&
+ git checkout -b base_inherit fetch_upstream/fetch_inherit &&
+ test_commit -C fetch_upstream u_inherit2 &&
+ git checkout main &&
+ git checkout --track=fetch,inherit -b local_inherit base_inherit &&
+ test_cmp_rev refs/remotes/fetch_upstream/fetch_inherit HEAD &&
+ test_cmp_config fetch_upstream branch.local_inherit.remote &&
+ test_cmp_config refs/heads/fetch_inherit branch.local_inherit.merge
+'
+
+test_expect_success 'checkout --track=bogus reports an error' '
+ git checkout main &&
+ test_must_fail git checkout --track=bogus -b bogus_branch fetch_upstream/fetch_new 2>err &&
+ test_grep "expects" err
+'
+
+test_expect_success 'switch --track=fetch -c picks up branch created upstream after clone' '
+ git checkout main &&
+ git -C fetch_upstream checkout -b fetch_switch &&
+ test_commit -C fetch_upstream u_switch &&
+ test_must_fail git rev-parse --verify refs/remotes/fetch_upstream/fetch_switch &&
+ git switch --track=fetch -c local_switch fetch_upstream/fetch_switch &&
+ test_cmp_rev refs/remotes/fetch_upstream/fetch_switch HEAD
+'
+
test_done
base-commit: 94f057755b7941b321fd11fec1b2e3ca5313a4e0
--
gitgitgadget
^ permalink raw reply related
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