]> git.ipfire.org Git - thirdparty/git.git/log
thirdparty/git.git
10 months agobuiltin/remote: rework how remote refs get renamed
Patrick Steinhardt [Thu, 31 Jul 2025 14:56:53 +0000 (16:56 +0200)] 
builtin/remote: rework how remote refs get renamed

It was recently reported [1] that renaming a remote that has dangling
symrefs is broken. This issue can be trivially reproduced:

    $ git init repo
    Initialized empty Git repository in /tmp/repo/.git/
    $ cd repo/
    $ git remote add origin /dev/null
    $ git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/master
    $ git remote rename origin renamed
    $ git symbolic-ref refs/remotes/origin/HEAD
    refs/remotes/origin/master
    $ git symbolic-ref refs/remotes/renamed/HEAD
    fatal: ref refs/remotes/renamed/HEAD is not a symbolic ref

As one can see, the "HEAD" reference did not get renamed but stays in
the same place. There are two issues here:

  - We use `refs_resolve_ref_unsafe()` to resolve references, but we
    don't pass the `RESOLVE_REF_NO_RECURSE` flag. Consequently, if the
    reference does not resolve, the function will fail and we thus
    ignore this branch.

  - We use `refs_for_each_ref()` to iterate through the old remote's
    references, but that function ignores broken references.

Both of these issues are easy to fix. But having a closer look at the
logic that renames remote references surfaces that it leaves a lot to be
desired overall.

The problem is that we're using O(|refs| + |symrefs| * 2) many reference
transactions to perform the renames. We first delete all symrefs, then
individually rename every direct reference and finally we recreate the
symrefs. On the one hand this isn't even remotely an atomic operation,
so if we hit any error we'll already have deleted all references.

But more importantly it is also extremely inefficient. The number of
transactions for symrefs doesn't really bother us too much, as there
should generally only be a single symref anyway ("HEAD"). But the
renames are very expensive:

  - For the "reftable" backend we perform auto-compaction after every
    single rename, which does add up.

  - For the "files" backend we potentially have to rewrite the
    "packed-refs" file on every single rename in case they are packed.
    The consequence here is quadratic runtime performance. Renaming a
    100k references takes hours to complete.

Refactor the code to use a single transaction to perform all the
reference updates atomically, which speeds up the transaction quite
significantly:

    Benchmark 1: rename remote (refformat = files, revision = HEAD~)
      Time (mean ± σ):     238.770 s ± 13.857 s    [User: 91.473 s, System: 143.793 s]
      Range (min … max):   204.863 s … 247.699 s    10 runs

    Benchmark 2: rename remote (refformat = files, revision = HEAD)
      Time (mean ± σ):      2.103 s ±  0.036 s    [User: 0.360 s, System: 1.313 s]
      Range (min … max):    2.011 s …  2.141 s    10 runs

    Summary
      rename remote (refformat = files, revision = HEAD) ran
      113.53 ± 6.87 times faster than rename remote (refformat = files, revision = HEAD~)

For the "reftable" backend we see a significant speedup, as well, but
given that we don't have quadratic runtime behaviour there it's way less
extreme:

    Benchmark 1: rename remote (refformat = reftable, revision = HEAD~)
      Time (mean ± σ):      8.604 s ±  0.539 s    [User: 4.985 s, System: 2.368 s]
      Range (min … max):    7.880 s …  9.556 s    10 runs

    Benchmark 2: rename remote (refformat = reftable, revision = HEAD)
      Time (mean ± σ):      1.177 s ±  0.103 s    [User: 0.446 s, System: 0.270 s]
      Range (min … max):    1.023 s …  1.410 s    10 runs

    Summary
      rename remote (refformat = reftable, revision = HEAD) ran
        7.31 ± 0.79 times faster than rename remote (refformat = reftable, revision = HEAD~)

There is one issue though with using atomic transactions: when nesting a
remote into itself it can happen that renamed references conflict with
the old referencse. For example, when we have a reference
"refs/remotes/origin/foo" and we rename "origin" to "origin/foo", then
we'll end up with an F/D conflict when we try to create the renamed
reference "refs/remotes/origin/foo/foo".

This situation is overall quite unlikely to happen: people tend to not
use nested remotes, and if they do they must at the same time also have
a conflicting refname. But the end result would be that the old remote
references stay intact whereas all the other parts of the repository
have been adjusted for the new remote name.

Address this by queueing and preparing the reference update before we
touch any other part of the repository. Like this we can make sure that
the reference update will go through before rewriting the configuration.
Otherwise, if the transaction fails to prepare we can gracefully abort
the whole operation without any changes having been performed in the
repository yet. Furthermore, we can detect the conflict and print some
helpful advice for how the user can resolve this situation. So overall,
the tradeoff is that:

  - Reference transactions are now all-or-nothing. This is a significant
    improvement over the previous state where we may have ended up with
    partially-renamed references.

  - Rewriting references is now significantly faster.

  - We only rewrite the configuration in case we know that all
    references can be updated.

  - But we may refuse to rename a remote in case references conflict.

Overall this seems like an acceptable tradeoff.

While at it, fix the handling of symbolic/broken references by using
`refs_for_each_rawref()`. Add tests that cover both this reported issue
and tests that exercise nesting of remotes.

One thing to note: with this change we cannot provide a proper progress
monitor anymore as we queue the references into the transactions as we
iterate through them. Consequently, as we don't know yet how many refs
there are in total, we cannot report how many percent of the operation
is done anymore. But that's a small price to pay considering that you
now shouldn't need the progress monitor in most situations at all
anymore.

[1]: <CANrWfmQWa=RJnm7d3C7ogRX6Tth2eeuGwvwrNmzS2gr+eP0OpA@mail.gmail.com>

Reported-by: Han Jiang <jhcarl0814@gmail.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agobuiltin/remote: determine whether refs need renaming early on
Patrick Steinhardt [Thu, 31 Jul 2025 14:56:52 +0000 (16:56 +0200)] 
builtin/remote: determine whether refs need renaming early on

When renaming a remote we may have to also rename remote refs in case
the refspec changes. Pull out this computation into a separate loop.
While that seems nonsensical right now, it'll help us in a subsequent
commit where we will prepare the reference transaction before we rewrite
the configuration.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agobuiltin/remote: fix sign comparison warnings
Patrick Steinhardt [Thu, 31 Jul 2025 14:56:51 +0000 (16:56 +0200)] 
builtin/remote: fix sign comparison warnings

Fix -Wsign-comparison warnings. All of the warnings we have are about
mismatches in signedness for loop counters. These are trivially fixable
by using the correct integer type.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agorefs: simplify logic when migrating reflog entries
Patrick Steinhardt [Thu, 31 Jul 2025 14:56:50 +0000 (16:56 +0200)] 
refs: simplify logic when migrating reflog entries

When migrating reflog entries between two storage formats we have to do
so via two callback-driven functions:

  - `migrate_one_reflog()` gets invoked via `refs_for_each_reflog()` to
    first list all available reflogs.

  - `migrate_one_reflog_entry()` gets invoked via
    `refs_for_each_reflog_ent()` in `migrate_one_reflog()`.

Before the preceding commit we didn't have the refname available in
`migrate_one_reflog_entry()`, which made it necessary to have a separate
structure that we pass to the second callback so that we can propagate
the refname. Now that `refs_for_each_reflog_ent()` knows to pass the
refname to the callback though that indirection isn't necessary anymore.

There's one catch though: we do have an update index that is also stored
in the entry-specific callback data. This update index is required so
that we can tell the ref backend in which order it should persist the
reflog entries to disk.

But that purpose can be trivially achieved by just converting it into a
global counter that is used for all reflog entries, regardless of which
reference they are for. The ordering will remain the same as both the
update index and the refname is considered when sorting the entries.

Move the index into `struct migration_data` and drop the now-unused
`struct reflog_migration_data` to simplify the code a bit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agorefs: pass refname when invoking reflog entry callback
Patrick Steinhardt [Thu, 31 Jul 2025 14:56:49 +0000 (16:56 +0200)] 
refs: pass refname when invoking reflog entry callback

With `refs_for_each_reflog_ent()` callers can iterate through all the
reflog entries for a given reference. The callback that is being invoked
for each such entry does not receive the name of the reference that we
are currently iterating through. This isn't really a limiting factor, as
callers can simply pass the name via the callback data.

But this layout sometimes does make for a bit of an awkward calling
pattern. One example: when iterating through all reflogs, and for each
reflog we iterate through all refnames, we have to do some extra book
keeping to track which reference name we are currently yielding reflog
entries for.

Change the signature of the callback function so that the reference name
of the reflog gets passed through to it. Adapt callers accordingly and
start using the new parameter in trivial cases. The next commit will
refactor the reference migration logic to make use of this parameter so
that we can simplify its logic a bit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoMerge branch 'ps/reflog-migrate-fixes' into ps/remote-rename-fix
Junio C Hamano [Wed, 6 Aug 2025 14:41:57 +0000 (07:41 -0700)] 
Merge branch 'ps/reflog-migrate-fixes' into ps/remote-rename-fix

* ps/reflog-migrate-fixes:
  refs: fix invalid old object IDs when migrating reflogs
  refs: stop unsetting REF_HAVE_OLD for log-only updates
  refs/files: detect race when generating reflog entry for HEAD
  refs: fix identity for migrated reflogs
  ident: fix type of string length parameter
  builtin/reflog: implement subcommand to write new entries
  refs: export `ref_transaction_update_reflog()`
  builtin/reflog: improve grouping of subcommands
  Documentation/git-reflog: convert to use synopsis type

10 months agorebase -i: permit 'drop' of a merge commit
Johannes Sixt [Wed, 6 Aug 2025 17:38:35 +0000 (19:38 +0200)] 
rebase -i: permit 'drop' of a merge commit

4c063c82e9 (rebase -i: improve error message when picking merge,
2024-05-30) added advice texts for cases when a merge commit is
passed as argument of sequencer command that cannot operate with
a merge commit. However, it forgot about the 'drop' command, so
that in this case the BUG() in the default branch is reached.

Handle 'drop' like 'merge', i.e., permit it without a message.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agorefs: fix invalid old object IDs when migrating reflogs
Patrick Steinhardt [Wed, 6 Aug 2025 05:54:20 +0000 (07:54 +0200)] 
refs: fix invalid old object IDs when migrating reflogs

When migrating reflog entries between different storage formats we end
up with invalid old object IDs for the migrated entries: instead of
writing the old object ID of the to-be-migrated entry, we end up with
the all-zeroes object ID.

The root cause of this issue is that we don't know to use the old object
ID provided by the caller. Instead, we manually resolve the old object
ID by resolving the current value of its matching reference. But as that
reference does not yet exist in the target ref storage we always end up
resolving it to all-zeroes.

This issue got unnoticed as there is no user-facing command that would
even show the old object ID. While `git log -g` knows to show the new
object ID, we don't have any formatting directive to show the old object
ID.

Fix the bug by introducing a new flag `REF_LOG_USE_PROVIDED_OIDS`. If
set, backends are instructed to use the old and new object IDs provided
by the caller, without doing any manual resolving. Set this flag in
`ref_transaction_update_reflog()`.

Amend our tests in t1460-refs-migrate to use our test tool to read
reflog entries. This test tool prints out both old and new object ID of
each reflog entry, which fixes the test gap. Furthermore it also prints
the full identity used to write the reflog, which provides test coverage
for the previous commit in this patch series that fixed the identity for
migrated reflogs.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agorefs: stop unsetting REF_HAVE_OLD for log-only updates
Patrick Steinhardt [Wed, 6 Aug 2025 05:54:19 +0000 (07:54 +0200)] 
refs: stop unsetting REF_HAVE_OLD for log-only updates

The `REF_HAVE_OLD` flag indicates whether a given ref update has its old
object ID set. If so, the value of that field is used to verify whether
the current state of the reference matches this expected state. It is
thus an important part of mitigating races with a concurrent process
that updates the same set of references.

When writing reflogs though we explicitly unset that flag. This is a
sensible thing to do: the old state of reflog entry updates may not
necessarily match the current on-disk state of its accompanying ref, but
it's only intended to signal what old object ID we want to write into
the new reflog entry. For example when migrating refs we end up writing
many reflog entries for a single reference, and most likely those reflog
entries will have many different old object IDs.

But unsetting this flag also removes a useful signal, namely that the
caller _did_ provide an old object ID for a given reflog entry. This
signal will become useful in a subsequent commit, where we add a new
flag that tells the transaction to use the provided old and new object
IDs to write a reflog entry. The `REF_HAVE_OLD` flag is then used as a
signal to verify that the caller really did provide an old object ID.

Stop unsetting the flag so that we can use it as this described signal
in a subsequent commit. Skip checking the old object ID for log-only
updates so that we don't expect it to match the current on-disk state.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agorefs/files: detect race when generating reflog entry for HEAD
Patrick Steinhardt [Wed, 6 Aug 2025 05:54:18 +0000 (07:54 +0200)] 
refs/files: detect race when generating reflog entry for HEAD

When updating a reference that is being pointed to HEAD we don't only
write a reflog message for that particular reference, but also generate
one for HEAD. This logic is handled by `split_head_update()`, where we:

  1. Verify that the condition actually triggered. This is done by
     reading HEAD at the start of the transaction so that we can then
     check whether a given reference update refers to its target.

  2. Queue a new log-only update for HEAD in case it did.

But the logic is unfortunately not free of races, as we do not lock the
HEAD reference after we have read its target. This can lead to the
following two scenarios:

  - HEAD gets concurrently updated to point to one of the references we
    have already processed. This causes us not writing a reflog message
    even though we should have done so.

  - HEAD gets concurrently updated to no longer point to a reference
    anymore that we have already processed. This causes us to write a
    reflog message even though we should _not_ have done so.

Improve the situation by introducing a new `REF_LOG_VIA_SPLIT` flag that
is specific to the "files" backend. If set, we will double check that
the HEAD reference still points to the reference that we are creating
the reflog entry for after we have locked HEAD. Furthermore, instead of
manually resolving the old object ID of that entry, we now use the same
old state as for the parent update.

If we detect such a racy update we abort the transaction. This is a bit
heavy-handed: the user didn't even ask us to write a reflog update for
"HEAD", so it might be surprising if we abort the transaction. That
being said:

  - Normal users wouldn't typically hit this case as we only hit the
    relevant code when committing to a branch that is being pointed to
    by "HEAD" directly. Commands like git-commit(1) typically commit to
    "HEAD" itself though.

  - Scripted users that use git-update-ref(1) and related plumbing
    commands are unlikely to hit this case either, as they would have to
    update the pointed-to-branch at the same as "HEAD" is being updated,
    which is an exceedingly rare event.

The alternative would be to instead drop the log-only update completely,
but that would require more logic that is hard to verify without adding
infrastructure specific for such a test. So we rather do the pragmatic
thing and don't worry too much about an edge case that is very unlikely
to happen.

Unfortunately, this change only helps with the second race. We cannot
reliably plug the first race without locking the HEAD reference at the
start of the transaction. Locking HEAD unconditionally would effectively
serialize all writes though, and that doesn't seem like an option. Also,
double checking its value at the end of the transaction is not an option
either, as its target may have flip-flopped during the transaction.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agorefs: fix identity for migrated reflogs
Patrick Steinhardt [Wed, 6 Aug 2025 05:54:17 +0000 (07:54 +0200)] 
refs: fix identity for migrated reflogs

When migrating reflog entries between different storage formats we must
reconstruct the identity of reflog entries. This is done by passing the
committer passed to the `migrate_one_reflog_entry()` callback function
to `fmt_ident()`.

This results in an invalid identity though: `fmt_ident()` expects the
caller to provide both name and mail of the author, but we pass the full
identity as mail. This leads to an identity like:

    pks <Patrick Steinhardt ps@pks.im>

Fix the bug by splitting the identity line first. This allows us to
extract both the name and mail so that we can pass them to `fmt_ident()`
separately.

This commit does not yet add any tests as there is another bug in the
reflog migration that will be fixed in a subsequent commit. Once that
bug is fixed we'll make the reflog verification in t1450 stricter, and
that will catch both this bug here and the other bug.

Note that we also add two new `name` and `mail` string buffers to the
callback structures and splice them through to the callbacks. This is
done so that we can avoid allocating a new buffer every time we compute
the committer information.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoident: fix type of string length parameter
Patrick Steinhardt [Wed, 6 Aug 2025 05:54:16 +0000 (07:54 +0200)] 
ident: fix type of string length parameter

The last parameter in `split_ident_line()` is the length of the line
passed in by the caller. As such, most callers pass in either the result
of `strlen()`, `struct strbuf::len` or a pointer diff, all of which
are expected to be positive numbers. Regardless of that, the function
accepts a signed integer, which is somewhat confusing.

Fix the function signature to instead accept a `size_t`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agobuiltin/reflog: implement subcommand to write new entries
Patrick Steinhardt [Wed, 6 Aug 2025 05:54:15 +0000 (07:54 +0200)] 
builtin/reflog: implement subcommand to write new entries

While we provide a couple of subcommands in git-reflog(1) to remove
reflog entries, we don't provide any to write new entries. Obviously
this is not an operation that really would be needed for many use cases
out there, or otherwise people would have complained that such a command
does not exist yet. But the introduction of the "reftable" backend
changes the picture a bit, as it is now basically impossible to manually
append a reflog entry if one wanted to do so due to the binary format.

Plug this gap by introducing a simple "write" subcommand. For now, all
this command does is to append a single new reflog entry with the given
object IDs and message to the reflog. More specifically, it is not yet
possible to:

  - Write multiple reflog entries at once.

  - Insert reflog entries at arbitrary indices.

  - Specify the date of the reflog entry.

  - Insert reflog entries that refer to nonexistent objects.

If required, those features can be added at a future point in time. For
now though, the new command aims to fulfill the most basic use cases
while being as strict as possible when it comes to verifying parameters.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agorefs: export `ref_transaction_update_reflog()`
Patrick Steinhardt [Wed, 6 Aug 2025 05:54:14 +0000 (07:54 +0200)] 
refs: export `ref_transaction_update_reflog()`

In a subsequent commit we'll add another user that wants to write reflog
entries. This requires them to call `ref_transaction_update_reflog()`,
but that function is local to "refs.c".

Export the function to prepare for the change. While at it, drop the
`flags` field, as all callers are for now expected to use the same flags
anyway.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agobuiltin/reflog: improve grouping of subcommands
Patrick Steinhardt [Wed, 6 Aug 2025 05:54:13 +0000 (07:54 +0200)] 
builtin/reflog: improve grouping of subcommands

The way subcommands of git-reflog(1) are laid out does not make any
immediate sense. Reorder them such that read-only subcommands precede
writing commands for a bit more structure.

Furthermore, move the "expire" subcommand last. This prepares for a
subsequent change where we are about to introduce a new "write" command
to append reflog entries. Like this, the writing subcommands are ordered
such that those affecting a single reflog come before those spanning
across all reflogs.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoDocumentation/git-reflog: convert to use synopsis type
Patrick Steinhardt [Wed, 6 Aug 2025 05:54:12 +0000 (07:54 +0200)] 
Documentation/git-reflog: convert to use synopsis type

With 974cdca345c (doc: introduce a synopsis typesetting, 2024-09-24) we
have introduced a new synopsis type that simplifies the rules for
typesetting a command's synopsis. Convert the git-reflog(1)
documentation to use it.

While at it, convert the list of options to use backticks. This is done
to appease an upcoming new linter that mandates the use of backticks
when using the synopsis type.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoA bit more after -rc0
Junio C Hamano [Tue, 5 Aug 2025 18:53:34 +0000 (11:53 -0700)] 
A bit more after -rc0

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoMerge branch 'kj/renamed-submodule'
Junio C Hamano [Tue, 5 Aug 2025 18:53:56 +0000 (11:53 -0700)] 
Merge branch 'kj/renamed-submodule'

The case where a new submodule takes a path where used to be a
completely different subproject is now dealt a bit better than
before.

* kj/renamed-submodule:
  fixup! submodule: skip redundant active entries when pattern covers path
  fixup! submodule: prevent overwriting .gitmodules on path reuse
  submodule: skip redundant active entries when pattern covers path
  submodule: prevent overwriting .gitmodules on path reuse

10 months agoMerge branch 'rs/tighten-alias-help'
Junio C Hamano [Tue, 5 Aug 2025 18:53:55 +0000 (11:53 -0700)] 
Merge branch 'rs/tighten-alias-help'

"git -c alias.foo=bar foo -h baz" reported "'foo' is aliased to
'bar'" and then went on to run "git foo -h baz", which was
unexpected.  Tighten the rule so that alias expansion is reported
only when "-h" is the sole option.

* rs/tighten-alias-help:
  git: show alias info only with lone -h

10 months agoMerge branch 'ps/object-file-wo-the-repository'
Junio C Hamano [Tue, 5 Aug 2025 18:53:55 +0000 (11:53 -0700)] 
Merge branch 'ps/object-file-wo-the-repository'

Reduce implicit assumption and dependence on the_repository in the
object-file subsystem.

* ps/object-file-wo-the-repository:
  object-file: get rid of `the_repository` in index-related functions
  object-file: get rid of `the_repository` in `force_object_loose()`
  object-file: get rid of `the_repository` in `read_loose_object()`
  object-file: get rid of `the_repository` in loose object iterators
  object-file: remove declaration for `for_each_file_in_obj_subdir()`
  object-file: inline `for_each_loose_file_in_objdir_buf()`
  object-file: get rid of `the_repository` when writing objects
  odb: introduce `odb_write_object()`
  loose: write loose objects map via their source
  object-file: get rid of `the_repository` in `finalize_object_file()`
  object-file: get rid of `the_repository` in `loose_object_info()`
  object-file: get rid of `the_repository` when freshening objects
  object-file: inline `check_and_freshen()` functions
  object-file: get rid of `the_repository` in `has_loose_object()`
  object-file: stop using `the_hash_algo`
  object-file: fix -Wsign-compare warnings

10 months agot: add test for git refs list subcommand
Meet Soni [Tue, 5 Aug 2025 09:27:58 +0000 (14:57 +0530)] 
t: add test for git refs list subcommand

Add a test script, `t/t1461-refs-list.sh`, for the new `git refs list`
command.

This script acts as a simple driver, leveraging the shared test library
created in the preceding commit. It works by overriding the
`$git_for_each_ref` variable to "git refs list" and then sourcing the
shared library (`t/for-each-ref-tests.sh`).

This approach ensures that `git refs list` is tested against the
entire comprehensive test suite of `git for-each-ref`, verifying
that it acts as a compatible drop-in replacement.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Mentored-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agot6300: refactor tests to be shareable
Meet Soni [Tue, 5 Aug 2025 09:27:57 +0000 (14:57 +0530)] 
t6300: refactor tests to be shareable

In preparation for adding tests for the new `git refs list` command,
refactor the existing t6300 test suite to make its logic shareable.

Move the core test logic from `t6300-for-each-ref.sh` into a new
`for-each-ref-tests.sh` file. Inside this new script, replace hardcoded
calls to "git for-each-ref" with the `$git_for_each_ref` variable.

The original `t6300-for-each-ref.sh` script now becomes a simple
"driver". It is responsible for setting the default value of the
variable and then sourcing the test library.

This new structure follows the established pattern used for sharing
tests between `git-blame` and `git-annotate` and prepares the test suite
for the `refs list` tests to be added in a subsequent commit.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Mentored-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agobuiltin/refs: add list subcommand
Meet Soni [Tue, 5 Aug 2025 09:27:56 +0000 (14:57 +0530)] 
builtin/refs: add list subcommand

Git's reference management is distributed across multiple commands. As
part of an ongoing effort to consolidate and modernize reference
handling, introduce a `list` subcommand under the `git refs` umbrella as
a replacement for `git for-each-ref`.

Implement `cmd_refs_list` by having it call the `for_each_ref_core()`
helper function. This helper was factored out of the original
`cmd_for_each_ref` in a preceding commit, allowing both commands to
share the same core logic as independent peers.

Add documentation for the new command. The man page leverages the shared
options file, created in a previous commit, by using the AsciiDoc
`include::` macro to ensure consistency with git-for-each-ref(1).

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Mentored-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agobuiltin/for-each-ref: factor out core logic into a helper
Meet Soni [Tue, 5 Aug 2025 09:27:55 +0000 (14:57 +0530)] 
builtin/for-each-ref: factor out core logic into a helper

The implementation of `git for-each-ref` is monolithic within
`cmd_for_each_ref()`, making it impossible to share its logic with other
commands. To enable code reuse for the upcoming `git refs list`
subcommand, refactor the core logic into a shared helper function.

Introduce a new `for-each-ref.h` header to define the public interface
for this shared logic. It contains the declaration for a new helper
function, `for_each_ref_core()`, and a macro for the common usage
options.

Move the option parsing, filtering, and formatting logic from
`cmd_for_each_ref()` into a new helper function named
`for_each_ref_core()`. This helper is made generic by accepting the
command's usage string as a parameter.

The original `cmd_for_each_ref()` is simplified to a thin wrapper that
is only responsible for defining its specific usage array and calling
the shared helper.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Mentored-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agobuiltin/for-each-ref: align usage string with the man page
Meet Soni [Tue, 5 Aug 2025 09:27:54 +0000 (14:57 +0530)] 
builtin/for-each-ref: align usage string with the man page

Usage string for `git for-each-ref` was out of sync with its official
documentation. The test `t0450-txt-doc-vs-help.sh` was marked as broken
due to this.

Update the usage string to match the documentation. This allows the test
to pass, so remove the corresponding 'known breakage' marker from the
test file.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Mentored-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agodoc: factor out common option
Meet Soni [Tue, 5 Aug 2025 09:27:53 +0000 (14:57 +0530)] 
doc: factor out common option

In preparation for adding documentation for `git refs list`, factor out
the common options from the `git-for-each-ref` man page into a
shareable file `for-each-ref-options.adoc` and update
`git-for-each-ref.adoc` to use an `include::` macro.

This change is a pure refactoring and results in no change to the
final rendered documentation for `for-each-ref`.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Mentored-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agot/unit-tests/clar: fix -Wmaybe-uninitialized with -Og
Denton Liu [Tue, 5 Aug 2025 05:31:16 +0000 (22:31 -0700)] 
t/unit-tests/clar: fix -Wmaybe-uninitialized with -Og

When building with -Og on gcc 15.1.1, the build produces a warning. In
practice, though, this cannot be hit because `exact` acts as a guard and
that variable can only be set after `matchlen` is already initialized

Assign a default value to `matchlen` so that the warning is silenced.

Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoremote: bail early from set_head() if missing remote name
Jeff King [Tue, 5 Aug 2025 05:31:13 +0000 (22:31 -0700)] 
remote: bail early from set_head() if missing remote name

In "git remote set-head", we can take varying numbers of arguments
depending on whether we saw the "-d" or "-a" options. But the first
argument is always the remote name.

The current code is somewhat awkward in that it conditionally handles
the remote name up-front like this:

  if (argc)
     remote = ...from argv[0]...

and then only later decides to bail if we do not have the right number
of arguments for the options we saw.

This makes it hard to figure out if "remote" is always set when it needs
to be. Both for humans, but also for compilers; with -Og, gcc complains
that "remote" can be accessed without being initialized (although this
is not true, as we'd always die with a usage message in that case).

Let's instead enforce the presence of the remote argument up front,
which fixes the compiler warning and is easier to understand. It does
mean duplicating the code to print a usage message, but it's a single
line.

Noticed-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Jeff King <peff@peff.net>
Tested-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoarchive: flush deflate stream until Z_STREAM_END
Justin Tobler [Sat, 2 Aug 2025 22:08:03 +0000 (17:08 -0500)] 
archive: flush deflate stream until Z_STREAM_END

In `archive-zip.c:write_zip_entry()` when using a stream as input for
deflating a file, the call to `git_deflate()` with Z_FINISH always
expects Z_STREAM_END to be returned. Per zlib documentation[1]:

        If the parameter flush is set to Z_FINISH, pending input is
        processed, pending output is flushed and deflate returns with
        Z_STREAM_END if there was enough output space. If deflate
        returns with Z_OK or Z_BUF_ERROR, this function must be called
        again with Z_FINISH and more output space (updated avail_out)
        but no more input data, until it returns with Z_STREAM_END or an
        error. After deflate has returned Z_STREAM_END, the only
        possible operations on the stream are deflateReset or
        deflateEnd.

In scenarios where the output buffer is not large enough to write all
the compressed data, it is perfectly valid for the underlying
`deflate()` to return Z_OK. Thus, expecting a single pass of `deflate()`
here to always return Z_STREAM_END is a bug. Update the code to flush
the deflate stream until Z_STREAM_END is returned.

[1]: https://zlib.net/manual.html

Helped-by: Toon Claes <toon@iotcl.com>
Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoMerge branch 'master' of https://github.com/j6t/git-gui
Junio C Hamano [Mon, 4 Aug 2025 18:45:23 +0000 (11:45 -0700)] 
Merge branch 'master' of https://github.com/j6t/git-gui

* 'master' of https://github.com/j6t/git-gui: (21 commits)
  git-gui: ensure own version of git-gui--askpass is used
  git-gui: Allow Tcl 9.0
  git-gui: use -profile tcl8 on encoding conversions
  git-gui: use -profile tcl8 for file input with Tcl 9
  git-gui: themed.tcl: use full namespace for color
  git-gui: remove EOL translation for gets
  git-gui: honor TCLTK_PATH in git-gui--askpass
  git-gui: retire Git Gui.app
  git-gui: fix dependency of GITGUI_MAIN on generator
  git-gui: remove uname_O in Makefile
  git-gui i18n: Remove the locations within the Bulgarian translation
  git-gui i18n: Update Bulgarian translation (557t)
  git-gui: do not mix -translation binary and -encoding
  git-gui: replace encoding binary with iso8859-1
  git-gui: translation binary defines iso8859-1
  git-gui: assure -eofchar {} on all channels
  git-gui: use /cmd/git-gui.exe for shortcut
  git-gui: Windows tk_getSaveFile is not useful for shortcuts
  git-gui: let nice work on Windows
  git-gui: do not add directories to PATH on Windows
  ...

10 months agoMerge branch 'master' of https://github.com/j6t/gitk
Junio C Hamano [Mon, 4 Aug 2025 18:44:30 +0000 (11:44 -0700)] 
Merge branch 'master' of https://github.com/j6t/gitk

* 'master' of https://github.com/j6t/gitk:
  gitk: Mention globs in description of preference to hide custom refs
  gitk: filter invisible upstream refs from reference list
  gitk: avoid duplicated upstream refs
  gitk i18n: Remove the locations within the Bulgarian translation
  gitk i18n: Update Bulgarian translation (322t)
  gitk: allow Tcl/Tk 9.0+
  gitk: use -profile tcl8 on encoding conversions
  gitk: use -profile tcl8 for file input with Tcl 9
  gitk: Tcl9 doesn't expand ~, use $env(HOME)
  gitk: switch to -translation binary
  gitk: update scrolling for TclTk 8.7+ / TIP 474
  gitk: restore ui colors after cancelling config dialog
  gitk: set config dialog color swatches in one place
  gitk: Add user preference to hide specific references

10 months agoMerge branch 'cb/no-tcl86-on-macos'
Johannes Sixt [Mon, 4 Aug 2025 16:27:03 +0000 (18:27 +0200)] 
Merge branch 'cb/no-tcl86-on-macos'

* cb/no-tcl86-on-macos:
  git-gui: ensure own version of git-gui--askpass is used
  git-gui: honor TCLTK_PATH in git-gui--askpass
  git-gui: retire Git Gui.app
  git-gui: fix dependency of GITGUI_MAIN on generator
  git-gui: remove uname_O in Makefile

10 months agogit-gui: ensure own version of git-gui--askpass is used
Carlo Marcelo Arenas Belón [Thu, 31 Jul 2025 08:06:28 +0000 (01:06 -0700)] 
git-gui: ensure own version of git-gui--askpass is used

When finding a location for the askpass helper, git will be asked
for its exec path, but if that git is not the same that called
git-gui then we might mistakenly point to its helper instead.

Assume that git-gui and the helper are colocated to derive its
path instead.

This is specially useful in macOS where a broken version of that
helper is provided by the system git.

[j6t: move directory to variable to help in-flight topics]

Suggested-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Carlo Marcelo Arenas Belón <carenas@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
10 months agoMerge branch 'docglobs' of github.com:ilyagr/gitk
Johannes Sixt [Mon, 4 Aug 2025 16:20:32 +0000 (18:20 +0200)] 
Merge branch 'docglobs' of github.com:ilyagr/gitk

* 'docglobs' of github.com:ilyagr/gitk:
  gitk: Mention globs in description of preference to hide custom refs

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
10 months agoGit 2.51-rc0 v2.51.0-rc0
Junio C Hamano [Mon, 4 Aug 2025 15:09:37 +0000 (08:09 -0700)] 
Git 2.51-rc0

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoMerge branch 'jc/test-hashmap-is-still-here'
Junio C Hamano [Mon, 4 Aug 2025 15:10:36 +0000 (08:10 -0700)] 
Merge branch 'jc/test-hashmap-is-still-here'

Comment fix.

* jc/test-hashmap-is-still-here:
  test-hashmap: document why it is no longer used but still there

10 months agoMerge branch 'kh/doc-fast-import-historical'
Junio C Hamano [Mon, 4 Aug 2025 15:10:36 +0000 (08:10 -0700)] 
Merge branch 'kh/doc-fast-import-historical'

Doc update.

* kh/doc-fast-import-historical:
  doc: fast-import: contextualize the hardware cost

10 months agoMerge branch 'ms/meson-with-ancient-git-wo-ls-files-dedup'
Junio C Hamano [Mon, 4 Aug 2025 15:10:35 +0000 (08:10 -0700)] 
Merge branch 'ms/meson-with-ancient-git-wo-ls-files-dedup'

Build fix.

* ms/meson-with-ancient-git-wo-ls-files-dedup:
  meson: tolerate errors from git ls-files --deduplicate

10 months agoMerge branch 'jc/doc-release-vs-clear'
Junio C Hamano [Mon, 4 Aug 2025 15:10:35 +0000 (08:10 -0700)] 
Merge branch 'jc/doc-release-vs-clear'

Doc update.

* jc/doc-release-vs-clear:
  CodingGuidelines: clarify that S_release() does not reinitialize

10 months agoMerge branch 'ch/t7450-recursive-clone-test-fix'
Junio C Hamano [Mon, 4 Aug 2025 15:10:34 +0000 (08:10 -0700)] 
Merge branch 'ch/t7450-recursive-clone-test-fix'

Test fix.

* ch/t7450-recursive-clone-test-fix:
  t7450: inspect the correct path a broken code would write to

10 months agoMerge branch 'js/prompt-crlf-fix'
Junio C Hamano [Mon, 4 Aug 2025 15:10:34 +0000 (08:10 -0700)] 
Merge branch 'js/prompt-crlf-fix'

Interactive prompt code did not correctly strip CRLF from the end
of line on Windows.

* js/prompt-crlf-fix:
  interactive: do strip trailing CRLF from input

10 months agoMerge branch 'ps/meson-clar-decls-fix'
Junio C Hamano [Mon, 4 Aug 2025 15:10:34 +0000 (08:10 -0700)] 
Merge branch 'ps/meson-clar-decls-fix'

Build fix.

* ps/meson-clar-decls-fix:
  meson: ensure correct "clar-decls.h" header is used

10 months agoMerge branch 'js/mingw-fixes'
Junio C Hamano [Mon, 4 Aug 2025 15:10:33 +0000 (08:10 -0700)] 
Merge branch 'js/mingw-fixes'

Windows fixes.

* js/mingw-fixes:
  mingw: support Windows Server 2016 again
  mingw_rename: support ReFS on Windows 2022
  mingw: drop Windows 7-specific work-around
  mingw_open_existing: handle directories better

10 months agoMerge branch 'lm/add-p-context'
Junio C Hamano [Mon, 4 Aug 2025 15:10:33 +0000 (08:10 -0700)] 
Merge branch 'lm/add-p-context'

"git add/etc -p" now honor the diff.context configuration variable,
and also they learn to honor the -U<n> command-line option.

* lm/add-p-context:
  add-patch: add diff.context command line overrides
  add-patch: respect diff.context configuration
  t: use test_config in t4055
  t: use test_grep in t3701 and t4055

10 months agoMerge branch 'ps/config-wo-the-repository'
Junio C Hamano [Mon, 4 Aug 2025 15:10:32 +0000 (08:10 -0700)] 
Merge branch 'ps/config-wo-the-repository'

The config API had a set of convenience wrapper functions that
implicitly use the_repository instance; they have been removed and
inlined at the calling sites.

* ps/config-wo-the-repository: (21 commits)
  config: fix sign comparison warnings
  config: move Git config parsing into "environment.c"
  config: remove unused `the_repository` wrappers
  config: drop `git_config_set_multivar()` wrapper
  config: drop `git_config_get_multivar_gently()` wrapper
  config: drop `git_config_set_multivar_in_file_gently()` wrapper
  config: drop `git_config_set_in_file_gently()` wrapper
  config: drop `git_config_set()` wrapper
  config: drop `git_config_set_gently()` wrapper
  config: drop `git_config_set_in_file()` wrapper
  config: drop `git_config_get_bool()` wrapper
  config: drop `git_config_get_ulong()` wrapper
  config: drop `git_config_get_int()` wrapper
  config: drop `git_config_get_string()` wrapper
  config: drop `git_config_get_string()` wrapper
  config: drop `git_config_get_string_multi()` wrapper
  config: drop `git_config_get_value()` wrapper
  config: drop `git_config_get_value()` wrapper
  config: drop `git_config_get()` wrapper
  config: drop `git_config_clear()` wrapper
  ...

10 months agoMerge branch 'kn/for-each-ref-skip-updates'
Junio C Hamano [Mon, 4 Aug 2025 15:10:32 +0000 (08:10 -0700)] 
Merge branch 'kn/for-each-ref-skip-updates'

Code clean-up.

* kn/for-each-ref-skip-updates:
  ref-filter: use REF_ITERATOR_SEEK_SET_PREFIX instead of '1'
  t6302: add test combining '--start-after' with '--exclude'
  for-each-ref: reword the documentation for '--start-after'
  for-each-ref: fix documentation argument ordering
  ref-cache: use 'size_t' instead of int for length

10 months agoMerge branch 'jt/switch-restore-no-longer-experimental'
Junio C Hamano [Mon, 4 Aug 2025 15:10:31 +0000 (08:10 -0700)] 
Merge branch 'jt/switch-restore-no-longer-experimental'

"git switch" and "git restore" are declared to be no longer
experimental.

* jt/switch-restore-no-longer-experimental:
  builtin: unmark git-switch and git-restore as experimental

10 months agoMerge branch 'jb/t7510-gpg-program-path'
Junio C Hamano [Mon, 4 Aug 2025 15:10:31 +0000 (08:10 -0700)] 
Merge branch 'jb/t7510-gpg-program-path'

A new test to ensure that a recent change will keep working.

* jb/t7510-gpg-program-path:
  t7510: use $PWD instead of $(pwd) inside PATH
  t7510: add test cases for non-absolute gpg program

10 months agoMerge branch 'cc/t9350-cleanup'
Junio C Hamano [Mon, 4 Aug 2025 15:10:30 +0000 (08:10 -0700)] 
Merge branch 'cc/t9350-cleanup'

Test clean-up.

* cc/t9350-cleanup:
  t9350: redirect input to only fast-import

10 months agoMerge branch 'hy/blame-simplify-get-commit-info'
Junio C Hamano [Mon, 4 Aug 2025 15:10:30 +0000 (08:10 -0700)] 
Merge branch 'hy/blame-simplify-get-commit-info'

Code simplification.

* hy/blame-simplify-get-commit-info:
  blame: remove parameter detailed in get_commit_info()

10 months agorevert: initialize const value
Jeff King [Mon, 4 Aug 2025 13:00:11 +0000 (09:00 -0400)] 
revert: initialize const value

When building with clang-22 and DEVELOPER=1 mode, this warning causes us
to fail compilation:

  builtin/revert.c:114:13: error: default initialization of an object of type 'const char' leaves the object uninitialized [-Werror,-Wdefault-const-init-var-unsafe]
    114 |         const char sentinel_value;
        |                    ^

The compiler is right that this code is a bit funny. We declare a const
value without an initializer. It cannot be assigned to because of the
const, but without an initializer it has no predictable value. So as a
variable it can never have any useful function, and if we tried to look
at it, we'd get undefined behavior.

But it does have a function. We never use its value, but rather use its
address as a sentinel value for some other variables:

        const char *gpg_sign = &sentinel_value;

...maybe set gpg_sign via parse_options...

if (gpg_sign != &sentinel_value)
...we got a non-default value...

Normally we'd use NULL as a sentinel value for a pointer, but it doesn't
work here because we also want to detect --no-gpg-sign, which is marked
by setting the pointer to NULL. We need a separate "this was not
touched" value, which is what this sentinel variable gives us.

So the code is correct as-is, but the sentinel variable itself is funny
enough that it's understandable for a compiler warning to flag it. Let's
try to appease the compiler.

There are a few possible options:

  1. Instead of a variable, we could just construct an artificial
     sentinel address like "1", "-1", etc. I think these technically
     fall afoul of the C standard (even if we do not access them, even
     constructing invalid pointers is not always allowed). But it's also
     something we do elsewhere, and even happens in some standard
     interfaces (e.g., mmap()'s MMAP_FAILED value). It does involve some
     annoying casts, though.

  2. We can mark it as static. That gives it a definite value, but
     perhaps makes people wonder if the static-ness is important, when
     it's not.

  3. We can just give it a value to shut the compiler up, even though
     nobody cares about that value.

I went with (3) here as the smallest and most obvious change.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agogitk: Mention globs in description of preference to hide custom refs
Ilya Grigoriev [Sun, 3 Aug 2025 04:59:24 +0000 (21:59 -0700)] 
gitk: Mention globs in description of preference to hide custom refs

This clarifies that one has to enter e.g. `jj/keep/*` and not just
`jj/keep`.

Follows up on 2441e19.

Signed-off-by: Ilya Grigoriev <ilyagr@users.noreply.github.com>
10 months agoThe seventeenth batch, just before -rc0
Junio C Hamano [Mon, 4 Aug 2025 01:44:07 +0000 (18:44 -0700)] 
The seventeenth batch, just before -rc0

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoMerge branch 'hl/test-helper-fd-close'
Junio C Hamano [Mon, 4 Aug 2025 01:44:27 +0000 (18:44 -0700)] 
Merge branch 'hl/test-helper-fd-close'

A few file descriptors left unclosed upon program completion in a
few test helper programs are now closed.

* hl/test-helper-fd-close:
  test-delta: close output descriptor after use
  test-delta: use strbufs to hold input files
  test-delta: handle errors with die()
  t/helper/test-truncate: close file descriptor after truncation

10 months agoMerge branch 'ow/rebase-verify-insn-fmt-before-initializing-state'
Junio C Hamano [Mon, 4 Aug 2025 01:44:27 +0000 (18:44 -0700)] 
Merge branch 'ow/rebase-verify-insn-fmt-before-initializing-state'

"git rebase -i" with bogus rebase.instructionFormat configuration
failed to produce the todo file after recording the state files,
leading to confused "git status"; this has been corrected.

* ow/rebase-verify-insn-fmt-before-initializing-state:
  rebase: write script before initializing state

10 months agoMerge branch 'ps/object-store-midx'
Junio C Hamano [Mon, 4 Aug 2025 01:44:26 +0000 (18:44 -0700)] 
Merge branch 'ps/object-store-midx'

Redefine where the multi-pack-index sits in the object subsystem,
which recently was restructured to allow multiple backends that
support a single object source that belongs to one repository.  A
midx does span mulitple "object sources".

* ps/object-store-midx:
  midx: remove now-unused linked list of multi-pack indices
  packfile: stop using linked MIDX list in `get_all_packs()`
  packfile: stop using linked MIDX list in `find_pack_entry()`
  packfile: refactor `get_multi_pack_index()` to work on sources
  midx: stop using linked list when closing MIDX
  packfile: refactor `prepare_packed_git_one()` to work on sources
  midx: start tracking per object database source

10 months agoMerge branch 'kn/for-each-ref-skip'
Junio C Hamano [Mon, 4 Aug 2025 01:44:26 +0000 (18:44 -0700)] 
Merge branch 'kn/for-each-ref-skip'

"git for-each-ref" learns "--start-after" option to help
applications that want to page its output.

* kn/for-each-ref-skip:
  ref-cache: set prefix_state when seeking
  for-each-ref: introduce a '--start-after' option
  ref-filter: remove unnecessary else clause
  refs: selectively set prefix in the seek functions
  ref-cache: remove unused function 'find_ref_entry()'
  refs: expose `ref_iterator` via 'refs.h'

10 months agomingw: support Windows Server 2016 again
Johannes Schindelin [Sun, 3 Aug 2025 21:25:18 +0000 (21:25 +0000)] 
mingw: support Windows Server 2016 again

It was reported to the Git for Windows project that a simple `git init`
fails on Windows Server 2016:

  D:\Dev\test> git init
  error: could not write config file D:/Dev/test/.git/config: Function not implemented
  fatal: could not set 'core.repositoryformatversion' to '0'

According to https://endoflife.date/windows-server, Windows Server 2016
is officially supported for another one-and-a-half years as of time of
writing, so this is not good.

The culprit is the `mingw_rename()` changes that try to use POSIX
semantics when available, but fail to fall back properly on Windows
Server 2016.

This fixes https://github.com/git-for-windows/git/issues/5695.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agomingw_rename: support ReFS on Windows 2022
Johannes Schindelin [Sun, 3 Aug 2025 21:25:17 +0000 (21:25 +0000)] 
mingw_rename: support ReFS on Windows 2022

ReFS is an alternative filesystem to NTFS. On Windows 2022, it seems not
to support the rename operation using POSIX semantics that Git uses on
Windows as of 391bceae4350 (compat/mingw: support POSIX semantics for
atomic renames, 2024-10-27).

However, Windows 2022 reports `ERROR_NOT_SUPPORTED` in this instance.
This is in contrast to `ERROR_INVALID_PARAMETER` (as previous Windows
versions would report that do not support POSIX semantics in renames at
all).

Let's handle both errors the same: by falling back to the best-effort
option, namely to rename without POSIX semantics.

This fixes https://github.com/git-for-windows/git/issues/5427

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agomingw: drop Windows 7-specific work-around
Johannes Schindelin [Sun, 3 Aug 2025 21:25:16 +0000 (21:25 +0000)] 
mingw: drop Windows 7-specific work-around

In ac33519ddfa8 (mingw: restrict file handle inheritance only on Windows
7 and later, 2019-11-22), I introduced code to safe-guard the
defense-in-depth handling that restricts handles' inheritance so that it
would work with Windows 7, too.

Let's revert this patch: Git for Windows dropped supporting Windows 7 (and
Windows 8) directly after Git for Windows v2.46.2. For full details, see
https://gitforwindows.org/requirements#windows-version.

Actually, on second thought: revert only the part that makes this handle
inheritance restriction logic optional and that suggests to open a bug
report if it fails, but keep the fall-back to try again without said
logic: There have been a few false positives over the past few years
(where the warning was triggered e.g. because Defender was still
accessing a file that Git wanted to overwrite), and the fall-back logic
seems to have helped occasionally in such situations.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agomingw_open_existing: handle directories better
Matthias Aßhauer [Sun, 3 Aug 2025 21:25:15 +0000 (21:25 +0000)] 
mingw_open_existing: handle directories better

CreateFileW() requires FILE_FLAG_BACKUP_SEMANTICS to create a directory
handle [1] and errors out with ERROR_ACCESS_DENIED without this flag.
Fall back to accessing Directory handles this way.

[1] https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew#directories

This fixes https://github.com/git-for-windows/git/issues/5068

Signed-off-by: Matthias Aßhauer <mha1993@live.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agodescribe: use prio_queue_replace()
René Scharfe [Sun, 3 Aug 2025 11:49:11 +0000 (13:49 +0200)] 
describe: use prio_queue_replace()

Optimize the sequence get+put to peek+replace to avoid one unnecessary
heap rebalance.

Do that by tracking partial get operations in a prio_queue wrapper,
struct lazy_queue, and using wrapper functions that turn get into peek
and put into replace as needed.  This is simpler than tracking the
state explicitly in the calling code.

We get a nice speedup on top of the previous patch's conversion to
prio_queue:

Benchmark 1: ./git_2.50.1 describe $(git rev-list v2.41.0..v2.47.0)
  Time (mean ± σ):      1.559 s ±  0.002 s    [User: 1.493 s, System: 0.051 s]
  Range (min … max):    1.556 s …  1.563 s    10 runs

Benchmark 2: ./git_describe_pq describe $(git rev-list v2.41.0..v2.47.0)
  Time (mean ± σ):      1.204 s ±  0.001 s    [User: 1.138 s, System: 0.051 s]
  Range (min … max):    1.202 s …  1.205 s    10 runs

Benchmark 3: ./git describe $(git rev-list v2.41.0..v2.47.0)
  Time (mean ± σ):     850.9 ms ±   1.6 ms    [User: 786.6 ms, System: 49.8 ms]
  Range (min … max):   849.1 ms … 854.1 ms    10 runs

Summary
  ./git describe $(git rev-list v2.41.0..v2.47.0) ran
    1.41 ± 0.00 times faster than ./git_describe_pq describe $(git rev-list v2.41.0..v2.47.0)
    1.83 ± 0.00 times faster than ./git_2.50.1 describe $(git rev-list v2.41.0..v2.47.0)

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agodescribe: use prio_queue
René Scharfe [Sun, 3 Aug 2025 11:38:29 +0000 (13:38 +0200)] 
describe: use prio_queue

Replace the use a list-based priority queue whose order is maintained by
commit_list_insert_by_date() with a prio_queue.  This avoids quadratic
worst-case complexity.  And in the somewhat contrived example of
describing the 4751 commits from v2.41.0 to v2.47.0 in one go (to get a
sizable chunk of describe work with minimal ref loading overhead) it's
significantly faster:

Benchmark 1: ./git_2.50.1 describe $(git rev-list v2.41.0..v2.47.0)
  Time (mean ± σ):      1.558 s ±  0.002 s    [User: 1.492 s, System: 0.051 s]
  Range (min … max):    1.557 s …  1.562 s    10 runs

Benchmark 2: ./git describe $(git rev-list v2.41.0..v2.47.0)
  Time (mean ± σ):      1.209 s ±  0.006 s    [User: 1.143 s, System: 0.051 s]
  Range (min … max):    1.201 s …  1.219 s    10 runs

Summary
  ./git describe $(git rev-list v2.41.0..v2.47.0) ran
    1.29 ± 0.01 times faster than ./git_2.50.1 describe $(git rev-list v2.41.0..v2.47.0)

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agotrace2: do not use strbuf_split*()
Junio C Hamano [Thu, 31 Jul 2025 22:54:33 +0000 (15:54 -0700)] 
trace2: do not use strbuf_split*()

tr2_cfg_load_patterns() and tr2_load_env_vars() functions are
functions with very similar structure that each reads an environment
variable, splits its value at the ',' boundaries, and trims the
resulting string pieces into an array of strbufs.

But the code paths that later use these strbufs take no advantage of
the strbuf-ness of the result (they do not benefit from <ptr,len>
representation to avoid having to run strlen(<ptr>), for example).

Simplify the code by teaching these functions to split into a string
list instead; even the trimming comes for free ;-).

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agotrace2: trim_trailing_newline followed by trim is a no-op
Junio C Hamano [Thu, 31 Jul 2025 22:54:32 +0000 (15:54 -0700)] 
trace2: trim_trailing_newline followed by trim is a no-op

strbuf_trim_trailing_newline() removes a LF or a CRLF from the tail
of a string.  If the code plans to call strbuf_trim() immediately
after doing so, the code is better off skipping the EOL trimming in
the first place.  After all, LF/CRLF at the end is a mere special
case of whitespaces at the end of the string, which will be removed
by strbuf_rtrim() anyway.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agosub-process: do not use strbuf_split*()
Junio C Hamano [Thu, 31 Jul 2025 22:54:31 +0000 (15:54 -0700)] 
sub-process: do not use strbuf_split*()

The code to read status from subprocess reads one packet line and
tries to find "status=<foo>".  It is way overkill to split the line
into an array of two strbufs to extract <foo>.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoenvironment: do not use strbuf_split*()
Junio C Hamano [Thu, 31 Jul 2025 22:54:30 +0000 (15:54 -0700)] 
environment: do not use strbuf_split*()

environment.c:get_git_namespace() learns the raw namespace from an
environment variable, splits it at "/", and appends them after
"refs/namespaces/"; the reason why it splits first is so that an
empty string resulting from double slashes can be omitted.

The split pieces do not need to be edited in any way, so an array of
strbufs is a wrong data structure to use.  Instead split into a
string list and use the pieces from there.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoconfig: do not use strbuf_split()
Junio C Hamano [Thu, 31 Jul 2025 22:54:29 +0000 (15:54 -0700)] 
config: do not use strbuf_split()

When parsing an old-style GIT_CONFIG_PARAMETERS environment
variable, the code parses key=value pairs by splitting them at '='
into an array of strbuf's.  As strbuf_split() leaves the delimiter
at the end of the split piece, the code has to manually trim it.

If we split with string_list_split(), that becomes unnecessary.
Retire the use of strbuf_split() from this code path.

Note that the max parameter of string_list_split() is of
an ergonomically iffy design---it specifies the maximum number of
times the function is allowed to split, which means that in order to
split a text into up to 2 pieces, you have to pass 1, not 2.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agonotes: do not use strbuf_split*()
Junio C Hamano [Thu, 31 Jul 2025 22:54:28 +0000 (15:54 -0700)] 
notes: do not use strbuf_split*()

When reading copy instructions from the standard input, the program
reads a line, splits it into tokens at whitespace, and trims each of
the tokens before using.  We no longer need to use strbuf just to be
able to trim, as string_list_split*() family now can trim while
splitting a string.

Retire the use of strbuf_split() from this code path.

Note that this loop is a bit sloppy in that it ensures at least
there are two tokens on each line, but ignores if there are extra
tokens on the line.  Tightening it is outside the scope of this
series.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agomerge-tree: do not use strbuf_split*()
Junio C Hamano [Thu, 31 Jul 2025 22:54:27 +0000 (15:54 -0700)] 
merge-tree: do not use strbuf_split*()

When reading merge instructions from the standard input, the program
reads from the standard input, splits the line into tokens at
whitespace, and trims each of them before using.  We no longer need
to use strbuf just for trimming, as string_list_split*() family can
trim while splitting a string.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoclean: do not use strbuf_split*() [part 2]
Junio C Hamano [Thu, 31 Jul 2025 22:54:26 +0000 (15:54 -0700)] 
clean: do not use strbuf_split*() [part 2]

builtin/clean.c:filter_by_patterns_cmd() interactively reads a line
that has exclude patterns from the user and splits the line into a
list of patterns.  It uses the strbuf_split() so that each split
piece can then trimmed.

There is no need to use strbuf anymore, thanks to the recent
enhancement to string_list_split*() family that allows us to trim
the pieces split into a string_list.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoclean: do not pass the whole structure when it is not necessary
Junio C Hamano [Sun, 3 Aug 2025 05:42:29 +0000 (22:42 -0700)] 
clean: do not pass the whole structure when it is not necessary

The callee parse_choice() only needs to access a NUL-terminated
string; instead of insisting to take a pointer to a strbuf, just
take a pointer to a character array.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoclean: do not use strbuf_split*() [part 1]
Junio C Hamano [Thu, 31 Jul 2025 22:54:25 +0000 (15:54 -0700)] 
clean: do not use strbuf_split*() [part 1]

builtin/clean.c:parse_choice() is fed a single line of input, which
is space or comma separated list of tokens, and a list of menu
items.  It parses the tokens into number ranges (e.g. 1-3 that means
the first three items) or string prefix (e.g. 's' to choose the menu
item "(s)elect") that specify the elements in the menu item list,
and tells the caller which ones are chosen.

For parsing the input string, it uses strbuf_split() to split it
into bunch of strbufs.  Instead use string_list_split_in_place(),
for a few reasons.

 * strbuf_split() is a bad API function to use, that yields an array
   of strbuf that is a bad data structure to use in general.

 * string_list_split_in_place() allows you to split with "comma or
   space"; the current code has to preprocess the input string to
   replace comma with space because strbuf_split() does not allow
   this.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoclean: do not pass strbuf by value
Junio C Hamano [Thu, 31 Jul 2025 22:54:24 +0000 (15:54 -0700)] 
clean: do not pass strbuf by value

When you pass a structure by value, the callee can modify the
contents of the structure that was passed in without having to worry
about changing the structure the caller has.  Passing structure by
value sometimes (but not very often) can be a valid way to give
callee a temporary variable it can freely modify.

But not a structure with members that are pointers, like a strbuf.

builtin/clean.c:list_and_choose() reads a line interactively from
the user, and passes the line (in a strbuf) to parse_choice() by
value, which then munges by replacing ',' with ' ' (to accept both
comma and space separated list of choices).  But because the strbuf
passed by value still shares the underlying character array buf[],
this ends up munging the caller's strbuf contents.

This is a catastrophe waiting to happen.  If the callee causes the
strbuf to be reallocated, the buf[] the caller has will become
dangling, and when the caller does strbuf_release(), it would result
in double-free.

Stop calling the function with misleading call-by-value with strbuf.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agowt-status: avoid strbuf_split*()
Junio C Hamano [Thu, 31 Jul 2025 22:54:23 +0000 (15:54 -0700)] 
wt-status: avoid strbuf_split*()

strbuf is a very good data structure to work with string data
without having to worry about running past the end of the string,
but strbuf_split() is a wrong API and an array of strbuf that the
function produces is a wrong thing to use in general.  You do not
edit these N strings split out of a single strbuf simultaneously.
Often it is much better off to split a string into string_list and
work with the resulting strings.

wt-status.c:abbrev_oid_in_line() takes one line of rebase todo list
(like "pick e813a0200a7121b97fec535f0d0b460b0a33356c title"), and
for instructions that has an object name as the second token on the
line, replace the object name with its unique abbreviation.  After
splitting these tokens out of a single line, no simultaneous edit on
any of these pieces of string that takes advantage of strbuf API
takes place.  The final string is composed with strbuf API, but
these split pieces are merely used as pieces of strings and there is
no need for them to be stored in individual strbuf.

Instead, split the line into a string_list, and compose the final
string using these pieces.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoMerge branch 'jc/string-list-split' into jc/strbuf-split
Junio C Hamano [Sun, 3 Aug 2025 05:36:41 +0000 (22:36 -0700)] 
Merge branch 'jc/string-list-split' into jc/strbuf-split

* jc/string-list-split:
  string-list: split-then-remove-empty can be done while splitting
  string-list: optionally omit empty string pieces in string_list_split*()
  diff: simplify parsing of diff.colormovedws
  string-list: optionally trim string pieces split by string_list_split*()
  string-list: unify string_list_split* functions
  string-list: align string_list_split() with its _in_place() counterpart
  string-list: report programming error with BUG

10 months agostring-list: split-then-remove-empty can be done while splitting
Junio C Hamano [Fri, 1 Aug 2025 22:04:23 +0000 (15:04 -0700)] 
string-list: split-then-remove-empty can be done while splitting

Thanks to the new STRING_LIST_SPLIT_NONEMPTY flag, a common pattern
to split a string into a string list and then remove empty items in
the resulting list is no longer needed.  Instead, just tell the
string_list_split*() to omit empty ones while splitting.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agostring-list: optionally omit empty string pieces in string_list_split*()
Junio C Hamano [Fri, 1 Aug 2025 22:04:22 +0000 (15:04 -0700)] 
string-list: optionally omit empty string pieces in string_list_split*()

Teach the unified split_string() machinery a new flag bit,
STRING_LIST_SPLIT_NONEMPTY, to cause empty split pieces to be
omitted from the resulting string list.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agodiff: simplify parsing of diff.colormovedws
Junio C Hamano [Fri, 1 Aug 2025 22:04:21 +0000 (15:04 -0700)] 
diff: simplify parsing of diff.colormovedws

The code to parse this configuration variable, whose value is a
comma-separated list of known tokens like "ignore-space-change" and
"ignore-all-space", uses string_list_split() to split the value into
pieces, and then places each piece of string in a strbuf to trim,
before comparing the result with the list of known tokens.

Thanks to the previous steps, now string_list_split() can trim the
resulting pieces before it places them in the string list.  Use it
to simplify the code.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agostring-list: optionally trim string pieces split by string_list_split*()
Junio C Hamano [Fri, 1 Aug 2025 22:04:20 +0000 (15:04 -0700)] 
string-list: optionally trim string pieces split by string_list_split*()

Teach the unified split_string() to take an optional "flags" word,
and define the first flag STRING_LIST_SPLIT_TRIM to cause the split
pieces to be trimmed before they are placed in the string list.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agostring-list: unify string_list_split* functions
Junio C Hamano [Fri, 1 Aug 2025 22:04:19 +0000 (15:04 -0700)] 
string-list: unify string_list_split* functions

Thanks to the previous step, the only difference between these two
related functions is that string_list_split() works on a string
without modifying its contents (i.e. taking "const char *") and the
resulting pieces of strings are their own copies in a string list,
while string_list_split_in_place() works on a mutable string and the
resulting pieces of strings come from the original string.

Consolidate their implementations into a single helper function, and
make them a thin wrapper around it.  We can later add an extra flags
parameter to extend both of these functions by updating only the
internal helper function.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agostring-list: align string_list_split() with its _in_place() counterpart
Junio C Hamano [Fri, 1 Aug 2025 22:04:18 +0000 (15:04 -0700)] 
string-list: align string_list_split() with its _in_place() counterpart

The string_list_split_in_place() function was updated by 52acddf3
(string-list: multi-delimiter `string_list_split_in_place()`,
2023-04-24) to take more than one delimiter characters, hoping that
we can later use it to replace our uses of strtok().  We however did
not make a matching change to the string_list_split() function,
which is very similar.

Before giving both functions more features in future commits, allow
string_list_split() to also take more than one delimiter characters
to make them closer to each other.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoMerge branch 'strip-post-hooks' of github.com:orgads/git-gui
Johannes Sixt [Sat, 2 Aug 2025 12:45:19 +0000 (14:45 +0200)] 
Merge branch 'strip-post-hooks' of github.com:orgads/git-gui

* 'strip-post-hooks' of github.com:orgads/git-gui:
  git-gui: strip the commit message after running commit-msg hook

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
10 months agoMerge branch 'ml/tcl90'
Johannes Sixt [Sat, 2 Aug 2025 12:43:25 +0000 (14:43 +0200)] 
Merge branch 'ml/tcl90'

* ml/tcl90:
  git-gui: Allow Tcl 9.0
  git-gui: use -profile tcl8 on encoding conversions
  git-gui: use -profile tcl8 for file input with Tcl 9
  git-gui: themed.tcl: use full namespace for color
  git-gui: remove EOL translation for gets
  git-gui: do not mix -translation binary and -encoding
  git-gui: replace encoding binary with iso8859-1
  git-gui: translation binary defines iso8859-1
  git-gui: assure -eofchar {} on all channels

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
10 months agoMerge branch 'master' of https://github.com/alshopov/git-gui
Johannes Sixt [Sat, 2 Aug 2025 12:41:48 +0000 (14:41 +0200)] 
Merge branch 'master' of https://github.com/alshopov/git-gui

* 'master' of https://github.com/alshopov/git-gui:
  git-gui i18n: Remove the locations within the Bulgarian translation
  git-gui i18n: Update Bulgarian translation (557t)

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
10 months agostring-list: report programming error with BUG
Junio C Hamano [Fri, 1 Aug 2025 22:04:17 +0000 (15:04 -0700)] 
string-list: report programming error with BUG

Passing a string list that has .strdup_strings bit unset to
string_list_split(), or one that has .strdup_strings bit set to
string_list_split_in_place(), is a programmer error.  Do not use
die() to abort the execution.  Use BUG() instead.

As a developer-facing message, the message string itself should
be a lot more concise, but let's keep the original one for now.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoThe sixteenth batch
Junio C Hamano [Fri, 1 Aug 2025 18:26:46 +0000 (11:26 -0700)] 
The sixteenth batch

Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoMerge branch 'sk/reftable-clarify-tests'
Junio C Hamano [Fri, 1 Aug 2025 18:27:14 +0000 (11:27 -0700)] 
Merge branch 'sk/reftable-clarify-tests'

The reftable unit tests are now ported to the "clar" unit testing
framework.

* sk/reftable-clarify-tests:
  t/unit-tests: finalize migration of reftable-related tests
  t/unit-tests: convert reftable stack test to use clar
  t/unit-tests: convert reftable record test to use clar
  t/unit-tests: convert reftable readwrite test to use clar
  t/unit-tests: convert reftable table test to use clar
  t/unit-tests: convert reftable pq test to use clar
  t/unit-tests: convert reftable merged test to use clar
  t/unit-tests: convert reftable block test to use clar
  t/unit-tests: convert reftable basics test to use clar test framework
  t/unit-tests: implement clar specific reftable test helper functions

10 months agoMerge branch 'ly/pull-autostash'
Junio C Hamano [Fri, 1 Aug 2025 18:27:13 +0000 (11:27 -0700)] 
Merge branch 'ly/pull-autostash'

"git pull" learned to pay attention to pull.autostash configuration
variable, which overrides rebase/merge.autostash.

* ly/pull-autostash:
  pull: add pull.autoStash config option

10 months agoMerge branch 'jc/document-test-balloons-in-flight'
Junio C Hamano [Fri, 1 Aug 2025 18:27:13 +0000 (11:27 -0700)] 
Merge branch 'jc/document-test-balloons-in-flight'

To help our developers, document what C99 language features are
being considered for adoption, in addition to what past experiments
have already decided.

* jc/document-test-balloons-in-flight:
  CodingGuidelines: document test balloons in flight

10 months agoMerge branch 'ag/imap-send-list-folders-doc'
Junio C Hamano [Fri, 1 Aug 2025 18:27:12 +0000 (11:27 -0700)] 
Merge branch 'ag/imap-send-list-folders-doc'

Document recently added "git imap-send --list" with an example.

* ag/imap-send-list-folders-doc:
  docs: explain how to use `git imap-send --list` command to get a list of available folders

10 months agoMerge branch 'cb/meson-avoid-broken-macos-pcre2'
Junio C Hamano [Fri, 1 Aug 2025 18:27:12 +0000 (11:27 -0700)] 
Merge branch 'cb/meson-avoid-broken-macos-pcre2'

Build fix for macOS.

* cb/meson-avoid-broken-macos-pcre2:
  meson: work around broken system PCRE2 dependency in macOS

10 months agoMerge branch 'jc/ci-print-test-failures-fix'
Junio C Hamano [Fri, 1 Aug 2025 18:27:12 +0000 (11:27 -0700)] 
Merge branch 'jc/ci-print-test-failures-fix'

CI fix.

* jc/ci-print-test-failures-fix:
  ci: allow github-actions print test failures again

10 months agoMerge branch 'jk/unleak-reflog-expire-entry'
Junio C Hamano [Fri, 1 Aug 2025 18:27:11 +0000 (11:27 -0700)] 
Merge branch 'jk/unleak-reflog-expire-entry'

Leakfix.

* jk/unleak-reflog-expire-entry:
  reflog: close leak of reflog expire entry

10 months agoMerge branch 'jc/do-not-scan-argv-without-parsing'
Junio C Hamano [Fri, 1 Aug 2025 18:27:11 +0000 (11:27 -0700)] 
Merge branch 'jc/do-not-scan-argv-without-parsing'

Update a hard-to-read in-code NEEDSWORK comment.

* jc/do-not-scan-argv-without-parsing:
  rev-list: update a NEEDSWORK comment

10 months agoMerge branch 'jk/revision-no-early-output'
Junio C Hamano [Fri, 1 Aug 2025 18:27:10 +0000 (11:27 -0700)] 
Merge branch 'jk/revision-no-early-output'

Remove unsupported, unused, and unsupportable old option from "git
log".

* jk/revision-no-early-output:
  revision: drop early output option

10 months agoMerge branch 'jc/rev-list-info-cleanup'
Junio C Hamano [Fri, 1 Aug 2025 18:27:10 +0000 (11:27 -0700)] 
Merge branch 'jc/rev-list-info-cleanup'

Move structure definition from unrelated header file to where it
belongs.

* jc/rev-list-info-cleanup:
  rev-list: make "struct rev_list_info" static to the only user

10 months agomeson: tolerate errors from git ls-files --deduplicate
Martin Storsjö [Fri, 1 Aug 2025 16:28:14 +0000 (19:28 +0300)] 
meson: tolerate errors from git ls-files --deduplicate

When using the Meson build system with versions of Git before 2.31,
that does not yet know the `git ls-files --deduplicate` option, one
can observe the following error:

    ../meson.build:697:19: ERROR: Command `/usr/bin/git -C /home/martin/code/git ls-files --deduplicate '*.h' ':!contrib' ':!compat/inet_ntop.c' ':!compat/inet_pton.c' ':!compat/nedmalloc' ':!compat/obstack.*' ':!compat/poll' ':!compat/regex' ':!sha1collisiondetection' ':!sha1dc' ':!t/unit-tests/clar' ':!t/t[0-9][0-9][0-9][0-9]*' ':!xdiff'` failed with status 129.

The failing command is used to find all header files in our code
base, which is required for static analysis.

Static analysis is an entirely optional feature that distributors
typically don't care about, and we already know to skip running the
command when we are not in a Git repository. But we do not handle
the above failure gracefully, even though we could.

Fix this by passing `check: false` to `run_command`, which makes it
tolerate failures. Then check `returncode()` manually to decide
whether to inspect the output.

Signed-off-by: Martin Storsjö <martin@martin.st>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agodoc: fast-import: contextualize the hardware cost
Kristoffer Haugsbakk [Fri, 1 Aug 2025 13:42:25 +0000 (15:42 +0200)] 
doc: fast-import: contextualize the hardware cost

6e411d20440 (Initial draft of fast-import documentation., 2007-02-05)
pointed out how much time a fast-import took on some hardware with a
specific cost.  Let’s further point out that this experiment was done
in 2007.  So modern hardware should have no issues with such a repo.

Also move the parenthetical to the end now that it contains four words.

Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 months agoCodingGuidelines: clarify that S_release() does not reinitialize
Junio C Hamano [Fri, 1 Aug 2025 17:06:55 +0000 (10:06 -0700)] 
CodingGuidelines: clarify that S_release() does not reinitialize

In the section for naming various API functions, the fact that
S_release() only releases the resources without preparing the
structure for immediate reuse becomes only apparent when you
readentries for S_release() and S_clear().

Clarify the description of S_release() a bit to make the entry self
sufficient.

Signed-off-by: Junio C Hamano <gitster@pobox.com>