* Re: [GSoC Patch v4 2/4] rev-parse: use append_formatted_path() for path formatting
From: Justin Tobler @ 2026-06-15 17:18 UTC (permalink / raw)
To: K Jayatheerth
Cc: git, a3205153416, gitster, kumarayushjha123, lucasseikioshiro,
phillip.wood, sandals, kristofferhaugsbakk
In-Reply-To: <20260615045112.50686-3-jayatheerthkulkarni2005@gmail.com>
On 26/06/15 10:21AM, K Jayatheerth wrote:
[snip]
> -static void print_path(const char *path, const char *prefix, enum format_type format, enum default_type def)
> +static void print_path(const char *path, const char *prefix,
> + enum path_format arg_path_format, enum path_format def_format)
> {
> - char *cwd = NULL;
> - /*
> - * We don't ever produce a relative path if prefix is NULL, so set the
> - * prefix to the current directory so that we can produce a relative
> - * path whenever possible. If we're using RELATIVE_IF_SHARED mode, then
> - * we want an absolute path unless the two share a common prefix, so don't
> - * set it in that case, since doing so causes a relative path to always
> - * be produced if possible.
> - */
> - if (!prefix && (format != FORMAT_DEFAULT || def != DEFAULT_RELATIVE_IF_SHARED))
> - prefix = cwd = xgetcwd();
> - if (format == FORMAT_DEFAULT && def == DEFAULT_UNMODIFIED) {
> - puts(path);
> - } else if (format == FORMAT_RELATIVE ||
> - (format == FORMAT_DEFAULT && def == DEFAULT_RELATIVE)) {
> - /*
> - * In order for relative_path to work as expected, we need to
> - * make sure that both paths are absolute paths. If we don't,
> - * we can end up with an unexpected absolute path that the user
> - * didn't want.
> - */
> - struct strbuf buf = STRBUF_INIT, realbuf = STRBUF_INIT, prefixbuf = STRBUF_INIT;
> - if (!is_absolute_path(path)) {
> - strbuf_realpath_forgiving(&realbuf, path, 1);
> - path = realbuf.buf;
> - }
> - if (!is_absolute_path(prefix)) {
> - strbuf_realpath_forgiving(&prefixbuf, prefix, 1);
> - prefix = prefixbuf.buf;
> - }
> - puts(relative_path(path, prefix, &buf));
> - strbuf_release(&buf);
> - strbuf_release(&realbuf);
> - strbuf_release(&prefixbuf);
> - } else if (format == FORMAT_DEFAULT && def == DEFAULT_RELATIVE_IF_SHARED) {
> - struct strbuf buf = STRBUF_INIT;
> - puts(relative_path(path, prefix, &buf));
> - strbuf_release(&buf);
> - } else {
> - struct strbuf buf = STRBUF_INIT;
> - strbuf_realpath_forgiving(&buf, path, 1);
> - puts(buf.buf);
> - strbuf_release(&buf);
> - }
> - free(cwd);
> + struct strbuf sb = STRBUF_INIT;
> + enum path_format fmt = (arg_path_format != PATH_FORMAT_DEFAULT) ? arg_path_format : def_format;
Without context, it might be a bit confusing to readers as to why we
override PATH_FORMAT_DEFAULT without our own provided default. It may be
worth leaving a comment to provide some breadcrumbs.
The rest of this patch looks good to me.
-Justin
^ permalink raw reply
* Re: [PATCH] builtin/history: unuse the commit buffer after use
From: Jeff King @ 2026-06-15 17:29 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: Kaartic Sivaraam, Git mailing list
In-Reply-To: <ai_KWo9o1Fhc6OFs@pks.im>
On Mon, Jun 15, 2026 at 11:48:10AM +0200, Patrick Steinhardt wrote:
> On Sun, Jun 14, 2026 at 02:15:40PM +0000, Kaartic Sivaraam wrote:
> > While running `git history reword` using a Git built with `SANITIZE` flag set
> > to `address,leak`, we could observe the following leak being reported:
>
> Huh, curious. That seems to hint that we're missing test coverage for
> this specific scenario, as our test suite doesn't detect this leak.
I think it will only leak when the commit object has an "encoding"
header. See below.
> > As part of rewording a commit in `git history`, we get the commit message
> > buffer in the `commit_tree_ext` function. This in turn obtains the buffer
> > from `repo_logmsg_reencode`. Given how `commit_tree_ext` is invoking the
> > function with the last two parameters as NULL, we are clearly not expecting
> > a reencode to happen. In this case, the buffer that we receive from
> > `repo_logmsg_reencode` ends up always being obtained from a call to
> > `repo_get_commit_buffer`.
> >
> > This buffer is expected to be released with an accompanying call to
> > `repo_unuse_commit_buffer` which takes care of freeing it. This call
> > is missing in the `commit_tree_ext` flow thus resulting in the leak.
>
> So this doesn't really read specific at all, and I would have expected
> us to hit this leak. Puzzling.
The first paragraph is accurate here. We'd generally just get a pointer
to the buffer cached in the slab, because no re-encoding occurs. And in
that case you _don't_ need to call unuse_commit_buffer(), because you
have a read-only copy, and the slab cache will hold it forever[1].
Calling the unuse function will be a noop.
But when we _do_ re-encode, then you get a new buffer which must be
freed. And that is when you have to call the unuse function. And the
reason it is "unuse" and not just "free" is that you don't necessarily
know which you have, but that function figures it out (and frees it only
if necessary).
So what the patch is doing is correct, but the explanation is a little
confused. We see the leak only when re-encoding, so we'd probably want a
test case that triggers that. Which I assume implies rewriting a commit
that was previously generated with an encoding header.
Now back to that [1] note. Even if we didn't re-encode, we'll still hold
onto that buffer forever. It's not a "leak" in the traditional sense
because it's still referenced in the commit slab cache. But if you are
going to walk over a million commits (like git-log does), you probably
don't want to hold a million commit messages in memory at once.
For that you'd want to call free_commit_buffer() when you know you're
totally done with it (again, like git-log does after it finishes showing
the commit). That might be the case here in commit_tree_ext(), or it
might happen later (I'm not familiar with the git-history code).
But note that you need to do _both_ the unuse and free calls. If we did
re-encode, the former is needed to free the newly allocated buffer. The
latter only drops the original buffer in the cache.
-Peff
^ permalink raw reply
* Re: [GSoC Patch v4 3/4] repo: add path.commondir with absolute and relative suffix formatting
From: Justin Tobler @ 2026-06-15 18:17 UTC (permalink / raw)
To: K Jayatheerth
Cc: git, a3205153416, gitster, kumarayushjha123, lucasseikioshiro,
phillip.wood, sandals, kristofferhaugsbakk
In-Reply-To: <20260615045112.50686-4-jayatheerthkulkarni2005@gmail.com>
On 26/06/15 10:21AM, K Jayatheerth wrote:
> Scripts working with worktree setups need a reliable way to discover
> the common directory, which diverges from the git directory when
> multiple worktrees are in use. There is no way to retrieve this path
> from git repo info today.
>
> Introduce path.commondir.absolute and path.commondir.relative keys.
> Exposing explicit format variants rather than a single key with a
> default avoids ambiguity for scripts that require predictable output.
>
> Add a test helper test_repo_info_path that creates isolated
> repositories per test case to prevent state leaks, captures the repo
> root before changing directories to avoid eval, and accepts an optional
> init_command to cover environment variable overrides such as
> GIT_COMMON_DIR and GIT_DIR.
I'm not sure this last paragraph in the log message provides much value.
To me it's a bit verbose and focuses mostly on what the test helper is
doing. Maybe we can just omit this section? If we want to have a note
though maybe we could say something like:
Each path key is expected to have an absolute and relative form. To
reduce duplication, a test_repo_info_path helper function is
introduced to configure and exercise both cases.
> Mentored-by: Justin Tobler <jltobler@gmail.com>
> Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
> Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
> ---
[snip]
> diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
> index 39bb77dda0..0c0228687f 100755
> --- a/t/t1900-repo-info.sh
> +++ b/t/t1900-repo-info.sh
> @@ -155,4 +155,65 @@ test_expect_success 'git repo info -h shows only repo info usage' '
> test_grep ! "git repo structure" actual
> '
>
> +# Helper function to test path keys in both absolute and relative formats.
> +# $1: label for the test
> +# $2: field_name (e.g., commondir)
> +# $3: unique repo name for isolation
> +# $4: expect_absolute (suffix appended to repo root)
> +# $5: expect_relative (the relative path string expected)
> +# $6: init_command (extra setup like exporting env vars)
> +test_repo_info_path () {
> + label=$1
> + field_name=$2
> + repo_name=$3
> + expect_absolute_suffix=$4
> + expect_relative=$5
> + init_command=$6
I may be overthinking it, but I can't help but feel this test helper is
overly complicated. I wonder if we can simlify and reduce the number of
arguments. For example, could we programatically construct the label
from the field name and init_command instead of explicitly passing it?
> + absolute_root="$repo_name-absolute"
> + relative_root="$repo_name-relative"
> +
> + test_expect_success "setup: $label" '
> + git init "$absolute_root" &&
> + git init "$relative_root" &&
> + mkdir -p "$absolute_root/sub" "$relative_root/sub"
> + '
Do really need this setup test case? Could we instead embed the setup in
both test cases below? Something like:
test_when_finished rm -rf repo &&
git init repo &&
(
mkdir repo/sub &&
cd repo/sub &&
...
)
With something like this, each test case is responsible to creating its
own repo and cleaning it up when finished. Then we could avoid have to
provide a separate repo name for each set of test cases and remove the
repo_name argument.
> + test_expect_success "absolute: $label" '
> + (
> + cd "$absolute_root/sub" &&
> + ROOT="$(test-tool path-utils real_path ..)" && export ROOT &&
> + eval "$init_command" &&
> + expect_path="$ROOT${expect_absolute_suffix:+/$expect_absolute_suffix}" &&
> + echo "path.$field_name.absolute=$expect_path" >expect &&
> + git repo info "path.$field_name.absolute" >actual &&
> + test_cmp expect actual
> + )
> + '
> +
> + test_expect_success "relative: $label" '
> + (
> + cd "$relative_root/sub" &&
> + ROOT="$(test-tool path-utils real_path ..)" && export ROOT &&
> + eval "$init_command" &&
> + echo "path.$field_name.relative=$expect_relative" >expect &&
> + git repo info "path.$field_name.relative" >actual &&
> + test_cmp expect actual
> + )
> + '
> +}
> +
> +test_repo_info_path 'commondir standard' 'commondir' 'commondir-std' \
> + '.git' '../.git'
> +
> +test_repo_info_path 'commondir with GIT_COMMON_DIR and GIT_DIR' 'commondir' \
> + 'commondir-envs' 'custom-common' '../custom-common' \
> + 'GIT_COMMON_DIR="$ROOT/custom-common" && export GIT_COMMON_DIR &&
> + GIT_DIR="../.git" && export GIT_DIR &&
> + git init --bare "$ROOT/custom-common"'
> +
> +test_repo_info_path 'commondir with only GIT_DIR' 'commondir' \
> + 'commondir-only-gitdir' '.git' '../.git' \
For each of these test cases, the `expect_absolute_suffix` and
`expect_relative` and exactly the same. This also appears to be the case
for the test cases in the next patch. Do these really need to be
configurable at all? Can we just embed them directly in each test case
assertion? Or maybe future keys will need this to be configurable?
> + 'GIT_DIR="../.git" && export GIT_DIR'
> +
> test_done
Overall the rest of the patch looks good to me.
-Justin
^ permalink raw reply
* What's cooking in git.git (Jun 2026, #05)
From: Junio C Hamano @ 2026-06-15 18:55 UTC (permalink / raw)
To: git
Here are the topics that have been cooking in my tree. Commits
prefixed with '+' are in 'next' (being in 'next' is a sign that a
topic is stable enough to be used and is a candidate to be in a
future release). Commits prefixed with '-' are only in 'seen', and
aren't considered "accepted" at all and may be annotated with a URL
to a message that raises issues but they are by no means exhaustive.
A topic without enough support may be discarded after a long period
of no activity (of course they can be resubmitted when new interests
arise).
A preview release Git 2.55-rc0 has been tagged and pushed out. There
may be a few more topics in 'next' and possibly outside 'next' that
we may want to include in the release that I didn't manage or I
forgot (please let me know).
Copies of the source code to Git live in many repositories, and the
following is a list of the ones I push into or their mirrors. Some
repositories have only a subset of branches.
With maint, master, next, seen, todo:
git://git.kernel.org/pub/scm/git/git.git/
git://repo.or.cz/alt-git.git/
https://kernel.googlesource.com/pub/scm/git/git/
https://github.com/git/git/
https://gitlab.com/git-scm/git/
With all the integration branches and topics broken out:
https://github.com/gitster/git/
Even though the preformatted documentation in HTML and man format
are not sources, they are published in these repositories for
convenience (replace "htmldocs" with "manpages" for the manual
pages):
git://git.kernel.org/pub/scm/git/git-htmldocs.git/
https://github.com/gitster/git-htmldocs.git/
Release tarballs are available at:
https://www.kernel.org/pub/software/scm/git/
--------------------------------------------------
[Graduated to 'master']
* ak/typofixes (2026-05-31) 1 commit
(merged to 'next' on 2026-06-09 at 40de2e7b90)
+ doc: fix typos via codespell
Typofixes.
cf. <3398ef40-1547-4324-2cfc-97b9e2b24854@gmx.de>
cf. <xmqq8q8p1ese.fsf@gitster.g>
source: <20260531184428.55905-1-algonell@gmail.com>
source: <20260506101631.18127-1-algonell@gmail.com>
source: <3398ef40-1547-4324-2cfc-97b9e2b24854@gmx.de>
* am/doc-tech-hash-typofix (2026-06-05) 1 commit
(merged to 'next' on 2026-06-09 at aeaf2363f8)
+ doc: fix typo in GIT_ALTERNATE_OBJECT_DIRECTORIES
Typofix.
cf. <aiZo9FqsdKrhz0gA@pks.im>
source: <20260605172643.8796-1-amonakov@ispras.ru>
* hn/config-typo-advice (2026-06-02) 2 commits
(merged to 'next' on 2026-06-09 at 5149e69e3e)
+ config: improve diagnostic for "set" with missing value
+ config: add git_config_key_is_valid() for quiet validation
"git config foo.bar=baz" is not likely to be a request to read the
value of such a variable with '=' in its name; rather it is plausible
that the user meant "git config set foo.bar baz". Give advice when
giving an error message.
cf. <xmqq1penqfg2.fsf@gitster.g>
source: <pull.2302.v6.git.git.1780425808.gitgitgadget@gmail.com>
* jc/submitting-patches-cover-letter (2026-06-02) 2 commits
(merged to 'next' on 2026-06-09 at 42b2538a2a)
+ SubmittingPatches: describe cover letter
+ SubmittingPatches: separate typofixes section
Guidelines on how to write a cover letter for a multi-patch series
have been added to SubmittingPatches, which also got a new marker
to separate the section for typofixes.
cf. <c54f3571-ff7b-4caa-b75d-a739ed87ec9d@gmail.com>
cf. <aiEgUdnL8dkszKFn@pks.im>
source: <20260602144304.3341000-1-gitster@pobox.com>
* lo/doc-format-patch-subject-prefix (2026-06-04) 1 commit
(merged to 'next' on 2026-06-09 at 58b2a20f6d)
+ Documentation: remove redundant 'instead' in --subject-prefix
Wording used in "format-patch --subject-prefix" documentation
has been improved.
source: <20260604163510.36687-2-lucasseikioshiro@gmail.com>
* ls/doc-raw-timestamp-prefix (2026-06-02) 1 commit
(merged to 'next' on 2026-06-09 at 7198b6bb9d)
+ doc: document and test `@` prefix for raw timestamps
Documentation and tests have been added to clarify that Git's internal
raw timestamp format requires a `@` prefix for values less than
100,000,000 to prevent ambiguity with other formats like YYYYMMDD.
cf. xmqqmrxdxq1r.fsf@gitster.g>
source: <20260602081924.673763-2-dev@luna.gl>
* ob/more-repo-config-values (2026-06-02) 8 commits
(merged to 'next' on 2026-06-09 at 3d0b057aee)
+ environment: move "warn_on_object_refname_ambiguity" into `struct repo_config_values`
+ environment: move "sparse_expect_files_outside_of_patterns" into `struct repo_config_values`
+ environment: move "core_sparse_checkout_cone" into `struct repo_config_values`
+ environment: move "precomposed_unicode" into `struct repo_config_values`
+ environment: move "pack_compression_level" into `struct repo_config_values`
+ environment: move `zlib_compression_level` into `struct repo_config_values`
+ environment: move "check_stat" into `struct repo_config_values`
+ environment: move "trust_ctime" into `struct repo_config_values`
Many core configuration variables have been migrated from global
variables into 'repo_config_values' to tie them to a specific
repository instance, avoiding cross-repository state leakage.
source: <20260602170921.35869-1-belkid98@gmail.com>
* ps/setup-centralize-odb-creation (2026-06-04) 9 commits
(merged to 'next' on 2026-06-09 at a1f23cb38c)
+ setup: construct object database in `apply_repository_format()`
+ repository: stop reading loose object map twice on repo init
+ setup: stop initializing object database without repository
+ setup: stop creating the object database in `setup_git_env()`
+ repository: stop initializing the object database in `repo_set_gitdir()`
+ setup: deduplicate logic to apply repository format
+ setup: drop `setup_git_env()`
+ t0001: plug test gaps for git-init(1) with GIT_OBJECT_DIRECTORY
+ Merge branch 'ps/setup-wo-the-repository' into ps/setup-centralize-odb-creation
(this branch is used by ps/refs-avoid-chdir-notify-reparent and ps/setup-drop-global-state.)
The setup logic to discover and configure repositories has been
refactored, and the initialization of the object database has been
centralized.
cf. <CAOLa=ZQwVbLsOcajaxQwtkTPm=4St7EiGEEyL6_B0o3Tt1v1pw@mail.gmail.com>
source: <20260604-b4-pks-setup-centralize-odb-creation-v3-0-0691834f318a@pks.im>
--------------------------------------------------
[New Topics]
* kh/submittingpatches-trailers (2026-06-10) 6 commits
- SubmittingPatches: note that trailer order matters
- SubmittingPatches: be consistent with trailer markup
- SubmittingPatches: document Based-on-patch-by trailer
- SubmittingPatches: discourage common Linux trailers
- SubmittingPatches: discuss non-ident trailers
- SubmittingPatches: encourage trailer use for substantial help
The trailer sections in SubmittingPatches have been updated to
encourage use of standard trailers.
Waiting for response(s) to review comment(s).
cf. <xmqqse6tnho1.fsf@gitster.g>
source: <CV_SubPatches_trailers.8f3@msgid.xyz>
* mv/log-follow-mergy (2026-06-14) 1 commit
- log: improve --follow following renames for non-linear history
"git log --follow" has been updated to handle non-linear history, in
which the path being tracked gets renamed differently in multiple
history lines, better.
Needs review.
source: <ai-aE83w02xPRlPr@collabora.com>
* wy/doc-myfirstcontribution-trim-quotes (2026-06-11) 1 commit
- MyFirstContribution: mention trimming quoted text in replies
The contributor guide has been updated to advise new contributors to
trim irrelevant quoted text when replying to review comments, matching
the existing advice given to reviewers.
Comments?
cf. <xmqqcxxwljue.fsf@gitster.g>
source: <080402ff0ac8127b654dccea59a1bf643df62a5c.1781186476.git.wy@wyuan.org>
* td/ls-files-pathspec-prefilter (2026-06-11) 1 commit
(merged to 'next' on 2026-06-15 at 38918c4cfd)
+ ls-files: filter pathspec before lstat
`git ls-files --modified` and `git ls-files --deleted` have been
optimized to filter with pathspec before calling lstat() when there is
only a single pathspec item, avoiding unnecessary filesystem access
for entries that will not be shown.
Will merge to 'master'.
cf. <xmqqfr2tnfk0.fsf@gitster.g>
source: <20260611-ls-files-pathspec-lstat-v3-1-f967e1a00c13@gmail.com>
* tb/midx-incremental-custom-base (2026-06-12) 3 commits
- midx-write: include packs above custom incremental base
- midx: pass custom '--base' through incremental writes
- t5334: expose shared `nth_line()` helper
The `git multi-pack-index write --incremental` command has been
corrected to properly honor the `--base` option. Previously, the
custom base was ignored by the normal write path, and the pack
exclusion logic incorrectly skipped packs from layers above the
selected base, breaking reachability closure for bitmaps.
Needs review.
source: <cover.1781294771.git.me@ttaylorr.com>
* en/commit-graph-timestamp-fix (2026-06-13) 1 commit
- commit-graph: use timestamp_t for max parent generation accumulator
compute_reachable_generation_numbers() in commit-graph used a 32-bit
integer to accumulate parent generations, which is OK for generation
number v1 (topological levels), but with generation number v2
(adjusted committer timestamps), it truncated timestamps beyond
2106. Fixed by widening the accumulator to timestamp_t.
Will merge to 'next'?
cf. <ai-zzWn9Ls6-j9h8@pks.im>
source: <pull.2148.git.1781420271100.gitgitgadget@gmail.com>
* mm/test-grep-lint (2026-06-12) 6 commits
. t: add greplint to detect bare grep assertions
. t: convert grep assertions to test_grep
. t: fix Lexer line count for $() inside double-quoted strings
. t: extract chainlint's parser into shared module
. t: fix grep assertions missing file arguments
. t/README: document test_grep helper
Needs review.
source: <pull.2135.v2.git.1781323575.gitgitgadget@gmail.com>
* js/objects-larger-than-4gb-on-windows-more (2026-06-15) 7 commits
- odb: use size_t for object_info.sizep and the size APIs
- packfile,delta: drop the `cast_size_t_to_ulong()` wrappers
- pack-objects: use size_t for in-core object sizes
- packfile: widen unpack_entry()'s size out-parameter to size_t
- pack-objects(check_pack_inflate()): use size_t instead of unsigned long
- patch-delta: use size_t for sizes
- compat/msvc: use _chsize_s for ftruncate
source: <pull.2137.v2.git.1781524349.gitgitgadget@gmail.com>
* kw/gitattributes-typofix (2026-06-15) 1 commit
- gitattributes: fix eol attribute for Perl scripts
source: <pull.2151.v2.git.1781510039164.gitgitgadget@gmail.com>
* rs/cat-file-default-format-optim (2026-06-14) 1 commit
- cat-file: speed up default format
source: <5a7ed929-6fe0-496c-83bd-65dee57c2241@web.de>
--------------------------------------------------
[Cooking]
* js/parseopt-subcommand-autocorrection (2026-04-27) 11 commits
- SQUASH???
- doc: document autocorrect API
- parseopt: add tests for subcommand autocorrection
- parseopt: enable subcommand autocorrection for git-remote and git-notes
- parseopt: autocorrect mistyped subcommands
- autocorrect: provide config resolution API
- autocorrect: rename AUTOCORRECT_SHOW to AUTOCORRECT_HINT
- autocorrect: use mode and delay instead of magic numbers
- help: move tty check for autocorrection to autocorrect.c
- help: make autocorrect handling reusable
- parseopt: extract subcommand handling from parse_options_step()
The parse-options library learned to auto-correct misspelled
subcommand names.
Expecting a reroll for too long. stalled.
cf. <SY0P300MB0801E50FCB7EB2F45CD15208CE042@SY0P300MB0801.AUSP300.PROD.OUTLOOK.COM>
source: <SY0P300MB0801677A2A1E0FD38D06A841CE2A2@SY0P300MB0801.AUSP300.PROD.OUTLOOK.COM>
* kk/prio-queue-get-put-fusion (2026-06-08) 2 commits
- prio-queue: fold lazy_queue into prio_queue for automatic get+put fusion
- prio-queue: rename .nr to .nr_ and add accessor helpers
The lazy priority queue optimization pattern (deferring actual removal
in prio_queue_get() to allow get+put fusion) has been folded directly
into prio_queue itself, speeding up commit traversal workflows and
simplifying callers.
Comments?
source: <pull.2140.v4.git.1780945851.gitgitgadget@gmail.com>
* kk/remove-get-reachable-subset (2026-06-11) 1 commit
- commit-reach: remove get_reachable_subset()
API clean-up.
Waiting for response(s) to review comment(s).
cf. <3a3d1dc4-341f-4276-a1ee-2972a885db84@gmail.com>
source: <pull.2144.v2.git.1781178567862.gitgitgadget@gmail.com>
* td/ref-filter-memoize-contains (2026-06-12) 3 commits
- commit-reach: die on contains walk errors
- ref-filter: memoize --contains with generations
- commit-reach: reject cycles in contains walk
'git branch --contains' and 'git for-each-ref --contains' have
been optimized to use the memoized commit traversal previously
used only by 'git tag --contains', significantly speeding up
connectivity checks across many candidate refs with shared
history.
Needs review.
source: <20260612-ref-filter-memoized-contains-v4-0-5ed39fd001dd@gmail.com>
* tc/replay-linearize (2026-06-10) 3 commits
- replay: offer an option to linearize the commit topology
- replay: add helper to put entry into mapped_commits
- replay: refactor enum replay_mode into a bool
git replay learns --linearize option to drop merge commits and
linearize the replayed history, mimicking git rebase
--no-rebase-merges.
Waiting for response(s) to review comment(s).
cf. <xmqqjys6wcpo.fsf@gitster.g>
cf. <CABPp-BGRi2obnqRGEY9pSMyvRbNGs8AdVUpZmr0C6vZSgHb=cg@mail.gmail.com>
source: <20260610-toon-git-replay-drop-merges-v2-0-5714a71c6d83@iotcl.com>
* td/describe-tag-iteration (2026-06-10) 1 commit
(merged to 'next' on 2026-06-15 at 1ae171f3b7)
+ describe: limit default ref iteration to tags
'git describe' has been taught to pass the 'refs/tags/' prefix down to
the ref iterator when '--all' is not requested, avoiding unnecessary
iteration over non-tag refs.
Will merge to 'master'.
cf. <20260611064912.GC2191159@coredump.intra.peff.net>
source: <20260610-describe-tag-ref-scope-v3-1-5aa63ab279f7@gmail.com>
* ta/doc-config-adoc-fixes (2026-06-11) 3 commits
(merged to 'next' on 2026-06-15 at 93340b5cf0)
+ doc: git-config: escape erroneous highlight markup
+ doc: config/sideband: fix description list delimiter
+ doc: config: terminate runaway lists
Various AsciiDoc markup fixes in 'git config' documentation and
related files to ensure lists and formatting are rendered correctly.
Will merge to 'master'.
cf. <20260612045329.GA593075@coredump.intra.peff.net>
source: <20260611161946.12166-1-taahol@utu.fi>
* ps/setup-drop-global-state (2026-06-10) 8 commits
(merged to 'next' on 2026-06-15 at d9a8b88d47)
+ treewide: drop USE_THE_REPOSITORY_VARIABLE
+ environment: stop using `the_repository` in `is_bare_repository()`
+ environment: split up concerns of `is_bare_repository_cfg`
+ builtin/init: stop modifying `is_bare_repository_cfg`
+ setup: remove global `git_work_tree_cfg` variable
+ builtin/init: simplify logic to configure worktree
+ builtin/init: stop modifying global `git_work_tree_cfg` variable
+ Merge branch 'ps/setup-centralize-odb-creation' into ps/setup-drop-global-state
Continuation of "setup.c" refactoring to drop remaining global state
(`git_work_tree_cfg`, `is_bare_repository_cfg`). The most notable
outcome is that `is_bare_repository()` has been updated to no longer
implicitly rely on `the_repository`.
Will merge to 'master'.
cf. <airVOrTboNDDGBak@denethor>
cf. <87ldckyygk.fsf@emacs.iotcl.com>
source: <20260611-b4-pks-setup-drop-global-state-v2-0-a6f7269c841d@pks.im>
* ps/refs-avoid-chdir-notify-reparent (2026-06-15) 9 commits
- refs: drop local buffer in `refs_compute_filesystem_location()`
- refs: fix recursing `get_main_ref_store()` with "onbranch" config
- repository: free main reference database
- chdir-notify: drop unused `chdir_notify_reparent()`
- refs: unregister reference stores from "chdir_notify"
- setup: don't apply "GIT_REFERENCE_BACKEND" without a repository
- setup: stop applying repository format twice
- setup: inline `check_and_apply_repository_format()`
- Merge branch 'ps/setup-centralize-odb-creation' into ps/refs-avoid-chdir-notify-reparent
The reference backends have been converted to always use absolute
paths internally. This allows dropping the calls to
`chdir_notify_reparent()` and fixes a memory leak in how the
reference database is constructed with an "onbranch" condition.
Needs review.
source: <20260615-b4-pks-refs-avoid-chdir-notify-reparent-v2-0-f4854aa99859@pks.im>
* jc/t1400-fifo-cleanup (2026-06-10) 1 commit
(merged to 'next' on 2026-06-15 at 7d5acd110a)
+ t1400: have fifo test clean after itself
Test cleanup.
Will merge to 'master'.
cf. <aiqs5Wq2Di-6yW0D@pks.im>
source: <xmqqo6hit6rn.fsf@gitster.g>
* jd/unpack-trees-wo-the-repository (2026-03-31) 1 commit
(merged to 'next' on 2026-06-11 at 3d7788721e)
+ unpack-trees: use repository from index instead of global
A handful of inappropriate uses of the_repository have been
rewritten to use the right repository structure instance in the
unpack-trees.c codepath.
Will merge to 'master'.
cf. <xmqqqzmfz91r.fsf@gitster.g>
source: <pull.2258.v2.git.git.1774971267.gitgitgadget@gmail.com>
* ps/odb-source-packed (2026-06-09) 18 commits
- odb/source-packed: drop pointer to "files" parent source
- midx: refactor interfaces to work on "packed" source
- odb/source-packed: stub out remaining functions
- odb/source-packed: wire up `freshen_object()` callback
- odb/source-packed: wire up `find_abbrev_len()` callback
- odb/source-packed: wire up `count_objects()` callback
- odb/source-packed: wire up `for_each_object()` callback
- odb/source-packed: wire up `read_object_stream()` callback
- odb/source-packed: wire up `read_object_info()` callback
- packfile: use higher-level interface to implement `has_object_pack()`
- odb/source-packed: wire up `reprepare()` callback
- odb/source-packed: wire up `close()` callback
- odb/source-packed: start converting to a proper `struct odb_source`
- odb/source-packed: store pointer to "files" instead of generic source
- packfile: move packed source into "odb/" subsystem
- packfile: split out packfile list logic
- packfile: rename `struct packfile_store` to `odb_source_packed`
- Merge branch 'ps/odb-source-loose' into ps/odb-source-packed
The packed object source has been refactored into a proper struct
odb_source.
Needs review.
source: <20260609-pks-odb-source-packed-v2-0-839089132c8b@pks.im>
* ps/transport-helper-tsan-fix (2026-06-09) 1 commit
(merged to 'next' on 2026-06-15 at 0857e6696f)
+ transport-helper: fix TSAN race in transfer_debug()
The TSAN race in transfer_debug() within transport-helper.c has been
resolved by initializing the debug flag early in
bidirectional_transfer_loop() before spawning worker threads, allowing
the removal of a TSAN suppression.
Will merge to 'master'.
cf. <20260609002833.GE358144@coredump.intra.peff.net>
cf. <20260611083320.GI2191159@coredump.intra.peff.net>
source: <20260609134741.4727-2-pushkarkumarsingh1970@gmail.com>
* ta/typofixes (2026-06-04) 1 commit
(merged to 'next' on 2026-06-11 at dfb63ded01)
+ docs: fix typos
Typofixes
Will merge to 'master'.
cf. <xmqqh5ncvfsu.fsf@gitster.g>
source: <20260604131457.19215-1-taahol@utu.fi>
* js/win-kill-child-more-gently (2026-06-04) 2 commits
(merged to 'next' on 2026-06-11 at b4a2299e7e)
+ mingw: really handle SIGINT
+ mingw: kill child processes in a gentler way
Advanced emulation of kill() used on Windows in GfW has been
upstreamed to improve the symptoms like left-behind .lock files and
that fails to let the child clean-up itself when it gets killed.
Will merge to 'master'.
source: <pull.2130.git.1780590261.gitgitgadget@gmail.com>
* dl/posix-unused-warning-clang (2026-06-13) 3 commits
(merged to 'next' on 2026-06-15 at 1d7e627c24)
+ compat/posix.h: simplify GIT_GNUC_PREREQ() comparison
+ compat/posix.h: clean up GIT_GNUC_PREREQ() and UNUSED
+ compat/posix.h: enable UNUSED warning messages for Clang
The UNUSED macro in 'compat/posix.h' has been updated to use a
newly introduced GIT_CLANG_PREREQ macro for compiler version
checks, and the existing GIT_GNUC_PREREQ macro has been modernized
to use explicit major/minor comparisons rather than bit-shifting.
Will merge to 'master'.
cf. <ai-8Y1r9zbWfdY8p@pks.im>
source: <20260613122711.38662-1-dominik.loidolt@univie.ac.at>
* td/ref-filter-restore-prefix-iteration (2026-06-12) 1 commit
- ref-filter: restore prefix-scoped iteration
Commands that list branches and tags (like git branch and git tag)
have been optimized to pass the namespace prefix when initializing
their ref iterator, avoiding a loose-ref scaling regression in
repositories with many unrelated loose references.
Needs review.
source: <20260612-fix-git-branch-regression-v4-1-f150038c02f4@gmail.com>
* ty/move-protect-hfs-ntfs (2026-06-10) 1 commit
(merged to 'next' on 2026-06-15 at c2a30ca954)
+ environment: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values'
The global configuration variables protect_hfs and protect_ntfs have
been migrated into struct repo_config_values to tie them to
per-repository configuration state.
Will merge to 'master'.
cf. <CAP8UFD35Tiy1_fqpjq8P-z=ZhzR3MTiThqfCs977652umRoSEQ@mail.gmail.com>
cf. <xmqqse6uwdnz.fsf@gitster.g>
source: <20260610124353.149874-2-cat@malon.dev>
* ds/config-no-includes (2026-06-08) 3 commits
- git: add --no-includes top-level option
- config: add GIT_CONFIG_INCLUDES
- git-config.adoc: fix paragraph break
Two new mechanisms, the GIT_CONFIG_INCLUDES environment variable and
the top-level --no-includes command-line option, have been introduced
to ignore configuration include directives.
Retracted.
cf. <539713c4-b291-42e6-8541-a16a454518f5@gmail.com>
source: <pull.2139.git.1780927027.gitgitgadget@gmail.com>
* ps/cat-file-remote-object-info (2026-06-08) 12 commits
- cat-file: make remote-object-info allow-list dynamic
- cat-file: validate remote atoms with allow_list
- cat-file: add remote-object-info to batch-command
- transport: add client support for object-info
- serve: advertise object-info feature
- fetch-pack: move fetch initialization
- connect: refactor packet writing
- fetch-pack: move function to connect.c
- t1006: split test utility functions into new "lib-cat-file.sh"
- cat-file: add declaration of variable i inside its for loop
- git-compat-util: add strtoul_ul() with error handling
- transport-helper: fix memory leak of helper on disconnect
The `remote-object-info` command has been added to `git cat-file
--batch-command`, allowing clients to request object metadata
(currently size) from a remote server via protocol v2 without
downloading the entire object.
The client dynamically filters format placeholders based on
server-advertised capabilities and safely returns empty strings for
inapplicable or unsupported fields.
Expecting a reroll.
cf. <CAN5EUNQQBRoHUbZtkhLoBX-K7_4Carsxws_fyh1Ac7Lmd_FjKg@mail.gmail.com>
source: <20260608-ps-eric-work-rebase-v12-0-5338b766e658@gmail.com>
* ap/http-redirect-wwwauth-fix (2026-06-02) 1 commit
- http: preserve wwwauth_headers across redirects
When cURL follows a redirect, the WWW-Authenticate headers from the
redirect target were lost because credential_from_url() cleared the
credential state. This has been fixed by preserving the collected
headers across the redirect update.
Expecting a reroll.
cf. <5144a29d-a53f-4446-beff-e1f549345bf9@nvidia.com>
source: <20260602161150.1527493-1-aplattner@nvidia.com>
* ps/doc-recommend-b4 (2026-06-15) 3 commits
- b4: introduce configuration for the Git project
- MyFirstContribution: recommend the use of b4
- MyFirstContribution: recommend shallow threading of cover letters
Project-specific configuration for b4 has been introduced, and the
documentation has been updated to recommend using it as a
streamlined method for submitting patches.
Needs review.
source: <20260615-pks-b4-v4-0-22cfca8f19c5@pks.im>
* kk/streaming-walk-pqueue (2026-05-27) 3 commits
(merged to 'next' on 2026-06-11 at 1466219fc9)
+ revision: use priority queue for non-limited streaming walks
+ revision: introduce rev_walk_mode to clarify get_revision_1()
+ pack-objects: call release_revisions() after cruft traversal
Streaming revision walks have been optimized by using a priority queue
for date-sorting commits, speeding up walks repositories with many
merges.
Will merge to 'master'.
source: <pull.2127.git.1779897003.gitgitgadget@gmail.com>
* sn/rebase-update-refs-symrefs (2026-06-03) 1 commit
- rebase: skip branch symref aliases
"git rebase --update-refs" has been taught to resolve local branch
symrefs to their referents before queuing updates. This correctly
skips aliases of the current branch and avoids duplicate updates for
underlying real branches, fixing failures when branch aliases (like a
default branch rename) are present.
Waiting for response(s) to review comment(s).
cf. <f982c386-e329-4ab0-b695-e540bcb9de3d@gmail.com>
source: <pull.2126.v2.git.1780482436865.gitgitgadget@gmail.com>
* jk/describe-contains-all-match-fix (2026-06-01) 1 commit
(merged to 'next' on 2026-06-11 at a95871538b)
+ describe: fix --exclude, --match with --contains and --all
The 'git describe --contains --all' command has been fixed to
properly honor the '--match' and '--exclude' options by passing
them down to 'git name-rev' with the appropriate reference
prefixes.
Will merge to 'master'.
source: <20260601233727.43558-1-jacob.e.keller@intel.com>
* wy/docs-typofixes (2026-05-29) 1 commit
(merged to 'next' on 2026-06-11 at bd53c91110)
+ docs: fix typos and grammar
Various typos, grammatical errors, and duplicated words in both
documentation and code comments have been corrected.
Will merge to 'master'.
source: <7b502e20e9495cd4720496bd6738a1fbeb453410.1780041658.git.wy@wyuan.org>
* ab/index-pack-retain-child-bases (2026-06-01) 1 commit
(merged to 'next' on 2026-06-12 at 625f76ac4c)
+ index-pack: retain child bases in delta cache
"git index-pack" has been optimized by retaining child bases in the
delta cache instead of immediately freeing them, letting the existing
cache limit policy decide eviction.
Will merge to 'master'.
source: <pull.2131.v2.git.1780330402264.gitgitgadget@gmail.com>
* mm/diff-process-hunks (2026-06-14) 6 commits
- blame: consult diff process for no-hunk detection
- diff: bypass diff process with --no-ext-diff and in format-patch
- diff: add long-running diff process via diff.<driver>.process
- sub-process: separate process lifecycle from hashmap management
- userdiff: add diff.<driver>.process config
- xdiff: support external hunks via xpparam_t
A new `diff.<driver>.process` configuration has been introduced to
allow a long-running external process to act as a hunk provider to
allows external tools to control which lines Git considers changed
while leaving all output formatting (word diff, color, blame, etc.) to
Git's standard pipeline.
Needs review.
source: <pull.2120.v4.git.1781463564.gitgitgadget@gmail.com>
* tb/pack-path-walk-bitmap-delta-islands (2026-06-02) 5 commits
- pack-objects: support `--delta-islands` with `--path-walk`
- pack-objects: extract `record_tree_depth()` helper
- pack-objects: support reachability bitmaps with `--path-walk`
- t/perf: drop p5311's lookup-table permutation
- Merge branch 'ds/path-walk-filters' into tb/pack-path-walk-bitmap-delta-islands
The pack-objects command now supports using reachability bitmaps and
delta-islands concurrently with the `--path-walk` option, allowing
faster packaging by falling back to path-walk when bitmaps cannot
fully satisfy the request.
Waiting for response(s) to review comment(s).
cf. <849c659f-efa8-430a-bfac-0c26a3ed1aaa@gmail.com>
source: <cover.1780438896.git.me@ttaylorr.com>
* ty/migrate-trust-executable-bit (2026-06-12) 3 commits
- environment: move trust_executable_bit into repo_config_values
- read-cache: move 'ce_mode_from_stat()' to 'read-cache.c'
- read-cache: remove redundant extern declarations
The 'trust_executable_bit' (coming from 'core.filemode'
configuration) has been migrated into 'repo_config_values' to tie it
to a specific repository instance.
Needs review.
source: <20260612160527.167203-1-cat@malon.dev>
* kk/prio-queue-cascade-sift (2026-06-01) 1 commit
- prio-queue: use cascade-down for faster extract-min
prio_queue_get() has been optimized by using a cascade-down approach
(promoting the smaller child at each level and sifting up the last
element from the leaf vacancy), which halves the number of comparisons
per extract-min operation in the common case.
Expecting a reroll.
cf. <CAL71e4Ob-B5MJ5DPY+_tzpj6nyrbQ5WutxED2T93SWJV6kJGPA@mail.gmail.com>
cf. <CAL71e4MYNiScZjTwkApjDAjRh2LM0_SP59h5HCTywV-Pua03tw@mail.gmail.com>
source: <pull.2132.v2.git.1780301856444.gitgitgadget@gmail.com>
* mm/subprocess-handshake-fix (2026-06-01) 1 commit
(merged to 'next' on 2026-06-11 at b649c3a97c)
+ sub-process: use gentle handshake to avoid die() on startup failure
The subprocess handshake during startup has been made gentler by using
packet_read_line_gently() instead of packet_read_line() to prevent the
parent Git process from dying abruptly when a configured subprocess
(e.g., a clean/smudge filter) fails to start.
Will merge to 'master'.
source: <pull.2133.v2.git.1780348848489.gitgitgadget@gmail.com>
* jk/repo-info-path-keys (2026-06-14) 4 commits
- repo: add path.gitdir with absolute and relative suffix formatting
- repo: add path.commondir with absolute and relative suffix formatting
- rev-parse: use append_formatted_path() for path formatting
- path: introduce append_formatted_path() for shared path formatting
The "git repo info" command has been taught new keys to output both
absolute and relative paths for "gitdir" and "commondir", supported by
a new path-formatting helper extracted from "git rev-parse".
Needs review.
source: <20260615045112.50686-1-jayatheerthkulkarni2005@gmail.com>
* ps/history-drop (2026-06-15) 10 commits
- builtin/history: implement "drop" subcommand
- builtin/history: split handling of ref updates into two phases
- reset: stop assuming that the caller passes in a clean index
- reset: allow the caller to specify the current HEAD object
- reset: introduce ability to skip updating HEAD
- reset: introduce dry-run mode
- reset: modernize flags passed to `reset_working_tree()`
- reset: rename `reset_head()`
- reset: drop `USE_THE_REPOSITORY_VARIABLE`
- read-cache: split out function to drop unmerged entries to stage 0
The experimental "git history" command has been taught a new "drop"
subcommand to remove a commit and replay its descendants onto its
parent.
Needs review.
source: <20260615-b4-pks-history-drop-v6-0-2e329e536d78@pks.im>
* jk/setup-gitfile-diag-fix (2026-06-01) 1 commit
- read_gitfile_gently(): return non-repo path on error
A regression in the error diagnosis code for invalid .git files has
been fixed, avoiding a potential NULL-pointer crash when reporting
that a .git file does not point to a valid repository.
Waiting for response(s) to review comment(s).
cf. <xmqqeciezh0w.fsf@gitster.g>
source: <20260602061159.GA693928@coredump.intra.peff.net>
* ps/t7527-fix-tap-output (2026-06-04) 8 commits
(merged to 'next' on 2026-06-11 at b5a4cd26ee)
+ t: let prove fail when parsing invalid TAP output
+ t/lib-git-p4: silence output when killing p4d and its watchdog
+ t/test-lib: silence EBUSY errors on Windows during test cleanup
+ t7810: turn MB_REGEX check into a lazy prereq
+ t7527: fix broken TAP output
+ ci: unify Linux images across GitLab and GitHub
+ gitlab-ci: add missing Linux jobs
+ gitlab-ci: rearrange Linux jobs to match GitHub's order
A recent regression in t7527 that broke TAP output has been fixed,
some other test noise that also broke TAP output has been silenced,
and 'prove' is now configured to fail on invalid TAP output to
prevent future regressions.
Will merge to 'master'.
source: <20260604-pks-t7527-fix-tap-output-v3-0-7d766ed481e4@pks.im>
* kh/doc-trailers (2026-06-10) 10 commits
- doc: interpret-trailers: document comment line treatment
- doc: interpret-trailers: commit to “trailer block” term
- doc: interpret-trailers: join new-trailers again
- doc: interpret-trailers: add key format example
- doc: interpret-trailers: explain key format
- doc: interpret-trailers: explain the format after the intro
- doc: interpret-trailers: not just for commit messages
- doc: interpret-trailers: use “metadata” in Name as well
- doc: interpret-trailers: replace “lines” with “metadata”
- doc: interpret-trailers: stop fixating on RFC 822
Documentation updates.
Waiting for response(s) to review comment(s).
cf. <xmqqcxxyt4op.fsf@gitster.g>
source: <V3_CV_doc_int-tr_key_format.8a3@msgid.xyz>
* za/completion-hide-dotfiles (2026-05-26) 1 commit
- completion: hide dotfiles for selected path completion
The path completion for commands like `git rm` and `git mv`, is being
updated to hide dotfiles by default, unless the user explicitly starts
the path with a dot, matching standard shell-completion behavior.
Waiting for response(s) to review comment(s).
cf. <xmqqik7qusuc.fsf@gitster.g>
source: <pull.2311.v2.git.git.1779808987825.gitgitgadget@gmail.com>
* ec/commit-fixup-options (2026-05-26) 2 commits
- commit: allow -c/-C for all kinds of --fixup
- commit: allow -m/-F for all kinds of --fixup
The -m/-F/-c/-C options to supply commit log message from outside the
editor are now supported for all "git commit --fixup" variations.
Needs review.
source: <cover.1779792311.git.erik@cervined.in>
* kh/doc-replay-config (2026-06-05) 4 commits
- doc: replay: move “default” to the right-hand side
- doc: replay: use a nested description list
- doc: replay: improve config description
- doc: link to config for git-replay(1)
Doc update for "git replay" to actually refer to its configuration
variables.
Needs review.
source: <V3_CV_doc_replay_config.780@msgid.xyz>
* hn/status-pull-advice-qualified (2026-05-21) 1 commit
(merged to 'next' on 2026-06-15 at 898a4df940)
+ remote: qualify "git pull" advice for non-upstream compareBranches
Advice shown by "git status" when the local branch is behind or has
diverged from its push branch has been updated to suggest "git pull
<remote> <branch>".
Will merge to 'master'.
cf. <xmqq7bo6xuok.fsf@gitster.g>
source: <pull.2301.v4.git.git.1779372367317.gitgitgadget@gmail.com>
* jt/config-lock-timeout (2026-05-17) 1 commit
- config: retry acquiring config.lock, configurable via core.configLockTimeout
Configuration file locking now retries for a short period, avoiding
failures when multiple processes attempt to update the configuration
simultaneously.
Waiting for response(s) to review comment(s).
cf. <agrIrGwSMFlKTx9x@pks.im>
source: <20260517132111.1014901-1-joerg@thalheim.io>
* hn/branch-prune-merged (2026-06-15) 7 commits
- branch: add --dry-run for --delete-merged
- branch: add branch.<name>.deleteMerged opt-out
- branch: add --delete-merged <branch>
- branch: prepare delete_branches for a bulk caller
- branch: let delete_branches skip unmerged branches on bulk refusal
- branch: convert delete_branches() to a flags argument
- branch: add --forked filter for --list mode
"git branch" command learned "--prune-merged" option to remove
local branches that have already been merged to the remote-tracking
branches they track.
Needs review.
source: <pull.2285.v15.git.git.1781542042.gitgitgadget@gmail.com>
* cc/promisor-auto-config-url-more (2026-05-27) 8 commits
(merged to 'next' on 2026-06-15 at d1c99e75cc)
+ doc: promisor: improve acceptFromServer entry
+ promisor-remote: auto-configure unknown remotes
+ promisor-remote: trust known remotes matching acceptFromServerUrl
+ promisor-remote: introduce promisor.acceptFromServerUrl
+ promisor-remote: add 'local_name' to 'struct promisor_info'
+ urlmatch: add url_normalize_pattern() helper
+ urlmatch: change 'allow_globs' arg to bool
+ t5710: simplify 'mkdir X' followed by 'git -C X init'
The handling of promisor-remote protocol capability has been
loosened to allow the other side to add to the list of promisor
remotes via the promisor.acceptFromServerURL configuration
variable.
Will merge to 'master'.
cf. <877bo7294j.fsf@emacs.iotcl.com>
cf. <xmqqh5naxwfc.fsf@gitster.g>
source: <20260527140820.1438165-1-christian.couder@gmail.com>
* hn/checkout-track-fetch (2026-05-23) 2 commits
- checkout: extend --track with a "fetch" mode to refresh start-point
- branch: expose helpers for finding the remote owning a tracking ref
"git checkout --track=..." learned to optionally fetch the branch
from the remote the new branch will work with.
Needs review.
source: <pull.2281.v13.git.git.1779565714.gitgitgadget@gmail.com>
* mf/revision-max-count-oldest (2026-06-10) 2 commits
(merged to 'next' on 2026-06-11 at c89a71798a)
+ bash-completions: add --max-count-oldest
(merged to 'next' on 2026-06-09 at 076600fa21)
+ revision.c: implement --max-count-oldest
"git rev-list" (and "git log" family of commands) learned a new "--max-count-oldest"
that picks oldest N commits in the range instead of the usual newest.
Will merge to 'master'.
source: <xmqq4ijm3p2x.fsf@gitster.g>
* en/ort-harden-against-corrupt-trees (2026-06-13) 5 commits
- cache-tree: fix verify_cache() to catch non-adjacent D/F conflicts
- merge-ort: abort merge when trees have duplicate entries
- merge-ort: free diff pairs queue in clear_or_reinit_internal_opts()
- merge-ort: drop unnecessary show_all_errors from collect_merge_info()
- merge-ort: propagate callback errors from traverse_trees_wrapper()
"ort" merge backend handles merging corrupt trees better by
aborting when it should.
Waiting for response(s) to review comment(s).
cf. <xmqq5x3ldu4h.fsf@gitster.g>
source: <pull.2096.v2.git.1781419047.gitgitgadget@gmail.com>
* pw/status-rebase-todo (2026-05-01) 2 commits
- status: improve rebase todo list parsing
- sequencer: factor out parsing of todo commands
The display of the rebase todo list in "git status" has been
improved to correctly abbreviate object IDs for more commands and
avoid misinterpreting refs as object IDs.
Waiting for response(s) to review comment(s).
cf. <xmqqqzmdoya9.fsf@gitster.g>
source: <cover.1777648598.git.phillip.wood@dunelm.org.uk>
* cl/conditional-config-on-worktree-path (2026-05-24) 2 commits
- config: add "worktree" and "worktree/i" includeIf conditions
- config: refactor include_by_gitdir() into include_by_path()
The [includeIf "condition"] conditional inclusion facility for
configuration files has learned to use the location of worktree
in its condition.
Waiting for response(s) to review comment(s).
cf. <xmqq8q97et9b.fsf@gitster.g>
source: <20260525-includeif-worktree-v5-0-1efe525d025a@black-desk.cn>
* ps/shift-root-in-graph (2026-06-13) 2 commits
- graph: indent visual root in graph
- lib-log-graph: move check_graph function
"git log --graph" has been modified to visually distinguish
parentless "root" commits (and commits that become roots due to
history simplification) by indenting them, preventing them from
appearing falsely related to unrelated commits rendered immediately
above them.
Waiting for response(s) to review comment(s).
cf. <xmqqo6hdepgy.fsf@gitster.g>
source: <20260613-ps-pre-commit-indent-v5-0-8d308efea63d@gmail.com>
--------------------------------------------------
[Discarded]
* kk/fetch-store-ref-optimization (2026-05-24) 1 commit
- fetch: pass transport to post-fetch connectivity check
When fetching from a transport that provides a self-contained pack,
pass the transport pointer to the post-fetch `check_connected()` call
to optimize connectivity check.
Retracted.
cf. <CAL71e4MrVqC1=AR6x0_8S=8kVqPdDkhgCZRb4etFsxTzd6s_8Q@mail.gmail.com>
source: <pull.2123.git.1779625693328.gitgitgadget@gmail.com>
* lp/repack-propagate-promisor-debugging-info (2026-04-18) 6 commits
- repack-promisor: add missing headers
- t7703: test for promisor file content after geometric repack
- t7700: test for promisor file content after repack
- repack-promisor: preserve content of promisor files after repack
- repack-promisor add helper to fill promisor file after repack
- pack-write: add explanation to promisor file content
When fetching objects into a lazily cloned repository, .promisor
files are created with information meant to help debugging. "git
repack" has been taught to carry this information forward to
packfiles that are newly created.
Retracted.
cf. <agx_GPfBKpkSc3Gx@lorenzo-VM>
source: <cover.1776384902.git.lorenzo.pegorari2002@gmail.com>
* cs/subtree-split-recursion (2026-03-05) 3 commits
. contrib/subtree: reduce recursion during split
. contrib/subtree: functionalize split traversal
. contrib/subtree: reduce function side-effects
When processing large history graphs on Debian or Ubuntu, "git
subtree" can die with a "recursion depth reached" error.
Retracted.
cf. <0915b5cc-5cbb-4cce-a832-147f85d4ff1f@howdoi.land>
source: <20260305-cs-subtree-split-recursion-v2-0-7266be870ba9@howdoi.land>
* jc/neuter-sideband-post-3.0 (2026-03-05) 2 commits
. sideband: delay sanitizing by default to Git v3.0
. Merge branch 'jc/neuter-sideband-fixup' into jc/neuter-sideband-post-3.0
The final step, split from earlier attempt by Dscho, to loosen the
sideband restriction for now and tighten later at Git v3.0 boundary.
Retracted.
cf. <xmqqzf11oz7a.fsf@gitster.g>
source: <20260305233452.3727126-8-gitster@pobox.com>
^ permalink raw reply
* Re: [PATCH] doc: fix a small, old release notes typo
From: D. Ben Knoble @ 2026-06-15 19:10 UTC (permalink / raw)
To: Jeff King; +Cc: git, Elijah Newren
In-Reply-To: <20260615171416.GC91269@coredump.intra.peff.net>
On Mon, Jun 15, 2026 at 1:14 PM Jeff King <peff@peff.net> wrote:
>
> On Sun, Jun 14, 2026 at 01:28:31PM -0400, D. Ben Knoble wrote:
>
> > No harm done if you choose not to keep this, I think. Stumbled upon it when
> > trying to understand Elijah's message [1] about timestamp_t overflowing in 2106
> > (I though 32-bit time_t overflowed in 2038, but timestamp_t is something
> > different… except maybe when it's not? Anyway…)
>
> Leaving aside the patch for a moment, the answer to your timestamp
> question is: signed 32-bit takes us to 2038 (and back to 1902), but
> unsigned goes to 2106 (but only back to 1970).
>
> Usually time_t is signed, but our timestamp_t is not, mostly for
> historical reasons. And timestamp_t itself is our local invention
> because we have no control over the definition of time_t (but we still
> end up needing it to call system date functions).
Doh, that's the difference I missed. Thanks!
> I have some patches to allow negative timestamps, but I ran into
> portability issues. IIRC, Windows gmtime() chokes on negative
> timestamps.
>
> It hasn't been a big deal in practice since new commits made today will
> always have a positive epoch. But negative timestamps would allow
> importing some historical projects (like Apollo mission code), as well
> as weird (ab)uses of Git to store historical documents (like legal code
> going back centuries).
>
> -Peff
Reminded me of https://williamzujkowski.github.io/posts/2026-04-02-building-us-code-tracker-law-as-git-history/
Thanks again,
Ben
^ permalink raw reply
* [PATCH] rebase: mention --abort alongside --continue
From: Harald Nordgren via GitGitGadget @ 2026-06-15 19:19 UTC (permalink / raw)
To: git; +Cc: Harald Nordgren, Harald Nordgren
From: Harald Nordgren <haraldnordgren@gmail.com>
The warning shown when an "exec" step fails and the "git status"
advice while splitting or editing a commit pointed users at "git
rebase --continue" but not "--abort". Mention it in both, matching
the conflict case.
Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
---
rebase: mention --abort when an exec step fails
Mention git rebase --abort both in the warning shown when an exec step
fails and in the git status advice while splitting or editing a commit,
since rebase pointed users at --continue there without saying how to
bail out, unlike every comparable command.
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2330%2FHaraldNordgren%2Frebase-exec-abort-hint-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2330/HaraldNordgren/rebase-exec-abort-hint-v1
Pull-Request: https://github.com/git/git/pull/2330
sequencer.c | 8 ++++++--
t/t7512-status-help.sh | 17 +++++++++++++++++
wt-status.c | 7 ++++++-
3 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/sequencer.c b/sequencer.c
index 57855b0066..c46e5b95bc 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -3884,7 +3884,9 @@ static int do_exec(struct repository *r, const char *command_line, int quiet)
"You can fix the problem, and then run\n"
"\n"
" git rebase --continue\n"
- "\n"),
+ "\n"
+ "To abort and get back to the state before \"git rebase\", run "
+ "\"git rebase --abort\".\n"),
command_line,
dirty ? _("and made changes to the index and/or the "
"working tree.\n") : "");
@@ -3897,7 +3899,9 @@ static int do_exec(struct repository *r, const char *command_line, int quiet)
"Commit or stash your changes, and then run\n"
"\n"
" git rebase --continue\n"
- "\n"), command_line);
+ "\n"
+ "To abort and get back to the state before \"git rebase\", run "
+ "\"git rebase --abort\".\n"), command_line);
status = 1;
}
diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index 08e82f7914..ca7ef66ae3 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -206,6 +206,7 @@ No commands remaining.
You are currently editing a commit while rebasing branch '\''rebase_i_edit'\'' on '\''$ONTO'\''.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
+ (use "git rebase --abort" to check out the original branch)
nothing to commit (use -u to show untracked files)
EOF
@@ -240,6 +241,7 @@ Next command to do (1 remaining command):
(use "git rebase --edit-todo" to view and edit)
You are currently splitting a commit while rebasing branch '\''split_commit'\'' on '\''$ONTO'\''.
(Once your working directory is clean, run "git rebase --continue")
+ (use "git rebase --abort" to check out the original branch)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
@@ -278,6 +280,7 @@ No commands remaining.
You are currently editing a commit while rebasing branch '\''amend_last'\'' on '\''$ONTO'\''.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
+ (use "git rebase --abort" to check out the original branch)
nothing to commit (use -u to show untracked files)
EOF
@@ -317,6 +320,7 @@ Next command to do (1 remaining command):
You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
+ (use "git rebase --abort" to check out the original branch)
nothing to commit (use -u to show untracked files)
EOF
@@ -347,6 +351,7 @@ Next command to do (1 remaining command):
(use "git rebase --edit-todo" to view and edit)
You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
(Once your working directory is clean, run "git rebase --continue")
+ (use "git rebase --abort" to check out the original branch)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
@@ -383,6 +388,7 @@ Next command to do (1 remaining command):
You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
+ (use "git rebase --abort" to check out the original branch)
nothing to commit (use -u to show untracked files)
EOF
@@ -414,6 +420,7 @@ Next command to do (1 remaining command):
You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
+ (use "git rebase --abort" to check out the original branch)
nothing to commit (use -u to show untracked files)
EOF
@@ -445,6 +452,7 @@ Next command to do (1 remaining command):
(use "git rebase --edit-todo" to view and edit)
You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
(Once your working directory is clean, run "git rebase --continue")
+ (use "git rebase --abort" to check out the original branch)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
@@ -482,6 +490,7 @@ Next command to do (1 remaining command):
You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
+ (use "git rebase --abort" to check out the original branch)
nothing to commit (use -u to show untracked files)
EOF
@@ -515,6 +524,7 @@ Next command to do (1 remaining command):
You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
+ (use "git rebase --abort" to check out the original branch)
nothing to commit (use -u to show untracked files)
EOF
@@ -548,6 +558,7 @@ Next command to do (1 remaining command):
(use "git rebase --edit-todo" to view and edit)
You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
(Once your working directory is clean, run "git rebase --continue")
+ (use "git rebase --abort" to check out the original branch)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
@@ -587,6 +598,7 @@ Next command to do (1 remaining command):
You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
+ (use "git rebase --abort" to check out the original branch)
nothing to commit (use -u to show untracked files)
EOF
@@ -718,6 +730,7 @@ No commands remaining.
You are currently editing a commit while rebasing branch '\''bisect'\'' on '\''$ONTO'\''.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
+ (use "git rebase --abort" to check out the original branch)
You are currently bisecting, started from branch '\''bisect_while_rebasing'\''.
(use "git bisect reset" to get back to the original branch)
@@ -987,6 +1000,7 @@ No commands remaining.
You are currently editing a commit while rebasing branch '\''several_commits'\'' on '\''$ONTO'\''.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
+ (use "git rebase --abort" to check out the original branch)
nothing to commit (use -u to show untracked files)
EOF
@@ -1015,6 +1029,7 @@ Next commands to do (2 remaining commands):
You are currently editing a commit while rebasing branch '\''several_commits'\'' on '\''$ONTO'\''.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
+ (use "git rebase --abort" to check out the original branch)
nothing to commit (use -u to show untracked files)
EOF
@@ -1044,6 +1059,7 @@ Next commands to do (2 remaining commands):
You are currently editing a commit while rebasing branch '\''several_commits'\'' on '\''$ONTO'\''.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
+ (use "git rebase --abort" to check out the original branch)
nothing to commit (use -u to show untracked files)
EOF
@@ -1064,6 +1080,7 @@ Next command to do (1 remaining command):
You are currently editing a commit while rebasing branch '\''several_commits'\'' on '\''$ONTO'\''.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
+ (use "git rebase --abort" to check out the original branch)
nothing to commit (use -u to show untracked files)
EOF
diff --git a/wt-status.c b/wt-status.c
index b17372390c..94fd14a058 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1527,9 +1527,12 @@ static void show_rebase_in_progress(struct wt_status *s,
else
status_printf_ln(s, color,
_("You are currently splitting a commit during a rebase."));
- if (s->hints)
+ if (s->hints) {
status_printf_ln(s, color,
_(" (Once your working directory is clean, run \"git rebase --continue\")"));
+ status_printf_ln(s, color,
+ _(" (use \"git rebase --abort\" to check out the original branch)"));
+ }
} else {
if (s->state.branch)
status_printf_ln(s, color,
@@ -1544,6 +1547,8 @@ static void show_rebase_in_progress(struct wt_status *s,
_(" (use \"git commit --amend\" to amend the current commit)"));
status_printf_ln(s, color,
_(" (use \"git rebase --continue\" once you are satisfied with your changes)"));
+ status_printf_ln(s, color,
+ _(" (use \"git rebase --abort\" to check out the original branch)"));
}
}
wt_longstatus_print_trailer(s);
base-commit: ea97ad8d017de0c9037451a78008a0fd60abea0c
--
gitgitgadget
^ permalink raw reply related
* Re: [PATCH 0/2] Silence po catalog output under "make -s"
From: Harald Nordgren @ 2026-06-15 19:25 UTC (permalink / raw)
To: Harald Nordgren via GitGitGadget; +Cc: git
In-Reply-To: <pull.2339.git.git.1781459539.gitgitgadget@gmail.com>
It's this output that currently is not silent:
$ make -s
...
579 translated messages.
558 translated messages.
514 translated messages.
381 translated messages, 4 fuzzy translations, 6 untranslated messages.
520 translated messages.
519 translated messages, 1 untranslated message.
546 translated messages, 1 untranslated message.
474 translated messages, 39 untranslated messages.
520 translated messages.
550 translated messages.
579 translated messages.
576 translated messages.
366 translated messages, 7 fuzzy translations, 17 untranslated messages.
543 translated messages.
Generating catalog po/bg.msg
322 translated messages.
Generating catalog po/ca.msg
307 translated messages.
Generating catalog po/de.msg
307 translated messages.
Generating catalog po/es.msg
184 translated messages, 46 fuzzy translations, 77 untranslated messages.
Generating catalog po/fr.msg
311 translated messages.
Generating catalog po/hu.msg
277 translated messages, 18 fuzzy translations, 12 untranslated messages.
Generating catalog po/it.msg
274 translated messages, 17 fuzzy translations, 16 untranslated messages.
Generating catalog po/ja.msg
311 translated messages.
Generating catalog po/pt_br.msg
279 translated messages, 16 fuzzy translations, 12 untranslated messages.
Generating catalog po/pt_pt.msg
311 translated messages.
Generating catalog po/ru.msg
317 translated messages.
Generating catalog po/sv.msg
323 translated messages.
Generating catalog po/ta.msg
Generating catalog po/vi.msg
327 translated messages.
Generating catalog po/zh_cn.msg
307 translated messages.
GEN gitk-wish
317 translated messages.
On Sun, Jun 14, 2026 at 7:52 PM Harald Nordgren via GitGitGadget
<gitgitgadget@gmail.com> wrote:
>
> The gitk and git-gui catalog rules sent msgfmt --statistics output (and a
> "Generating catalog" line) to stderr, so it survived "make -s". Emit it only
> when "-s" is absent, keeping a quiet build silent and a verbose build
> unchanged.
>
> Harald Nordgren (2):
> gitk: silence catalog output under "make -s"
> git-gui: silence statistics under "make -s"
>
> git-gui/Makefile | 3 ++-
> gitk-git/Makefile | 10 ++++++++--
> 2 files changed, 10 insertions(+), 3 deletions(-)
>
>
> base-commit: ea97ad8d017de0c9037451a78008a0fd60abea0c
> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2339%2FHaraldNordgren%2Fsilence-catalog-output-under-make-s-v1
> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2339/HaraldNordgren/silence-catalog-output-under-make-s-v1
> Pull-Request: https://github.com/git/git/pull/2339
> --
> gitgitgadget
^ permalink raw reply
* Re: [PATCH v4] ref-filter: restore prefix-scoped iteration
From: Tamir Duberstein @ 2026-06-15 20:47 UTC (permalink / raw)
To: git
Cc: Karthik Nayak, Patrick Steinhardt, Junio C Hamano, Victoria Dye,
ZheNing Hu
In-Reply-To: <20260612-fix-git-branch-regression-v4-1-f150038c02f4@gmail.com>
On Fri, Jun 12, 2026 at 5:27 PM Tamir Duberstein <tamird@gmail.com> wrote:
>
> dabecb9db2 (for-each-ref: introduce a '--start-after' option,
> 2025-07-15) changed branch, remote-tracking branch, and tag enumeration
> from constructing an iterator with the namespace prefix to constructing
> an unscoped iterator and seeking to the prefix.
>
> Review of --start-after noted that the construction prefix and seek
> position represent different state and are easy to conflate [1]. It also
> noted that future branch or tag support would need to retain the
> namespace prefix while moving the cursor [2].
>
> The files backend constructs its loose-ref iterator with cache priming
> enabled. cache_ref_iterator_begin() immediately applies the construction
> prefix through cache_ref_iterator_set_prefix(), reading loose refs
> beneath it before packed refs are opened. An empty prefix therefore
> reads every loose ref, and a later seek cannot undo that I/O.
>
> For the current single-kind filters, construct the iterator with the
> namespace prefix when start_after is not set. Leave the existing
> start_after path unchanged; no current command combines it with these
> filters, and future support must carry the prefix separately from the
> cursor.
>
> With 10,000 unrelated loose refs in the files backend, the p6300 tests
> improve as follows:
>
> before after
> branch 2.74 s 0.11 s
> branch --remotes 2.81 s 0.12 s
> tag 3.01 s 0.11 s
>
> [1] https://lore.kernel.org/r/aGZidwwlToWThkn8@pks.im/
> [2] https://lore.kernel.org/r/xmqqikjq7s16.fsf@gitster.g/
>
> Fixes: dabecb9db2b2 ("for-each-ref: introduce a '--start-after' option")
> Suggested-by: Karthik Nayak <karthik.188@gmail.com>
> Signed-off-by: Tamir Duberstein <tamird@gmail.com>
> ---
> The series is based on a89346e34a (maint) because the regression has
> been present in released versions since Git 2.51.0.
> ---
> Changes in v4:
> - Explain the historical references in the commit message.
> - Run the new performance cases with both ref backends.
> - Drop the Assisted-by trailer.
> - Link to v3: https://patch.msgid.link/20260610-fix-git-branch-regression-v3-1-6fd48fad7a53@gmail.com
>
> Changes in v3:
> - Construct the iterator directly with the namespace prefix.
> - Explain when the files backend primes its loose-ref cache.
> - Condense the commit message and performance results.
> - Link to v2: https://patch.msgid.link/20260608-fix-git-branch-regression-v2-1-fd82075a8520@gmail.com
>
> Changes in v2:
> - Extract local variable `store`.
> - Link to v1: https://patch.msgid.link/20260605-fix-git-branch-regression-v1-1-02f40ad40929@gmail.com
> ---
Hi folks, does this look reasonable?
^ permalink raw reply
* Re: [PATCH v2 2/4] pack-objects: support reachability bitmaps with `--path-walk`
From: Junio C Hamano @ 2026-06-15 20:57 UTC (permalink / raw)
To: Taylor Blau
Cc: git, Michael Montalbo, Derrick Stolee, Jeff King, Elijah Newren
In-Reply-To: <ffad584a43ebf3cb2138e8dce7daef84ab72712f.1780438896.git.me@ttaylorr.com>
Taylor Blau <me@ttaylorr.com> writes:
> 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
> ...
> + 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 &&
This gets flagged by updated test linter X-<. Use test_grep to
pacify it.
^ permalink raw reply
* Re: [PATCH v2] commit-reach: remove get_reachable_subset()
From: Kristofer Karlsson @ 2026-06-15 20:58 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Derrick Stolee, Kristofer Karlsson via GitGitGadget, git
In-Reply-To: <xmqq7bo5nf31.fsf@gitster.g>
I think we should park or abandon this patch for now; I initially thought
it would be a somewhat cheap win in code reduction but the risk of
introducing performance regressions for repos without commit graphs
means it's not really worth the time investment and I don't want to
add more maintainer burden for tracking it.
Thanks for looking at it though, I appreciate it!
Kristofer
On Thu, 11 Jun 2026 at 19:48, Junio C Hamano <gitster@pobox.com> wrote:
>
> Derrick Stolee <stolee@gmail.com> writes:
>
> > Finally, a commentary: You seem to have a habit of responding to
> > review feedback only through new patch versions, but I'd rather see
> > some thoughts in the discussion thread as direct replies to the review,
> > especially if you think you will change direction like this. Saying
> > something like "Maybe I should update the method to have two walk modes"
> > in a reply would have given me an opportunity to respond and perhaps
> > avoided a new version that went in this direction.
>
> Thanks for saying this.
>
> I haven't (yet) found it in my exchange with Kristofer, but I did
> find similar irritations during review sessions with other
> contributors.
>
> I wonder if we should talk about it in the SubmittingPatches and/or
> MyFirstContribution document?
^ permalink raw reply
* Re: [PREVIEW v4 0/6] [RFC] diff: add diff.<driver>.process for external hunk providers
From: Michael Montalbo @ 2026-06-15 21:14 UTC (permalink / raw)
To: Michael Montalbo via GitGitGadget; +Cc: git, Johannes Schindelin
In-Reply-To: <pull.2120.v4.git.1781463332.gitgitgadget@gmail.com>
On Sun, Jun 14, 2026 at 11:55 AM Michael Montalbo via GitGitGadget
<gitgitgadget@gmail.com> wrote:
>
> This series adds diff.<driver>.process, a long-running subprocess protocol
> that lets an external tool control which lines Git considers changed while
> Git handles all output formatting...
Now I'm realizing there are some diff flags that are not properly supported
yet with an external diff provider. Flags like -L and the stat-related
flags should probably behave like blame and consult the external diff
process. In general, there should be a more explicit and comprehensive
explanation for which flags interact with external diff processes and
which do not, included principled reasons for why that is the case.
^ permalink raw reply
* Re: [PATCH] cat-file: speed up default format
From: René Scharfe @ 2026-06-15 21:53 UTC (permalink / raw)
To: Jeff King; +Cc: Git List
In-Reply-To: <20260615165326.GA91269@coredump.intra.peff.net>
On 6/15/26 6:53 PM, Jeff King wrote:
>
> +static void rest_add(struct format_item *item UNUSED,
> + struct strbuf *sb, struct expand_data *data)
> +{
> + strbuf_addstr(sb, data->rest);
> +}
> } else if (is_atom("rest", atom, len)) {
> - if (data->mark_query)
> - data->split_on_whitespace = 1;
> - else if (data->rest)
This removes support for rest being NULL, breaking t1006.381.
> - strbuf_addstr(sb, data->rest);
> + data->split_on_whitespace = 1;
> + fmt->add = rest_add;
René
^ permalink raw reply
* Re: [PATCH] cat-file: speed up default format
From: René Scharfe @ 2026-06-15 21:53 UTC (permalink / raw)
To: Jeff King; +Cc: Git List
In-Reply-To: <20260615170652.GB91269@coredump.intra.peff.net>
On 6/15/26 7:06 PM, Jeff King wrote:
> On Mon, Jun 15, 2026 at 12:53:26PM -0400, Jeff King wrote:
>
>> It uses per-atom callback functions which is nice and clean, though we
>> might be able to do even better with a big ugly switch() statement.
>
> Being the curious sort, I swapped it out for a big switch statement.
> Patch below, but it does not seem to be any faster.
>
> So the bottom line is I think you could gain a little bit of performance
> by pre-parsing (versus strbuf_expand() on each object). Around 3% for
> something that actually looks at the objects, though more like 15% if
> for just dumping the objectnames.
>
> IMHO that is probably not worth it for a custom parsing system just for
> cat-file. But if we were to finally unify ref-filter and cat-file (and
> even --pretty=format) then it would probably worth doing this kind of
> pre-parsing.
It could be worth it for cat-file alone if we find the right balance, as
it already does do a separate parsing step, but that is awkward with its
mark_query checks all over the place and remembers only object property
requirements and no other format string details.
Making the opcodes small should be beneficial. We need only a handful
of them, so a byte each should suffice. We can use a strbuf for that.
We can also store literal characters in there. An opcode plus with a
payload char incurs an overhead of 50%, which sounds high, but at least
the default format only has two of them and it's much better than
storing pointer plus size for an overhead of more than 90% in case of a
single char.
That gets us closer to native speed, at least on an Apple M1:
Benchmark 1: ./git_fp cat-file --batch-all-objects --batch-check='%(objectname)-%(objecttype)-%(objectsize)'
Time (mean ± σ): 992.7 ms ± 3.2 ms [User: 967.5 ms, System: 23.8 ms]
Range (min … max): 990.1 ms … 1000.7 ms 10 runs
Benchmark 2: ./git_switch cat-file --batch-all-objects --batch-check='%(objectname)-%(objecttype)-%(objectsize)'
Time (mean ± σ): 991.8 ms ± 1.6 ms [User: 967.0 ms, System: 23.3 ms]
Range (min … max): 989.3 ms … 994.4 ms 10 runs
Benchmark 3: ./git cat-file --batch-all-objects --batch-check='%(objectname)-%(objecttype)-%(objectsize)'
Time (mean ± σ): 985.8 ms ± 2.9 ms [User: 960.5 ms, System: 23.6 ms]
Range (min … max): 982.9 ms … 993.0 ms 10 runs
Benchmark 4: ./git cat-file --batch-all-objects --batch-check='%(objectname) %(objecttype) %(objectsize)'
Time (mean ± σ): 982.1 ms ± 3.2 ms [User: 956.7 ms, System: 23.6 ms]
Range (min … max): 979.2 ms … 989.2 ms 10 runs
Summary
./git cat-file --batch-all-objects --batch-check='%(objectname) %(objecttype) %(objectsize)' ran
1.00 ± 0.00 times faster than ./git cat-file --batch-all-objects --batch-check='%(objectname)-%(objecttype)-%(objectsize)'
1.01 ± 0.00 times faster than ./git_switch cat-file --batch-all-objects --batch-check='%(objectname)-%(objecttype)-%(objectsize)'
1.01 ± 0.00 times faster than ./git_fp cat-file --batch-all-objects --batch-check='%(objectname)-%(objecttype)-%(objectsize)'
A Ryzen laptop gives me noisy numbers that seem to suggest your
switch-based code already won, but the more compact representation is at
least not worse:
Benchmark 1: ./git_fp cat-file --batch-all-objects --batch-check='%(objectname)-%(objecttype)-%(objectsize)'
Time (mean ± σ): 397.5 ms ± 8.0 ms [User: 326.9 ms, System: 39.4 ms]
Range (min … max): 388.1 ms … 410.0 ms 10 runs
Benchmark 2: ./git_switch cat-file --batch-all-objects --batch-check='%(objectname)-%(objecttype)-%(objectsize)'
Time (mean ± σ): 388.2 ms ± 4.2 ms [User: 318.2 ms, System: 39.2 ms]
Range (min … max): 382.8 ms … 395.7 ms 10 runs
Benchmark 3: ./git cat-file --batch-all-objects --batch-check='%(objectname)-%(objecttype)-%(objectsize)'
Time (mean ± σ): 385.5 ms ± 5.7 ms [User: 311.2 ms, System: 43.2 ms]
Range (min … max): 377.0 ms … 392.9 ms 10 runs
Benchmark 4: ./git cat-file --batch-all-objects --batch-check='%(objectname) %(objecttype) %(objectsize)'
Time (mean ± σ): 397.5 ms ± 8.4 ms [User: 321.9 ms, System: 45.2 ms]
Range (min … max): 382.1 ms … 406.5 ms 10 runs
Summary
./git cat-file --batch-all-objects --batch-check='%(objectname)-%(objecttype)-%(objectsize)' ran
1.01 ± 0.02 times faster than ./git_switch cat-file --batch-all-objects --batch-check='%(objectname)-%(objecttype)-%(objectsize)'
1.03 ± 0.03 times faster than ./git_fp cat-file --batch-all-objects --batch-check='%(objectname)-%(objecttype)-%(objectsize)'
1.03 ± 0.03 times faster than ./git cat-file --batch-all-objects --batch-check='%(objectname) %(objecttype) %(objectsize)'
René
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 0d1998784c..5667a13e93 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -36,8 +36,6 @@ enum batch_mode {
BATCH_MODE_QUEUE_AND_DISPATCH,
};
-struct format_item;
-
struct batch_options {
struct list_objects_filter_options objects_filter;
int enabled;
@@ -50,7 +48,7 @@ struct batch_options {
char input_delim;
char output_delim;
const char *format;
- struct format_item *parsed_format;
+ struct strbuf parsed_format;
};
static const char *force_path;
@@ -320,30 +318,16 @@ struct expand_data {
};
#define EXPAND_DATA_INIT { .mode = S_IFINVALID }
-struct format_item {
- enum {
- FORMAT_TYPE_END = 0,
- FORMAT_TYPE_LITERAL,
- FORMAT_TYPE_OBJECTNAME,
- FORMAT_TYPE_OBJECTTYPE,
- FORMAT_TYPE_OBJECTSIZE,
- FORMAT_TYPE_OBJECTSIZE_DISK,
- FORMAT_TYPE_REST,
- FORMAT_TYPE_DELTABASE,
- FORMAT_TYPE_OBJECTMODE,
- } type;
- union {
- struct {
- const char *p;
- size_t len;
- } literal;
- } u;
- /*
- * We could make a true tree here with child/next pointers, which would
- * be necessary if we had recursive formats, like %(if). But for our
- * simple formats for now it is enough to have a linear set of items,
- * so we'll just allocate an array and terminate it with a NULL entry.
- */
+
+enum item_type {
+ FORMAT_TYPE_LITERAL,
+ FORMAT_TYPE_OBJECTNAME,
+ FORMAT_TYPE_OBJECTTYPE,
+ FORMAT_TYPE_OBJECTSIZE,
+ FORMAT_TYPE_OBJECTSIZE_DISK,
+ FORMAT_TYPE_REST,
+ FORMAT_TYPE_DELTABASE,
+ FORMAT_TYPE_OBJECTMODE,
};
static int is_atom(const char *atom, const char *s, int slen)
@@ -352,84 +336,66 @@ static int is_atom(const char *atom, const char *s, int slen)
return alen == slen && !memcmp(atom, s, alen);
}
-static int parse_atom(struct format_item *fmt, const char *atom, int len,
+static int parse_atom(struct strbuf *parsed_format, const char *atom, int len,
struct expand_data *data)
{
if (is_atom("objectname", atom, len)) {
- fmt->type = FORMAT_TYPE_OBJECTNAME;
+ strbuf_addch(parsed_format, FORMAT_TYPE_OBJECTNAME);
} else if (is_atom("objecttype", atom, len)) {
data->info.typep = &data->type;
- fmt->type = FORMAT_TYPE_OBJECTTYPE;
+ strbuf_addch(parsed_format, FORMAT_TYPE_OBJECTTYPE);
} else if (is_atom("objectsize", atom, len)) {
data->info.sizep = &data->size;
- fmt->type = FORMAT_TYPE_OBJECTSIZE;
+ strbuf_addch(parsed_format, FORMAT_TYPE_OBJECTSIZE);
} else if (is_atom("objectsize:disk", atom, len)) {
data->info.disk_sizep = &data->disk_size;
- fmt->type = FORMAT_TYPE_OBJECTSIZE_DISK;
+ strbuf_addch(parsed_format, FORMAT_TYPE_OBJECTSIZE_DISK);
} else if (is_atom("rest", atom, len)) {
data->split_on_whitespace = 1;
- fmt->type = FORMAT_TYPE_REST;
+ strbuf_addch(parsed_format, FORMAT_TYPE_REST);
} else if (is_atom("deltabase", atom, len)) {
data->info.delta_base_oid = &data->delta_base_oid;
- fmt->type = FORMAT_TYPE_DELTABASE;
+ strbuf_addch(parsed_format, FORMAT_TYPE_DELTABASE);
} else if (is_atom("objectmode", atom, len)) {
- fmt->type = FORMAT_TYPE_OBJECTMODE;
+ strbuf_addch(parsed_format, FORMAT_TYPE_OBJECTMODE);
} else
return 0;
return 1;
}
-static struct format_item *parse_format(const char *start,
- struct expand_data *data)
+static void parse_format(struct strbuf *parsed_format,
+ const char *start, struct expand_data *data)
{
- struct format_item *ret = NULL;
- size_t nr = 0, alloc = 0;
-
while (1) {
- const char *percent = strchrnul(start, '%');
const char *end;
- if (percent != start) {
- ALLOC_GROW(ret, nr + 1, alloc);
- ret[nr].type = FORMAT_TYPE_LITERAL;
- ret[nr].u.literal.p = start;
- ret[nr].u.literal.len = percent - start;
- nr++;
+ while (*start && *start != '%') {
+ strbuf_addch(parsed_format, FORMAT_TYPE_LITERAL);
+ strbuf_addch(parsed_format, *start++);
}
- if (!*percent)
+ if (!*start)
break;
- start = percent + 1;
+ start++;
- ALLOC_GROW(ret, nr + 1, alloc);
if (skip_prefix(start, "%", &start) || *start != '(') {
- ret[nr].type = FORMAT_TYPE_LITERAL;
- ret[nr].u.literal.p = "%";
- ret[nr].u.literal.len = 1;
+ strbuf_addch(parsed_format, FORMAT_TYPE_LITERAL);
+ strbuf_addch(parsed_format, '%');
} else if ((end = strchr(start + 1, ')')) &&
- parse_atom(&ret[nr], start + 1, end - start - 1, data)) {
+ parse_atom(parsed_format, start + 1, end - start - 1, data)) {
start = end + 1;
} else {
strbuf_expand_bad_format(start, "cat-file");
}
- nr++;
}
-
- ALLOC_GROW(ret, nr + 1, alloc);
- ret[nr].type = FORMAT_TYPE_END;
-
- return ret;
}
-static void expand_format(struct strbuf *sb, struct format_item *fmt,
+static void expand_format(struct strbuf *sb, struct strbuf *parsed_format,
struct expand_data *data)
{
- for (; fmt->type; fmt++)
- switch (fmt->type) {
- case FORMAT_TYPE_END:
- BUG("we should have already left the loop!");
- break;
+ for (size_t i = 0; i < parsed_format->len; i++)
+ switch (parsed_format->buf[i]) {
case FORMAT_TYPE_OBJECTNAME:
strbuf_add_oid_hex(sb, &data->oid);
break;
@@ -453,7 +419,7 @@ static void expand_format(struct strbuf *sb, struct format_item *fmt,
strbuf_addf(sb, "%06o", data->mode);
break;
case FORMAT_TYPE_LITERAL:
- strbuf_add(sb, fmt->u.literal.p, fmt->u.literal.len);
+ strbuf_addch(sb, parsed_format->buf[++i]);
}
}
@@ -641,7 +607,7 @@ static void batch_object_write(const char *obj_name,
if (!opt->format) {
print_default_format(scratch, data, opt);
} else {
- expand_format(scratch, opt->parsed_format, data);
+ expand_format(scratch, &opt->parsed_format, data);
strbuf_addch(scratch, opt->output_delim);
}
@@ -1010,9 +976,8 @@ static int batch_objects(struct batch_options *opt)
int save_warning;
int retval = 0;
- opt->parsed_format = parse_format(opt->format ?
- opt->format : DEFAULT_FORMAT,
- &data);
+ parse_format(&opt->parsed_format,
+ opt->format ? opt->format : DEFAULT_FORMAT, &data);
if (opt->transform_mode)
data.split_on_whitespace = 1;
@@ -1152,6 +1117,7 @@ int cmd_cat_file(int argc,
const char *exp_type = NULL, *obj_name = NULL;
struct batch_options batch = {
.objects_filter = LIST_OBJECTS_FILTER_INIT,
+ .parsed_format = STRBUF_INIT,
};
int unknown_type = 0;
int input_nul_terminated = 0;
^ permalink raw reply related
* SHA-1/SHA-256 interoperability work is functional
From: brian m. carlson @ 2026-06-16 0:17 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: text/plain, Size: 6043 bytes --]
I'm pleased to announce that I have Git fully passing the testsuite and
CI in interoperability mode, both with SHA-256 and SHA-1 as the main
algorithm. While this is very exciting, the work is not ready to send
to the list and is effectively a draft, since there is still cleanup
and efficiency work to be done.
What is fully functional:
* The testsuite.
* The protocol, including extensions for mapping objects to support
shallow clones, submodules, and partial clones and interoperability
with remotes of different algorithms.
* A full complement of functionality for everyday use cases.
Features which are currently unsupported (and which may or may not be
supported in the future):
* Filtered bundles are unsupported because there is currently no way to provide
a mapping.
* Multi-pack index cannot be used as the sole pack index format because it does
not yet provide mappings.
* Pack index v1 and v2 cannot be used because they do not provide object
mappings. Git automatically uses pack index v3 instead when necessary, which
does handle mappings.
* Packfile URIs are not supported because the protocol-provided packfile is not
complete and its objects cannot be mapped.
* Large object promisors cannot be used if the server does not actually have
the entire history, since the server must have a complete history in order to
provide object mappings.
* `git fast-import` does not accept submodules in compatibility mode because
there is no provision for mappings.
* Remote helpers do not emit signatures in the compatibility algorithm for
signed tags.
* The WebDAV-based HTTP protocol doesn't support interoperability due to
the lack of a way to distribute mappings.
Some additional things that may need to be improved:
* We have some recursive delta resolution code in `git index-pack` that
will need to be made iterative to avoid stack overflows.
* We need to batch object maps whenever we write them, since having too
many causes `git gc` to kick off frequently (which can be seen in some
tests). This will require substantial refactoring of code like `git
add`, since any time we write an object we must be sure to always
write the mapping (even if we `die`).
* We will probably want to move the object map repacking code out of
`git gc` into a separate command that we can call manually.
* We may want some debugging tools for pack index v3 and other data
formats so that we can show the mapping of objects.
* We will probably want to be able to sign in only one algorithm instead
of always in both. Users may not want to sign the SHA-1 format for
security reasons.
* There is some extremely basic code for `^{sha1}` and `^{sha256}` to
help `git rev-list` perform connectivity checks for remotes using the
compatibility algorithm, but it is very much incomplete and will need
to be completed or fenced off.
* Operations can be rather slow in some cases and we'll want to see what
speedups we can perform.
* Probably other things I have forgotten.
There is new documentation in `Documentation/gitformat-hash.adoc` that
outlines the requirements for using the protocol. The protocol
restrictions described there are hard technical limitations that cannot
be avoided; I've intentionally made things as featureful as they can be.
This imposes real restrictions on using protocol interoperability with many
projects, including Git and Linux[0]. Interested parties may wish to look
at t1017 to see what's tested vis-à-vis the protocol and
interoperability.
On the end of the series is a small amount of new Rust code that moves
us in the direction of object file conversion in Rust. All the pointer
arithmetic makes me very nervous from a security perspective, especially
in network-facing code, so my hope is to eventually port that code over.
Note that Rust is already required for the interoperability work, so
this doesn't add any new dependencies.
I also have some unpublished code that could start on in-place migration
functionality much like is done with `git refs migrate` once the Rust
prerequisites above are ready. This could also make it possible at some
point to migrate any relevant submodules as part of the migration of the
main repository. I may or may not complete this work, but perhaps
someone else will want to pick it up if I do not. I'm certain that such
code would be valuable to many people, including forges.
I intend to rebase and tidy this work for at least a little while, but
don't actually intend to send it upstream, since there are some
technical limitations that prevent me from doing so. I have, however,
been in contact with someone (who may identify themselves if they
choose) who is interested in getting some of the polishing and
upstreaming work done, which I deeply appreciate.
If you're interested in testing or perusing the work, you may get it
from the `sha256-interop` branch of https://github.com/bk2204/git.git.
Please note that it may be rebased, rewound, or otherwise folded,
spindled, or mutilated at any time.
Even though the testsuite is passing earlier than I expected, I don't
expect it to make Git 3.0, nor do I think we should delay Git 3.0 for
this work. There are approximately 200 patches currently (and more to
come if we add in-place migration tooling), so it seems very unlikely
that we could get the entire series upstream in any reasonable amount of
time. We will also very much want to give this time in an experimental
state so people can try it out and report back on things that should be
improved, which is further evidence that it's not right for Git 3.0.
I'm happy to answer any further questions if folks have any.
[0] Git uses submodules, which would need to be rewritten first in order
to migrate, and Linux uses mergetags for which the tagged object is not
in the history (which makes mapping the commit containing it fail).
--
brian m. carlson (they/them)
Toronto, Ontario, CA
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 325 bytes --]
^ permalink raw reply
* Re: [GSoC] [Blog] week 3: Improving the new git repo command
From: K Jayatheerth @ 2026-06-16 3:41 UTC (permalink / raw)
To: GIT Mailing-list, Justin Tobler, Lucas Seiki Oshiro
In-Reply-To: <CA+rGoLeNzxaTrq50jE=at=0ecnZ5Diy+Q-0McG-R+XFTQ7oMow@mail.gmail.com>
Hi!
My Week 3 GSoC blog is live!
https://jayatheerth.com/blogs/gsoc/week-3-next-steps
Feel free to give it a read and share any feedback ; )
Regards,
- K Jayatheerth
^ permalink raw reply
* Re: [GSoC Patch v4 2/4] rev-parse: use append_formatted_path() for path formatting
From: K Jayatheerth @ 2026-06-16 4:19 UTC (permalink / raw)
To: Justin Tobler
Cc: git, a3205153416, gitster, kumarayushjha123, lucasseikioshiro,
phillip.wood, sandals, kristofferhaugsbakk
In-Reply-To: <ajAy1it6CGDQzVes@denethor>
Hey Justin,
>
> Without context, it might be a bit confusing to readers as to why we
> override PATH_FORMAT_DEFAULT without our own provided default. It may be
> worth leaving a comment to provide some breadcrumbs.
>
> The rest of this patch looks good to me.
That makes sense.
That's a minor change.
I will add proper comments!
> > Add a test helper test_repo_info_path that creates isolated
> > repositories per test case to prevent state leaks, captures the repo
> > root before changing directories to avoid eval, and accepts an optional
> > init_command to cover environment variable overrides such as
> > GIT_COMMON_DIR and GIT_DIR.
>
> I'm not sure this last paragraph in the log message provides much value.
> To me it's a bit verbose and focuses mostly on what the test helper is
> doing. Maybe we can just omit this section? If we want to have a note
> though maybe we could say something like:
>
> Each path key is expected to have an absolute and relative form. To
> reduce duplication, a test_repo_info_path helper function is
> introduced to configure and exercise both cases.
>
Now that I think about it
Maybe removing it is a better option.
I mean the patch itself contains the test and it has comments explaining
the test itself.
I am gonna remove the last para in the next series.
Thanks for pointing that out!
> > +test_repo_info_path () {
> > + label=$1
> > + field_name=$2
> > + repo_name=$3
> > + expect_absolute_suffix=$4
> > + expect_relative=$5
> > + init_command=$6
>
> I may be overthinking it, but I can't help but feel this test helper is
> overly complicated. I wonder if we can simlify and reduce the number of
> arguments. For example, could we programatically construct the label
> from the field name and init_command instead of explicitly passing it?
>
That’s a fair question
But I personally don't think the helper is overly complicated.
I think a lot of the current helper can be mapped with test_repo_info's
structure itself.
The existing helper uses a very similar 5-argument signature (label,
init_command, repo_name, key, expected_value)
and separates the setup step from the assertion steps.
Regarding the labels, I'd prefer to keep them explicitly passed in.
Programmatically constructing the label from the init_command could
result in messy
or hard-to-read test descriptions in the console output,
and having explicit strings makes it much easier to debug when a
specific test fails.
> > + absolute_root="$repo_name-absolute"
> > + relative_root="$repo_name-relative"
> > +
> > + test_expect_success "setup: $label" '
> > + git init "$absolute_root" &&
> > + git init "$relative_root" &&
> > + mkdir -p "$absolute_root/sub" "$relative_root/sub"
> > + '
>
> Do really need this setup test case? Could we instead embed the setup in
> both test cases below? Something like:
>
> test_when_finished rm -rf repo &&
> git init repo &&
> (
> mkdir repo/sub &&
> cd repo/sub &&
> ...
> )
>
That's a much more elegant way to handle it.
I will incorporate this in v5!
> With something like this, each test case is responsible to creating its
> own repo and cleaning it up when finished. Then we could avoid have to
> provide a separate repo name for each set of test cases and remove the
> repo_name argument.
>
True,
Thanks!
> > +test_repo_info_path 'commondir standard' 'commondir' 'commondir-std' \
> > + '.git' '../.git'
> > +
> > +test_repo_info_path 'commondir with GIT_COMMON_DIR and GIT_DIR' 'commondir' \
> > + 'commondir-envs' 'custom-common' '../custom-common' \
> > + 'GIT_COMMON_DIR="$ROOT/custom-common" && export GIT_COMMON_DIR &&
> > + GIT_DIR="../.git" && export GIT_DIR &&
> > + git init --bare "$ROOT/custom-common"'
> > +
> > +test_repo_info_path 'commondir with only GIT_DIR' 'commondir' \
> > + 'commondir-only-gitdir' '.git' '../.git' \
>
> For each of these test cases, the `expect_absolute_suffix` and
> `expect_relative` and exactly the same. This also appears to be the case
> for the test cases in the next patch. Do these really need to be
> configurable at all? Can we just embed them directly in each test case
> assertion? Or maybe future keys will need this to be configurable?
>
You're right that passing both is completely redundant!
However, the path does still need to be configurable because the directory
name changes between test cases (e.g., `.git` in the standard case vs.
`custom-common` when GIT_COMMON_DIR is exported).
Since the relative path is always just `../` appended to the directory name,
I will condense these two arguments into a single `expected_dir` argument in v5.
The helper will then just construct `$ROOT/$expected_dir` and
`../$expected_dir` internally.
> > + 'GIT_DIR="../.git" && export GIT_DIR'
> > +
> > test_done
>
> Overall the rest of the patch looks good to me.
>
Thanks again!
These are helpful.
Regards,
- K Jayatheerth
^ permalink raw reply
* [GSoC Patch v5 0/4] teach git repo info to handle path keys
From: K Jayatheerth @ 2026-06-16 4:49 UTC (permalink / raw)
To: git
Cc: jltobler, lucasseikioshiro, gitster, phillip.wood, sandals,
kumarayushjha123, a3205153416, K Jayatheerth
In-Reply-To: <20260601151950.30686-1-jayatheerthkulkarni2005@gmail.com>
Hi!
This series teaches `git repo info` to handle `path.*`
keys, allowing scripts to reliably discover core
repository paths without resorting to `git rev-parse`.
The patches are structured as follows:
1. path: Extract the localized path-formatting logic
out of `rev-parse` and expose it globally via
`path.h` using clear append semantics.
2. rev-parse: Refactor the command to leverage the
newly shared path engine.
3. repo: Introduce `path.commondir.absolute` and
`path.commondir.relative` alongside a robust,
isolated test helper.
4. repo: Introduce `path.gitdir.absolute` and
`path.gitdir.relative` using the same standardized
formatting rules.
changes since v4:
* Simplified the `test_repo_info_path` helper by dropping the `repo_name`
argument and utilizing `test_when_finished "rm -rf repo"` to handle
repository setup/teardown inline. This ensures perfect test isolation.
* Condensed the redundant `expect_absolute_suffix` and `expect_relative`
test helper arguments into a single `expected_dir` argument, reducing
the helper signature to 4 arguments (Justin).
* Added a contextual comment in `builtin/rev-parse.c`'s `print_path()`
explaining why `PATH_FORMAT_DEFAULT` is intercepted and overridden with
a path-specific fallback (Justin).
* Trimmed the verbose test helper explanations from the commit messages
in patches 3 and 4.
K Jayatheerth (4):
path: introduce append_formatted_path() for shared path formatting
rev-parse: use append_formatted_path() for path formatting
repo: add path.commondir with absolute and relative suffix formatting
repo: add path.gitdir with absolute and relative suffix formatting
Documentation/git-repo.adoc | 15 ++++++
builtin/repo.c | 50 +++++++++++++++++
builtin/rev-parse.c | 104 +++++++++---------------------------
path.c | 70 ++++++++++++++++++++++++
path.h | 36 +++++++++++++
t/t1900-repo-info.sh | 58 ++++++++++++++++++++
6 files changed, 253 insertions(+), 80 deletions(-)
Range-diff against v4:
1: a396b4f8e6 = 1: a396b4f8e6 path: introduce append_formatted_path() for shared path formatting
2: 16198f96d1 ! 2: 16b42a51d2 rev-parse: use append_formatted_path() for path formatting
@@ builtin/rev-parse.c: static void handle_ref_opt(const char *pattern, const char
- }
- free(cwd);
+ struct strbuf sb = STRBUF_INIT;
++ /* If the user didn't explicitly specify a format, fallback to the path-specific default. */
+ enum path_format fmt = (arg_path_format != PATH_FORMAT_DEFAULT) ? arg_path_format : def_format;
+
+ append_formatted_path(&sb, path, prefix, fmt);
3: b45c6f0d12 ! 3: 38b733ea64 repo: add path.commondir with absolute and relative suffix formatting
@@ Commit message
Exposing explicit format variants rather than a single key with a
default avoids ambiguity for scripts that require predictable output.
- Add a test helper test_repo_info_path that creates isolated
- repositories per test case to prevent state leaks, captures the repo
- root before changing directories to avoid eval, and accepts an optional
- init_command to cover environment variable overrides such as
- GIT_COMMON_DIR and GIT_DIR.
-
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
@@ t/t1900-repo-info.sh: test_expect_success 'git repo info -h shows only repo info
+# Helper function to test path keys in both absolute and relative formats.
+# $1: label for the test
+# $2: field_name (e.g., commondir)
-+# $3: unique repo name for isolation
-+# $4: expect_absolute (suffix appended to repo root)
-+# $5: expect_relative (the relative path string expected)
-+# $6: init_command (extra setup like exporting env vars)
++# $3: expected_dir (the directory name, e.g., .git or custom-common)
++# $4: init_command (extra setup like exporting env vars)
+test_repo_info_path () {
+ label=$1
+ field_name=$2
-+ repo_name=$3
-+ expect_absolute_suffix=$4
-+ expect_relative=$5
-+ init_command=$6
-+
-+ absolute_root="$repo_name-absolute"
-+ relative_root="$repo_name-relative"
-+
-+ test_expect_success "setup: $label" '
-+ git init "$absolute_root" &&
-+ git init "$relative_root" &&
-+ mkdir -p "$absolute_root/sub" "$relative_root/sub"
-+ '
++ expected_dir=$3
++ init_command=$4
+
+ test_expect_success "absolute: $label" '
++ test_when_finished "rm -rf repo" &&
++ git init repo &&
+ (
-+ cd "$absolute_root/sub" &&
++ mkdir -p repo/sub &&
++ cd repo/sub &&
+ ROOT="$(test-tool path-utils real_path ..)" && export ROOT &&
+ eval "$init_command" &&
-+ expect_path="$ROOT${expect_absolute_suffix:+/$expect_absolute_suffix}" &&
-+ echo "path.$field_name.absolute=$expect_path" >expect &&
++ echo "path.$field_name.absolute=$ROOT/$expected_dir" >expect &&
+ git repo info "path.$field_name.absolute" >actual &&
+ test_cmp expect actual
+ )
+ '
+
+ test_expect_success "relative: $label" '
++ test_when_finished "rm -rf repo" &&
++ git init repo &&
+ (
-+ cd "$relative_root/sub" &&
++ mkdir -p repo/sub &&
++ cd repo/sub &&
+ ROOT="$(test-tool path-utils real_path ..)" && export ROOT &&
+ eval "$init_command" &&
-+ echo "path.$field_name.relative=$expect_relative" >expect &&
++ echo "path.$field_name.relative=../$expected_dir" >expect &&
+ git repo info "path.$field_name.relative" >actual &&
+ test_cmp expect actual
+ )
+ '
+}
+
-+test_repo_info_path 'commondir standard' 'commondir' 'commondir-std' \
-+ '.git' '../.git'
++test_repo_info_path 'commondir standard' 'commondir' '.git'
+
+test_repo_info_path 'commondir with GIT_COMMON_DIR and GIT_DIR' 'commondir' \
-+ 'commondir-envs' 'custom-common' '../custom-common' \
++ 'custom-common' \
+ 'GIT_COMMON_DIR="$ROOT/custom-common" && export GIT_COMMON_DIR &&
+ GIT_DIR="../.git" && export GIT_DIR &&
+ git init --bare "$ROOT/custom-common"'
+
+test_repo_info_path 'commondir with only GIT_DIR' 'commondir' \
-+ 'commondir-only-gitdir' '.git' '../.git' \
++ '.git' \
+ 'GIT_DIR="../.git" && export GIT_DIR'
+
test_done
4: b5234ffe3e ! 4: ead1117332 repo: add path.gitdir with absolute and relative suffix formatting
@@ builtin/repo.c: static const struct repo_info_field repo_info_field[] = {
## t/t1900-repo-info.sh ##
@@ t/t1900-repo-info.sh: test_repo_info_path 'commondir with only GIT_DIR' 'commondir' \
- 'commondir-only-gitdir' '.git' '../.git' \
+ '.git' \
'GIT_DIR="../.git" && export GIT_DIR'
-+test_repo_info_path 'gitdir standard' 'gitdir' 'gitdir-std' \
-+ '.git' '../.git'
++test_repo_info_path 'gitdir standard' 'gitdir' '.git'
+
+test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
-+ 'gitdir-env' '.git' '../.git' \
++ '.git' \
+ 'GIT_DIR="../.git" && export GIT_DIR'
+
test_done
--
2.54.0
^ permalink raw reply
* [GSoC Patch v5 1/4] path: introduce append_formatted_path() for shared path formatting
From: K Jayatheerth @ 2026-06-16 4:49 UTC (permalink / raw)
To: git
Cc: jltobler, lucasseikioshiro, gitster, phillip.wood, sandals,
kumarayushjha123, a3205153416, K Jayatheerth
In-Reply-To: <20260616044953.184806-1-jayatheerthkulkarni2005@gmail.com>
The path-formatting logic in builtin/rev-parse.c is tightly coupled
to that command and writes directly to stdout, making it impossible
for other builtins to reuse.
Extract the core algorithm into append_formatted_path() in path.c
and expose a path_format enum in path.h so that any builtin can
format paths consistently without duplicating logic.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
path.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
path.h | 36 ++++++++++++++++++++++++++++++
2 files changed, 106 insertions(+)
diff --git a/path.c b/path.c
index d7e17bf174..5e83e3e4f6 100644
--- a/path.c
+++ b/path.c
@@ -1579,6 +1579,76 @@ char *xdg_cache_home(const char *filename)
return NULL;
}
+void append_formatted_path(struct strbuf *dest, const char *path,
+ const char *prefix, enum path_format format)
+{
+ switch (format) {
+ case PATH_FORMAT_DEFAULT:
+ case PATH_FORMAT_UNMODIFIED:
+ strbuf_addstr(dest, path);
+ break;
+
+ case PATH_FORMAT_RELATIVE: {
+ struct strbuf relative_buf = STRBUF_INIT;
+ struct strbuf real_path = STRBUF_INIT;
+ struct strbuf real_prefix = STRBUF_INIT;
+ char *cwd = NULL;
+
+ /*
+ * We don't ever produce a relative path if prefix is NULL,
+ * so set the prefix to the current directory so that we can
+ * produce a relative path whenever possible.
+ */
+ if (!prefix)
+ prefix = cwd = xgetcwd();
+
+ if (!is_absolute_path(path)) {
+ strbuf_realpath_forgiving(&real_path, path, 1);
+ path = real_path.buf;
+ }
+ if (!is_absolute_path(prefix)) {
+ strbuf_realpath_forgiving(&real_prefix, prefix, 1);
+ prefix = real_prefix.buf;
+ }
+
+ strbuf_addstr(dest, relative_path(path, prefix, &relative_buf));
+
+ strbuf_release(&relative_buf);
+ strbuf_release(&real_path);
+ strbuf_release(&real_prefix);
+ free(cwd);
+ break;
+ }
+
+ case PATH_FORMAT_RELATIVE_IF_SHARED: {
+ struct strbuf relative_buf = STRBUF_INIT;
+
+ /*
+ * If we're using RELATIVE_IF_SHARED mode, then we want an
+ * absolute path unless the two share a common prefix, so don't
+ * default the prefix to the current working directory. Doing so
+ * would cause a relative path to always be produced if possible.
+ */
+ strbuf_addstr(dest, relative_path(path, prefix, &relative_buf));
+ strbuf_release(&relative_buf);
+ break;
+ }
+
+ case PATH_FORMAT_CANONICAL: {
+ struct strbuf canonical_buf = STRBUF_INIT;
+
+ strbuf_realpath_forgiving(&canonical_buf, path, 1);
+ strbuf_addbuf(dest, &canonical_buf);
+
+ strbuf_release(&canonical_buf);
+ break;
+ }
+
+ default:
+ BUG("unknown path_format value %d", format);
+ }
+}
+
REPO_GIT_PATH_FUNC(squash_msg, "SQUASH_MSG")
REPO_GIT_PATH_FUNC(merge_msg, "MERGE_MSG")
REPO_GIT_PATH_FUNC(merge_rr, "MERGE_RR")
diff --git a/path.h b/path.h
index 0434ba5e07..6aca53b100 100644
--- a/path.h
+++ b/path.h
@@ -262,6 +262,42 @@ enum scld_error safe_create_leading_directories_no_share(char *path);
int safe_create_file_with_leading_directories(struct repository *repo,
const char *path);
+/**
+ * The formatting strategy to apply when writing a path into a buffer.
+ */
+enum path_format {
+ /*
+ * Represents the default formatting behavior. Treated as
+ * PATH_FORMAT_UNMODIFIED by append_formatted_path().
+ */
+ PATH_FORMAT_DEFAULT,
+
+ /* Output the path exactly as-is without any modifications. */
+ PATH_FORMAT_UNMODIFIED,
+
+ /* Output a path relative to the provided directory prefix. */
+ PATH_FORMAT_RELATIVE,
+
+ /* Output a relative path only if the path shares a root with the prefix. */
+ PATH_FORMAT_RELATIVE_IF_SHARED,
+
+ /* Output a fully resolved, absolute canonical path. */
+ PATH_FORMAT_CANONICAL
+};
+
+/**
+ * Format a path according to the specified formatting strategy and append
+ * the result to the given strbuf.
+ *
+ * `dest` : The string buffer to append the formatted path to.
+ * `path` : The path string that needs to be formatted.
+ * `prefix` : The directory prefix to calculate relative offsets against.
+ * Pass NULL to default to the current working directory where applicable.
+ * `format` : The formatting behavior rule to execute.
+ */
+void append_formatted_path(struct strbuf *dest, const char *path,
+ const char *prefix, enum path_format format);
+
# ifdef USE_THE_REPOSITORY_VARIABLE
# include "strbuf.h"
# include "repository.h"
--
2.54.0
^ permalink raw reply related
* [GSoC Patch v5 2/4] rev-parse: use append_formatted_path() for path formatting
From: K Jayatheerth @ 2026-06-16 4:49 UTC (permalink / raw)
To: git
Cc: jltobler, lucasseikioshiro, gitster, phillip.wood, sandals,
kumarayushjha123, a3205153416, K Jayatheerth
In-Reply-To: <20260616044953.184806-1-jayatheerthkulkarni2005@gmail.com>
Now that path formatting logic lives in a shared helper, keeping a
duplicate implementation in rev-parse is unnecessary and risks the
two diverging over time.
Replace the local format_type and default_type enums and the
hand-rolled formatting logic with a call to append_formatted_path().
Introduce PATH_FORMAT_DEFAULT as the initial value of arg_path_format
so that per-path fallback behavior is resolved in print_path() rather
than leaked into the shared helper.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
builtin/rev-parse.c | 104 ++++++++++----------------------------------
1 file changed, 24 insertions(+), 80 deletions(-)
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 218b5f34d6..1fdcb946a7 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -632,73 +632,17 @@ static void handle_ref_opt(const char *pattern, const char *prefix)
clear_ref_exclusions(&ref_excludes);
}
-enum format_type {
- /* We would like a relative path. */
- FORMAT_RELATIVE,
- /* We would like a canonical absolute path. */
- FORMAT_CANONICAL,
- /* We would like the default behavior. */
- FORMAT_DEFAULT,
-};
-
-enum default_type {
- /* Our default is a relative path. */
- DEFAULT_RELATIVE,
- /* Our default is a relative path if there's a shared root. */
- DEFAULT_RELATIVE_IF_SHARED,
- /* Our default is a canonical absolute path. */
- DEFAULT_CANONICAL,
- /* Our default is not to modify the item. */
- DEFAULT_UNMODIFIED,
-};
-
-static void print_path(const char *path, const char *prefix, enum format_type format, enum default_type def)
+static void print_path(const char *path, const char *prefix,
+ enum path_format arg_path_format, enum path_format def_format)
{
- char *cwd = NULL;
- /*
- * We don't ever produce a relative path if prefix is NULL, so set the
- * prefix to the current directory so that we can produce a relative
- * path whenever possible. If we're using RELATIVE_IF_SHARED mode, then
- * we want an absolute path unless the two share a common prefix, so don't
- * set it in that case, since doing so causes a relative path to always
- * be produced if possible.
- */
- if (!prefix && (format != FORMAT_DEFAULT || def != DEFAULT_RELATIVE_IF_SHARED))
- prefix = cwd = xgetcwd();
- if (format == FORMAT_DEFAULT && def == DEFAULT_UNMODIFIED) {
- puts(path);
- } else if (format == FORMAT_RELATIVE ||
- (format == FORMAT_DEFAULT && def == DEFAULT_RELATIVE)) {
- /*
- * In order for relative_path to work as expected, we need to
- * make sure that both paths are absolute paths. If we don't,
- * we can end up with an unexpected absolute path that the user
- * didn't want.
- */
- struct strbuf buf = STRBUF_INIT, realbuf = STRBUF_INIT, prefixbuf = STRBUF_INIT;
- if (!is_absolute_path(path)) {
- strbuf_realpath_forgiving(&realbuf, path, 1);
- path = realbuf.buf;
- }
- if (!is_absolute_path(prefix)) {
- strbuf_realpath_forgiving(&prefixbuf, prefix, 1);
- prefix = prefixbuf.buf;
- }
- puts(relative_path(path, prefix, &buf));
- strbuf_release(&buf);
- strbuf_release(&realbuf);
- strbuf_release(&prefixbuf);
- } else if (format == FORMAT_DEFAULT && def == DEFAULT_RELATIVE_IF_SHARED) {
- struct strbuf buf = STRBUF_INIT;
- puts(relative_path(path, prefix, &buf));
- strbuf_release(&buf);
- } else {
- struct strbuf buf = STRBUF_INIT;
- strbuf_realpath_forgiving(&buf, path, 1);
- puts(buf.buf);
- strbuf_release(&buf);
- }
- free(cwd);
+ struct strbuf sb = STRBUF_INIT;
+ /* If the user didn't explicitly specify a format, fallback to the path-specific default. */
+ enum path_format fmt = (arg_path_format != PATH_FORMAT_DEFAULT) ? arg_path_format : def_format;
+
+ append_formatted_path(&sb, path, prefix, fmt);
+ puts(sb.buf);
+
+ strbuf_release(&sb);
}
int cmd_rev_parse(int argc,
@@ -717,7 +661,7 @@ int cmd_rev_parse(int argc,
const char *name = NULL;
struct strbuf buf = STRBUF_INIT;
int seen_end_of_options = 0;
- enum format_type format = FORMAT_DEFAULT;
+ enum path_format arg_path_format = PATH_FORMAT_DEFAULT;
show_usage_if_asked(argc, argv, builtin_rev_parse_usage);
@@ -797,8 +741,8 @@ int cmd_rev_parse(int argc,
die(_("--git-path requires an argument"));
print_path(repo_git_path_replace(the_repository, &buf,
"%s", argv[i + 1]), prefix,
- format,
- DEFAULT_RELATIVE_IF_SHARED);
+ arg_path_format,
+ PATH_FORMAT_RELATIVE_IF_SHARED);
i++;
continue;
}
@@ -820,9 +764,9 @@ int cmd_rev_parse(int argc,
if (!arg)
die(_("--path-format requires an argument"));
if (!strcmp(arg, "absolute")) {
- format = FORMAT_CANONICAL;
+ arg_path_format = PATH_FORMAT_CANONICAL;
} else if (!strcmp(arg, "relative")) {
- format = FORMAT_RELATIVE;
+ arg_path_format = PATH_FORMAT_RELATIVE;
} else {
die(_("unknown argument to --path-format: %s"), arg);
}
@@ -985,7 +929,7 @@ int cmd_rev_parse(int argc,
if (!strcmp(arg, "--show-toplevel")) {
const char *work_tree = repo_get_work_tree(the_repository);
if (work_tree)
- print_path(work_tree, prefix, format, DEFAULT_UNMODIFIED);
+ print_path(work_tree, prefix, arg_path_format, PATH_FORMAT_UNMODIFIED);
else
die(_("this operation must be run in a work tree"));
continue;
@@ -993,7 +937,7 @@ int cmd_rev_parse(int argc,
if (!strcmp(arg, "--show-superproject-working-tree")) {
struct strbuf superproject = STRBUF_INIT;
if (get_superproject_working_tree(&superproject))
- print_path(superproject.buf, prefix, format, DEFAULT_UNMODIFIED);
+ print_path(superproject.buf, prefix, arg_path_format, PATH_FORMAT_UNMODIFIED);
strbuf_release(&superproject);
continue;
}
@@ -1028,18 +972,18 @@ int cmd_rev_parse(int argc,
const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
char *cwd;
int len;
- enum format_type wanted = format;
+ enum path_format wanted = arg_path_format;
if (arg[2] == 'g') { /* --git-dir */
if (gitdir) {
- print_path(gitdir, prefix, format, DEFAULT_UNMODIFIED);
+ print_path(gitdir, prefix, arg_path_format, PATH_FORMAT_UNMODIFIED);
continue;
}
if (!prefix) {
- print_path(".git", prefix, format, DEFAULT_UNMODIFIED);
+ print_path(".git", prefix, arg_path_format, PATH_FORMAT_UNMODIFIED);
continue;
}
} else { /* --absolute-git-dir */
- wanted = FORMAT_CANONICAL;
+ wanted = PATH_FORMAT_CANONICAL;
if (!gitdir && !prefix)
gitdir = ".git";
if (gitdir) {
@@ -1055,11 +999,11 @@ int cmd_rev_parse(int argc,
strbuf_reset(&buf);
strbuf_addf(&buf, "%s%s.git", cwd, len && cwd[len-1] != '/' ? "/" : "");
free(cwd);
- print_path(buf.buf, prefix, wanted, DEFAULT_CANONICAL);
+ print_path(buf.buf, prefix, wanted, PATH_FORMAT_CANONICAL);
continue;
}
if (!strcmp(arg, "--git-common-dir")) {
- print_path(repo_get_common_dir(the_repository), prefix, format, DEFAULT_RELATIVE_IF_SHARED);
+ print_path(repo_get_common_dir(the_repository), prefix, arg_path_format, PATH_FORMAT_RELATIVE_IF_SHARED);
continue;
}
if (!strcmp(arg, "--is-inside-git-dir")) {
@@ -1089,7 +1033,7 @@ int cmd_rev_parse(int argc,
if (the_repository->index->split_index) {
const struct object_id *oid = &the_repository->index->split_index->base_oid;
const char *path = repo_git_path_replace(the_repository, &buf, "sharedindex.%s", oid_to_hex(oid));
- print_path(path, prefix, format, DEFAULT_RELATIVE);
+ print_path(path, prefix, arg_path_format, PATH_FORMAT_RELATIVE);
}
continue;
}
--
2.54.0
^ permalink raw reply related
* [GSoC Patch v5 3/4] repo: add path.commondir with absolute and relative suffix formatting
From: K Jayatheerth @ 2026-06-16 4:49 UTC (permalink / raw)
To: git
Cc: jltobler, lucasseikioshiro, gitster, phillip.wood, sandals,
kumarayushjha123, a3205153416, K Jayatheerth
In-Reply-To: <20260616044953.184806-1-jayatheerthkulkarni2005@gmail.com>
Scripts working with worktree setups need a reliable way to discover
the common directory, which diverges from the git directory when
multiple worktrees are in use. There is no way to retrieve this path
from git repo info today.
Introduce path.commondir.absolute and path.commondir.relative keys.
Exposing explicit format variants rather than a single key with a
default avoids ambiguity for scripts that require predictable output.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Documentation/git-repo.adoc | 9 +++++++
builtin/repo.c | 26 +++++++++++++++++++
t/t1900-repo-info.sh | 52 +++++++++++++++++++++++++++++++++++++
3 files changed, 87 insertions(+)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 42262c1983..890c34051d 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -104,6 +104,15 @@ values that they return:
`object.format`::
The object format (hash algorithm) used in the repository.
+`path.commondir.absolute`::
+ The canonical absolute path to the Git repository's common
+ directory (the shared `.git` directory containing objects,
+ refs, and global configuration).
+
+`path.commondir.relative`::
+ The path to the Git repository's common directory relative to
+ the current working directory.
+
`references.format`::
The reference storage format. The valid values are:
+
diff --git a/builtin/repo.c b/builtin/repo.c
index 71a5c1c29c..c4cc3bf3fc 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -7,12 +7,14 @@
#include "hex.h"
#include "odb.h"
#include "parse-options.h"
+#include "path.h"
#include "path-walk.h"
#include "progress.h"
#include "quote.h"
#include "ref-filter.h"
#include "refs.h"
#include "revision.h"
+#include "setup.h"
#include "strbuf.h"
#include "string-list.h"
#include "shallow.h"
@@ -75,6 +77,28 @@ static int get_object_format(struct repository *repo, struct strbuf *buf)
return 0;
}
+static int get_path_commondir_absolute(struct repository *repo, struct strbuf *buf)
+{
+ const char *common_dir = repo_get_common_dir(repo);
+
+ if (!common_dir)
+ return error(_("unable to get common directory"));
+
+ append_formatted_path(buf, common_dir, startup_info->prefix, PATH_FORMAT_CANONICAL);
+ return 0;
+}
+
+static int get_path_commondir_relative(struct repository *repo, struct strbuf *buf)
+{
+ const char *common_dir = repo_get_common_dir(repo);
+
+ if (!common_dir)
+ return error(_("unable to get common directory"));
+
+ append_formatted_path(buf, common_dir, startup_info->prefix, PATH_FORMAT_RELATIVE);
+ return 0;
+}
+
static int get_references_format(struct repository *repo, struct strbuf *buf)
{
strbuf_addstr(buf,
@@ -87,6 +111,8 @@ static const struct repo_info_field repo_info_field[] = {
{ "layout.bare", get_layout_bare },
{ "layout.shallow", get_layout_shallow },
{ "object.format", get_object_format },
+ { "path.commondir.absolute", get_path_commondir_absolute },
+ { "path.commondir.relative", get_path_commondir_relative },
{ "references.format", get_references_format },
};
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 39bb77dda0..09158d29f9 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -155,4 +155,56 @@ test_expect_success 'git repo info -h shows only repo info usage' '
test_grep ! "git repo structure" actual
'
+# Helper function to test path keys in both absolute and relative formats.
+# $1: label for the test
+# $2: field_name (e.g., commondir)
+# $3: expected_dir (the directory name, e.g., .git or custom-common)
+# $4: init_command (extra setup like exporting env vars)
+test_repo_info_path () {
+ label=$1
+ field_name=$2
+ expected_dir=$3
+ init_command=$4
+
+ test_expect_success "absolute: $label" '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ mkdir -p repo/sub &&
+ cd repo/sub &&
+ ROOT="$(test-tool path-utils real_path ..)" && export ROOT &&
+ eval "$init_command" &&
+ echo "path.$field_name.absolute=$ROOT/$expected_dir" >expect &&
+ git repo info "path.$field_name.absolute" >actual &&
+ test_cmp expect actual
+ )
+ '
+
+ test_expect_success "relative: $label" '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ mkdir -p repo/sub &&
+ cd repo/sub &&
+ ROOT="$(test-tool path-utils real_path ..)" && export ROOT &&
+ eval "$init_command" &&
+ echo "path.$field_name.relative=../$expected_dir" >expect &&
+ git repo info "path.$field_name.relative" >actual &&
+ test_cmp expect actual
+ )
+ '
+}
+
+test_repo_info_path 'commondir standard' 'commondir' '.git'
+
+test_repo_info_path 'commondir with GIT_COMMON_DIR and GIT_DIR' 'commondir' \
+ 'custom-common' \
+ 'GIT_COMMON_DIR="$ROOT/custom-common" && export GIT_COMMON_DIR &&
+ GIT_DIR="../.git" && export GIT_DIR &&
+ git init --bare "$ROOT/custom-common"'
+
+test_repo_info_path 'commondir with only GIT_DIR' 'commondir' \
+ '.git' \
+ 'GIT_DIR="../.git" && export GIT_DIR'
+
test_done
--
2.54.0
^ permalink raw reply related
* [GSoC Patch v5 4/4] repo: add path.gitdir with absolute and relative suffix formatting
From: K Jayatheerth @ 2026-06-16 4:49 UTC (permalink / raw)
To: git
Cc: jltobler, lucasseikioshiro, gitster, phillip.wood, sandals,
kumarayushjha123, a3205153416, K Jayatheerth
In-Reply-To: <20260616044953.184806-1-jayatheerthkulkarni2005@gmail.com>
Scripts need a stable way to locate the git directory without
parsing rev-parse output or relying on its flag-driven path format
selection. There is no way to retrieve this path from git repo info
today.
Introduce path.gitdir.absolute and path.gitdir.relative keys,
consistent with the path.commondir keys added in the previous patch.
Reuse the test_repo_info_path helper introduced there to validate
both variants.
Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
---
Documentation/git-repo.adoc | 6 ++++++
builtin/repo.c | 24 ++++++++++++++++++++++++
t/t1900-repo-info.sh | 6 ++++++
3 files changed, 36 insertions(+)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index 890c34051d..ed7d80c690 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -113,6 +113,12 @@ values that they return:
The path to the Git repository's common directory relative to
the current working directory.
+`path.gitdir.absolute`::
+ The canonical absolute path to the Git repository directory (the `.git` directory).
+
+`path.gitdir.relative`::
+ The path to the Git repository directory relative to the current working directory.
+
`references.format`::
The reference storage format. The valid values are:
+
diff --git a/builtin/repo.c b/builtin/repo.c
index c4cc3bf3fc..9a312d127a 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -99,6 +99,28 @@ static int get_path_commondir_relative(struct repository *repo, struct strbuf *b
return 0;
}
+static int get_path_gitdir_absolute(struct repository *repo, struct strbuf *buf)
+{
+ const char *git_dir = repo_get_git_dir(repo);
+
+ if (!git_dir)
+ return error(_("unable to get git directory"));
+
+ append_formatted_path(buf, git_dir, startup_info->prefix, PATH_FORMAT_CANONICAL);
+ return 0;
+}
+
+static int get_path_gitdir_relative(struct repository *repo, struct strbuf *buf)
+{
+ const char *git_dir = repo_get_git_dir(repo);
+
+ if (!git_dir)
+ return error(_("unable to get git directory"));
+
+ append_formatted_path(buf, git_dir, startup_info->prefix, PATH_FORMAT_RELATIVE);
+ return 0;
+}
+
static int get_references_format(struct repository *repo, struct strbuf *buf)
{
strbuf_addstr(buf,
@@ -113,6 +135,8 @@ static const struct repo_info_field repo_info_field[] = {
{ "object.format", get_object_format },
{ "path.commondir.absolute", get_path_commondir_absolute },
{ "path.commondir.relative", get_path_commondir_relative },
+ { "path.gitdir.absolute", get_path_gitdir_absolute },
+ { "path.gitdir.relative", get_path_gitdir_relative },
{ "references.format", get_references_format },
};
diff --git a/t/t1900-repo-info.sh b/t/t1900-repo-info.sh
index 09158d29f9..ae8c22c817 100755
--- a/t/t1900-repo-info.sh
+++ b/t/t1900-repo-info.sh
@@ -207,4 +207,10 @@ test_repo_info_path 'commondir with only GIT_DIR' 'commondir' \
'.git' \
'GIT_DIR="../.git" && export GIT_DIR'
+test_repo_info_path 'gitdir standard' 'gitdir' '.git'
+
+test_repo_info_path 'gitdir with explicit GIT_DIR' 'gitdir' \
+ '.git' \
+ 'GIT_DIR="../.git" && export GIT_DIR'
+
test_done
--
2.54.0
^ permalink raw reply related
* Re: [PATCH] builtin/history: unuse the commit buffer after use
From: Patrick Steinhardt @ 2026-06-16 5:45 UTC (permalink / raw)
To: Jeff King; +Cc: Kaartic Sivaraam, Git mailing list
In-Reply-To: <20260615172946.GD91269@coredump.intra.peff.net>
On Mon, Jun 15, 2026 at 01:29:46PM -0400, Jeff King wrote:
> On Mon, Jun 15, 2026 at 11:48:10AM +0200, Patrick Steinhardt wrote:
>
> > On Sun, Jun 14, 2026 at 02:15:40PM +0000, Kaartic Sivaraam wrote:
> > > While running `git history reword` using a Git built with `SANITIZE` flag set
> > > to `address,leak`, we could observe the following leak being reported:
> >
> > Huh, curious. That seems to hint that we're missing test coverage for
> > this specific scenario, as our test suite doesn't detect this leak.
>
> I think it will only leak when the commit object has an "encoding"
> header. See below.
>
> > > As part of rewording a commit in `git history`, we get the commit message
> > > buffer in the `commit_tree_ext` function. This in turn obtains the buffer
> > > from `repo_logmsg_reencode`. Given how `commit_tree_ext` is invoking the
> > > function with the last two parameters as NULL, we are clearly not expecting
> > > a reencode to happen. In this case, the buffer that we receive from
> > > `repo_logmsg_reencode` ends up always being obtained from a call to
> > > `repo_get_commit_buffer`.
> > >
> > > This buffer is expected to be released with an accompanying call to
> > > `repo_unuse_commit_buffer` which takes care of freeing it. This call
> > > is missing in the `commit_tree_ext` flow thus resulting in the leak.
> >
> > So this doesn't really read specific at all, and I would have expected
> > us to hit this leak. Puzzling.
>
> The first paragraph is accurate here. We'd generally just get a pointer
> to the buffer cached in the slab, because no re-encoding occurs. And in
> that case you _don't_ need to call unuse_commit_buffer(), because you
> have a read-only copy, and the slab cache will hold it forever[1].
> Calling the unuse function will be a noop.
>
> But when we _do_ re-encode, then you get a new buffer which must be
> freed. And that is when you have to call the unuse function. And the
> reason it is "unuse" and not just "free" is that you don't necessarily
> know which you have, but that function figures it out (and frees it only
> if necessary).
>
> So what the patch is doing is correct, but the explanation is a little
> confused. We see the leak only when re-encoding, so we'd probably want a
> test case that triggers that. Which I assume implies rewriting a commit
> that was previously generated with an encoding header.
>
> Now back to that [1] note. Even if we didn't re-encode, we'll still hold
> onto that buffer forever. It's not a "leak" in the traditional sense
> because it's still referenced in the commit slab cache. But if you are
> going to walk over a million commits (like git-log does), you probably
> don't want to hold a million commit messages in memory at once.
>
> For that you'd want to call free_commit_buffer() when you know you're
> totally done with it (again, like git-log does after it finishes showing
> the commit). That might be the case here in commit_tree_ext(), or it
> might happen later (I'm not familiar with the git-history code).
>
> But note that you need to do _both_ the unuse and free calls. If we did
> re-encode, the former is needed to free the newly allocated buffer. The
> latter only drops the original buffer in the cache.
Thanks for the explanation!
Patrick
^ permalink raw reply
* Re: [PATCH v4 0/3] Documentation: recommend the use of b4
From: Toon Claes @ 2026-06-16 6:40 UTC (permalink / raw)
To: Patrick Steinhardt, git
Cc: Junio C Hamano, Tuomas Ahola, Weijie Yuan, Ramsay Jones,
SZEDER Gábor, Kristoffer Haugsbakk, Karthik Nayak
In-Reply-To: <20260615-pks-b4-v4-0-22cfca8f19c5@pks.im>
Patrick Steinhardt <ps@pks.im> writes:
> Hi,
>
> this small patch series wires up b4 in Git and recommends the use
> thereof via "MyFirstContribution", as discussed in [1].
>
> Changes in v4:
> - Improve a commit message.
> - Link to v3: https://patch.msgid.link/20260608-pks-b4-v3-0-f5e497d10c56@pks.im
>
> Changes in v3:
> - I wasn't really able to judge consensus one way or the other
> regarding the deep vs shallow nesting of cover letters, so I still
> have the change to shallow nesting of cover letters part of this
> series. If we continue to be split on this one (or if we favor the
> current status quo) I'm happy to drop the first patch and adapt the
> last patch to use deep nesting of cover letters instead.
> - Hopefully fix some confusion by saying "shallow/deep threading of
> cover letters".
> - Fix some more instances where we recommend deep threading of cover
> letters.
> - Link to v2: https://patch.msgid.link/20260603-pks-b4-v2-0-a8aea0aa2c23@pks.im
>
> Changes in v2:
> - Reorder commits so that the b4 docs are added first.
> - Add a section that highlights how to configure b4, and that points
> out that the per-project defaults can be overridden via Git
> configuration.
> - Add a patch to MyFirstContribution that recommends shallow
> threading. I mostly intend this to be a discussion starter so that
> the `.b4-config` file matches our preferred threading style.
> - Fix a typo.
> - Link to v1: https://patch.msgid.link/20260602-pks-b4-v1-0-a7ae5a49e9cf@pks.im
>
> Thanks!
>
> Patrick
>
> [1]: <xmqqik81xpqx.fsf@gitster.g>
>
> ---
> Patrick Steinhardt (3):
> MyFirstContribution: recommend shallow threading of cover letters
> MyFirstContribution: recommend the use of b4
> b4: introduce configuration for the Git project
>
> .b4-config | 6 ++
> .b4-cover-template | 11 ++++
> Documentation/MyFirstContribution.adoc | 100 ++++++++++++++++++++++++++++++---
> Documentation/SubmittingPatches | 6 +-
> 4 files changed, 114 insertions(+), 9 deletions(-)
>
> Range-diff versus v3:
>
> 1: 1aec56f76c = 1: b6b488e6a8 MyFirstContribution: recommend shallow threading of cover letters
> 2: f2036769bd = 2: 1a68b993d2 MyFirstContribution: recommend the use of b4
> 3: fb522c7d90 ! 3: 5bc8fba96a b4: introduce configuration for the Git project
> @@ Metadata
> ## Commit message ##
> b4: introduce configuration for the Git project
>
> - We're about to extend our documentation to recommend b4 for sending
> - patch series to the mailing list. Prepare for this by introducing a b4
> - configuration so that the tool knows to honor our preferences. For now,
> - this configuration does two things:
> + In the preceding commit we have extended our documentation to recommend
> + b4 for sending patch series to the mailing list. Introduce configuration
> + so that it knows to honor preferences of the Git project by default. For
> + now, this configuration does two things:
>
> - It configures "send-same-thread = shallow", which tells b4 to always
> send subsequent versions of the same patch series as a reply to the
No further comments based on the range-diff.
--
Cheers,
Toon
^ permalink raw reply
* Re: [PATCH v2 0/7] setup: drop global state
From: Toon Claes @ 2026-06-16 6:42 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: Justin Tobler, git
In-Reply-To: <aivsoM9Qwv0m_P1c@pks.im>
Patrick Steinhardt <ps@pks.im> writes:
> There's only a single change to a commit message I've queued, so I'll
> for now not send another iteration.
Yeah, not worth a reroll.
--
Cheers,
Toon
^ permalink raw reply
* Re: [PATCH v2 3/3] replay: offer an option to linearize the commit topology
From: Toon Claes @ 2026-06-16 7:09 UTC (permalink / raw)
To: Elijah Newren; +Cc: git, Johannes Schindelin
In-Reply-To: <CABPp-BGRi2obnqRGEY9pSMyvRbNGs8AdVUpZmr0C6vZSgHb=cg@mail.gmail.com>
Elijah Newren <newren@gmail.com> writes:
> Hi,
>
> On Wed, Jun 10, 2026 at 7:51 AM Toon Claes <toon@iotcl.com> wrote:
>>
>> From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
>>
>> One of the stated goals of git-replay(1) is to allow implementing the
>> git-rebase(1) functionality on the server side.
>>
>> The default mode of git-rebase(1) is to act as if `--no-rebase-merges`
>> was given. This mode drops merge commits instead of replaying them, and
>> linearizes the commit history into a sequence of the
>> regular (single-parent) commits.
>>
>> Add option `--linearize` to git-replay(1) to do the same.
>
> I think this version is nicer overall than the one from my
> replay-upstream branch; sorry for repeatedly getting distracted from
> that, but this does look nice.
Dscho gets most of the credit here. And don't worry about being
distracted, we know how things go around here. I appreciate the review!
>
> A few small comments:
>
>> Co-authored-by: Toon Claes <toon@iotcl.com>
>> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
>> Signed-off-by: Toon Claes <toon@iotcl.com>
>> ---
>> Documentation/git-replay.adoc | 5 +++++
>> builtin/replay.c | 4 ++++
>> replay.c | 30 +++++++++++++++++++++++-------
>> replay.h | 5 +++++
>> t/t3650-replay-basics.sh | 26 ++++++++++++++++++++++++++
>> 5 files changed, 63 insertions(+), 7 deletions(-)
>>
>> diff --git a/Documentation/git-replay.adoc b/Documentation/git-replay.adoc
>> index a32f72aead..41c96c7061 100644
>> --- a/Documentation/git-replay.adoc
>> +++ b/Documentation/git-replay.adoc
>> @@ -88,6 +88,11 @@ incompatible with `--contained` (which is a modifier for `--onto` only).
>> +
>> The default mode can be configured via the `replay.refAction` configuration variable.
>>
>> +--linearize::
>> + In this mode, `git replay` imitates `git rebase --no-rebase-merges`,
>> + i.e. it cherry-picks only non-merge commits, each one on top of the
>> + previous one.
>
> The SYNOPSIS block at the top of the file is missing this new flag.
>
> The replay_usage[] variable in cmd_replay is also missing this new flag.
>
>> <revision-range>::
>> Range of commits to replay; see "Specifying Ranges" in
>> linkgit:git-rev-parse[1]. In `--advance=<branch>` or
>> diff --git a/builtin/replay.c b/builtin/replay.c
>> index 39e3a86f6c..fedfe46dc6 100644
>> --- a/builtin/replay.c
>> +++ b/builtin/replay.c
>> @@ -111,6 +111,8 @@ int cmd_replay(int argc,
>> N_("mode"),
>> N_("control ref update behavior (update|print)"),
>> PARSE_OPT_NONEG),
>> + OPT_BOOL(0, "linearize", &opts.linearize,
>> + N_("ignore merge commits instead of replaying them")),
>
> "ignore" feels a bit ambiguous to me. Can we use "drop" instead,
> matching your commit message?
Agreed, I don't like it too. "drop" sounds better.
>> OPT_END()
>> };
>>
>> @@ -132,6 +134,8 @@ int cmd_replay(int argc,
>> opts.contained, "--contained");
>> die_for_incompatible_opt2(!!opts.ref, "--ref",
>> !!opts.contained, "--contained");
>> + die_for_incompatible_opt2(!!opts.revert, "--revert",
>> + opts.linearize, "--linearize");
>
> Sensible; should the docs mention this incompatibility? (I'm not sure
> myself; just throwing it out as food for thought.)
Let's add it.
>>
>> /* Parse ref action mode from command line or config */
>> ref_mode = get_ref_action_mode(repo, ref_action);
>> diff --git a/replay.c b/replay.c
>> index 7921d7dba3..81033fb889 100644
>> --- a/replay.c
>> +++ b/replay.c
>> @@ -277,12 +277,16 @@ static struct commit *pick_regular_commit(struct repository *repo,
>> struct commit *onto,
>> struct merge_options *merge_opt,
>> struct merge_result *result,
>> + struct commit *replayed_base,
>> bool reverse,
>> enum replay_empty_commit_action empty)
>> {
>> - struct commit *base, *replayed_base;
>> + struct commit *base;
>> struct tree *pickme_tree, *base_tree, *replayed_base_tree;
>>
>> + if (replayed_base && reverse)
>> + BUG("Linearizing commits is not supported when replaying in reverse");
>> +
>
> This is dead code given the die_for_incompatible_opt2 check above,
> right? Just extra defense in depth?
We also have another defense-in-depth for --onto/--advance/--revert:
BUG("expected one of onto_name, *advance_name, or *revert_name");
I don't mind having it for --linearize too.
>> if (pickme->parents) {
>> base = pickme->parents->item;
>> base_tree = repo_get_commit_tree(repo, base);
>> @@ -291,7 +295,8 @@ static struct commit *pick_regular_commit(struct repository *repo,
>> base_tree = lookup_tree(repo, repo->hash_algo->empty_tree);
>> }
>>
>> - replayed_base = get_mapped_commit(replayed_commits, base, onto);
>> + if (!replayed_base)
>> + replayed_base = get_mapped_commit(replayed_commits, base, onto);
>> replayed_base_tree = repo_get_commit_tree(repo, replayed_base);
>> pickme_tree = repo_get_commit_tree(repo, pickme);
>>
>> @@ -430,12 +435,23 @@ int replay_revisions(struct rev_info *revs,
>> while ((commit = get_revision(revs))) {
>> const struct name_decoration *decoration;
>>
>> - if (commit->parents && commit->parents->next)
>> - die(_("replaying merge commits is not supported yet!"));
>> + if (commit->parents && commit->parents->next) {
>> + if (!opts->linearize)
>> + die(_("replaying merge commits is not supported yet!"));
>> + /*
>> + * When linearizing, a merge commit itself is not picked,
>> + * but refs that point to it might need updating.
>> + */
>
> Is it worth pointing out that last_commit is intentionally not updated
> by this code path? That is implied by your comment, but it takes a
> bit of reasoning to get there, and I think it might help future
> readers to just explicitly state it.
Ah yes, I didn't realize that, but you make a good point. I'll rephrase
the comment a bit.
>> + } else {
>> + struct commit *to_pick = reverse ? last_commit : onto;
>> + last_commit =
>> + pick_regular_commit(revs->repo, commit,
>> + replayed_commits, to_pick,
>> + &merge_opt, &result,
>> + opts->linearize ? last_commit : NULL,
>> + reverse, opts->empty);
>> + }
>>
>> - last_commit = pick_regular_commit(revs->repo, commit, replayed_commits,
>> - reverse ? last_commit : onto,
>> - &merge_opt, &result, reverse, opts->empty);
>> if (!last_commit)
>> break;
>>
>> diff --git a/replay.h b/replay.h
>> index 1851a07705..07e6fdcca3 100644
>> --- a/replay.h
>> +++ b/replay.h
>> @@ -62,6 +62,11 @@ struct replay_revisions_options {
>> * Defaults to REPLAY_EMPTY_COMMIT_DROP.
>> */
>> enum replay_empty_commit_action empty;
>> +
>> + /*
>> + * Whether to linearize the commits (i.e. drop merge commits).
>> + */
>> + int linearize;
>> };
>>
>> /* This struct is used as an out-parameter by `replay_revisions()`. */
>> diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh
>> index 3353bc4a4d..64e0731188 100755
>> --- a/t/t3650-replay-basics.sh
>> +++ b/t/t3650-replay-basics.sh
>> @@ -565,4 +565,30 @@ test_expect_success '--onto with --ref rejects multiple revision ranges' '
>> test_grep "cannot be used with multiple revision ranges" err
>> '
>>
>> +test_expect_success 'replay merge commit fails' '
>> + echo "fatal: replaying merge commits is not supported yet!" >expect &&
>> + test_must_fail git replay --ref-action=print --onto main I..P 2>actual &&
>> + test_cmp expect actual
>> +'
>> +
>> +test_expect_success 'replay to rebase merge commit with --linearize' '
>> + git replay --ref-action=print --linearize --onto main I..topic-with-merge >result &&
>> +
>> + test_line_count = 1 result &&
>> +
>> + git log --format=%s $(cut -f 3 -d " " result) >actual &&
>> + test_write_lines O N J M L B A >expect &&
>> + test_cmp expect actual
>> +'
>> +
>> +test_expect_success 'replay to rebase merge commit with --linearize down to root commit' '
>> + git replay --ref-action=print --linearize --onto main A..topic-with-merge >result &&
>
> You'd need to drop "A.." to have it go down to the root commit, as
> Junio mentioned elsewhere.
Yes, thanks for double confirmation.
>> +
>> + test_line_count = 1 result &&
>> +
>> + git log --format=%s $(cut -f 3 -d " " result) >actual &&
>> + test_write_lines O N J I M L B A >expect &&
>> + test_cmp expect actual
>> +'
>> +
>> test_done
>
> Should there also be a testcase combining --linearize and --advance?
Sure.
> Should there be a test with the incompatibility of --revert &
> --linearize? I think we have a few other tests for incompatible
> options.
I was already about to add that.
> One additional testing idea, borrowed from an older variant of
> this patch I had sitting in a local branch (dscho's original
> linearize patch, adapted): in addition to checking specific commit
> subjects, it's worth verifying that the linearized chain produces
> the *same patches* as the original. Something along the lines of:
>
> test_expect_success '--linearize preserves patches' '
> test_when_finished "git update-ref -d refs/heads/merge_I_L" &&
> test_tick &&
> git checkout -b merge_I_L I &&
> git merge --no-edit L &&
>
> git replay --linearize --onto A B..merge_I_L &&
>
> # range-diff ignores merges, so the original
> # {I, L, merge} reduces to {I, L} on the LHS,
> # and the replayed chain on the RHS should match.
> git range-diff B..merge_I_L@{1} B..merge_I_L >out &&
> ! test_grep -v "=" out &&
>
> git log --oneline A..merge_I_L >out &&
> test_line_count = 2 out
> '
>
> The range-diff check is nice because it asserts patch equivalence
> rather than tying the test to a particular replay ordering, which
> makes the test less brittle if the rev-walk order ever changes.
> Feel free to take, adapt, or ignore.
Interesting idea and I like it. Lemme add it.
> Anyway, thanks for working on this; looking good.
Thanks!
--
Cheers,
Toon
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox