]> Kevux Git Server - rit/log
rit
6 months agotrim_last_path_component(): avoid hard-coding the directory separator
Karsten Blees [Fri, 9 Jan 2026 20:05:09 +0000 (20:05 +0000)]
trim_last_path_component(): avoid hard-coding the directory separator

Currently, this function hard-codes the directory separator as the
forward slash.

However, on Windows the backslash character is valid, too. And we want
to call this function in the upcoming support for symlinks on Windows
with the symlink targets (which naturally use the canonical directory
separator on Windows, which is _not_ the forward slash).

Prepare that function to be useful also in that context.

Signed-off-by: Karsten Blees <karsten.blees@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 months agostrbuf_readlink(): support link targets that exceed 2*PATH_MAX
Johannes Schindelin [Fri, 9 Jan 2026 20:05:08 +0000 (20:05 +0000)]
strbuf_readlink(): support link targets that exceed 2*PATH_MAX

The `strbuf_readlink()` function refuses to read link targets that
exceed 2*PATH_MAX (even if a sufficient size was specified by the
caller).

The reason that that limit is 2*PATH_MAX instead of PATH_MAX is that
the symlink targets do not need to be normalized. After running
`ln -s a/../a/../a/../a/../b c`, the target of the symlink `c` will not
be normalized to `b` but instead be much longer. As such, symlink
targets' lengths can far exceed PATH_MAX.

They are frequently much longer than 2*PATH_MAX on Windows, which
actually supports paths up to 32,767 characters, but sets PATH_MAX to
260 for backwards compatibility. For full details, see
https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation

Let's just hard-code the limit used by `strbuf_readlink()` to 32,767 and
make it independent of the current platform's PATH_MAX.

Based-on-a-patch-by: Karsten Blees <karsten.blees@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 months agostrbuf_readlink(): avoid calling `readlink()` twice in corner-cases
Karsten Blees [Fri, 9 Jan 2026 20:05:07 +0000 (20:05 +0000)]
strbuf_readlink(): avoid calling `readlink()` twice in corner-cases

The `strbuf_readlink()` function calls `readlink()`` twice if the hint
argument specifies the exact size of the link target (e.g. by passing
stat.st_size as returned by `lstat()`). This is necessary because
`readlink(..., hint) == hint` could mean that the buffer was too small.

Use `hint + 1` as buffer size to prevent this.

Signed-off-by: Karsten Blees <karsten.blees@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 months agoinit: do parse _all_ core.* settings early
Johannes Schindelin [Fri, 9 Jan 2026 20:05:06 +0000 (20:05 +0000)]
init: do parse _all_ core.* settings early

In Git for Windows, `has_symlinks` is set to 0 by default. Therefore, we
need to parse the config setting `core.symlinks` to know if it has been
set to `true`. In `git init`, we must do that before copying the
templates because they might contain symbolic links.

Even if the support for symbolic links on Windows has not made it to
upstream Git yet, we really should make sure that all the `core.*`
settings are parsed before proceeding, as they might very well change
the behavior of `git init` in a way the user intended.

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

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 months agomingw: do resolve symlinks in `getcwd()`
Johannes Schindelin [Fri, 9 Jan 2026 20:05:05 +0000 (20:05 +0000)]
mingw: do resolve symlinks in `getcwd()`

As pointed out in https://github.com/git-for-windows/git/issues/1676,
the `git rev-parse --is-inside-work-tree` command currently fails when
the current directory's path contains symbolic links.

The underlying reason for this bug is that `getcwd()` is supposed to
resolve symbolic links, but our `mingw_getcwd()` implementation did not.

We do have all the building blocks for that, though: the
`GetFinalPathByHandleW()` function will resolve symbolic links. However,
we only called that function if `GetLongPathNameW()` failed, for
historical reasons: the latter function was supported for a long time,
but the former API function was introduced only with Windows Vista, and
we used to support also Windows XP. With that support having been
dropped, we are free to call the symbolic link-resolving function right
away.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 months agoMerge branch 'js/test-symlink-windows' into js/prep-symlink-windows
Junio C Hamano [Wed, 17 Dec 2025 23:20:25 +0000 (08:20 +0900)]
Merge branch 'js/test-symlink-windows' into js/prep-symlink-windows

* js/test-symlink-windows:
  t7800: work around the MSYS path conversion on Windows
  t6423: introduce Windows-specific handling for symlinking to /dev/null
  t1305: skip symlink tests that do not apply to Windows
  t1006: accommodate for symlink support in MSYS2
  t0600: fix incomplete prerequisite for a test case
  t0301: another fix for Windows compatibility
  t0001: handle `diff --no-index` gracefully
  mingw: special-case `open(symlink, O_CREAT | O_EXCL)`
  apply: symbolic links lack a "trustable executable bit"
  t9700: accommodate for Windows paths

6 months agot7800: work around the MSYS path conversion on Windows
Johannes Schindelin [Wed, 17 Dec 2025 14:18:46 +0000 (14:18 +0000)]
t7800: work around the MSYS path conversion on Windows

Git's test suite's relies on Unix shell scripting, which is
understandable, of course, given Git's firm roots (and indeed, ongoing
focus) on Linux.

This fact, combined with Unix shell scripting's natural
habitat -- which is, naturally... *drumroll*... Unix --
often has unintended side effects, where developers expect the test
suite to run in a Unix environment, which is an incorrect assumption.

One instance of this problem can be observed in the 'difftool --dir-diff
handles modified symlinks' test case in `t7800-difftool.sh`, which
assumes that all absolute paths start with a forward slash. That
assumption is incorrect in general, e.g. on Windows, where absolute
paths have many shapes and forms, none of which starts with a forward
slash.

The only saving grace is that this test case is currently not run on
Windows because of the `SYMLINK` prerequisite. However, I am currently
working towards upstreaming symbolic link support from Git for Windows
to upstream Git, which will put a crack into that saving grace.

Let's change that test case so that it does not rely on absolute paths
(which are passed to the "external command" `ls` as parameters and are
therefore part of its output, and which the test case wants to filter
out before verifying that the output is as expected) starting with a
forward slash. Let's instead rely on the much more reliable fact that
`ls` will output the path in a line that ends in a colon, and simply
filter out those lines by matching said colon instead.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 months agot6423: introduce Windows-specific handling for symlinking to /dev/null
Johannes Schindelin [Wed, 17 Dec 2025 14:18:45 +0000 (14:18 +0000)]
t6423: introduce Windows-specific handling for symlinking to /dev/null

The device `/dev/null` does not exist on Windows, it's called `NUL`
there. Calling `ln -s /dev/null my-symlink` in a symlink-enabled MSYS2
Bash will therefore literally link to a file or directory called `null`
that is supposed to be in the current drive's top-level `dev` directory.
Which typically does not exist.

The test, however, really wants the created symbolic link to point to
the NUL device. Let's instead use the `mklink` utility on Windows to
perform that job, and keep using `ln -s /dev/null <target>` on
non-Windows platforms.

While at it, add the missing `SYMLINKS` prereq because this test _still_
would not pass on Windows before support for symbolic links is
upstreamed from Git for Windows.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 months agot1305: skip symlink tests that do not apply to Windows
Johannes Schindelin [Wed, 17 Dec 2025 14:18:44 +0000 (14:18 +0000)]
t1305: skip symlink tests that do not apply to Windows

In Git for Windows, the gitdir is canonicalized so that even when the
gitdir is specified via a symbolic link, the `gitdir:` conditional
include will only match the real directory path.

Unfortunately, t1305 codifies a different behavior in two test cases,
which are hereby skipped on Windows.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 months agot1006: accommodate for symlink support in MSYS2
Johannes Schindelin [Wed, 17 Dec 2025 14:18:43 +0000 (14:18 +0000)]
t1006: accommodate for symlink support in MSYS2

The MSYS2 runtime (which inherits this trait from the Cygwin runtime,
and which is used by Git for Windows' Bash to emulate POSIX
functionality on Windows, the same Bash that is also used to run Git's
test suite on Windows) has a mode where it can create native symbolic
links on Windows.

Naturally, this is a bit of a strange feature, given that Cygwin goes
out of its way to support Unix-like paths even if no Win32 program
understands those, and the symbolic links have to use Win32 paths
instead (which Win32 programs understand very well).

As a consequence, the symbolic link targets get normalized before the
links are created.

This results in certain quirks that Git's test suite is ill equipped to
accommodate (because Git's test suite expects to be able to use
Unix-like paths even on Windows).

The test script t1006-cat-file.sh contains two prime examples, two test
cases that need to skip a couple assertions because they are simply
wrong in the context of Git for Windows.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 months agot0600: fix incomplete prerequisite for a test case
Johannes Schindelin [Wed, 17 Dec 2025 14:18:42 +0000 (14:18 +0000)]
t0600: fix incomplete prerequisite for a test case

The 'symref transaction supports symlinks' test case is guarded by the
`SYMLINK` prerequisite because `core.prefersymlinkrefs = true` requires
symbolic links to be supported.

However, the `preferSymlinkRefs` feature is not supported on Windows,
therefore this test case needs the `MINGW` prerequisite, too.

There's a couple more cases where we set this config key:

  - In a subsequent test in t0600, but there we explicitly set it to
    "false". So this would naturally be supported by Windows.

  - In t7201 we set the value to `yes`, but we never verify that the
    written reference is a symbolic link in the first place. I guess
    that we could rather remove setting the configuration value here, as
    we are about to deprecate support for symrefs via symbolic links in
    the first place. But that's certainly outside of the scope of this
    patch.

  - In t9903 we do the same, but likewise, we don't check whether the
    written file is a symbolic link.

Therefore this seems to be the only instance where the tests actually
need to be adapted.

Helped-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 months agot0301: another fix for Windows compatibility
Johannes Schindelin [Wed, 17 Dec 2025 14:18:41 +0000 (14:18 +0000)]
t0301: another fix for Windows compatibility

Just like 0fdcfa2f9f5 (t0301: fixes for windows compatibility,
2021-09-14) explained, we should not call `mkdir -m<mode>` in the test
suite because that would fail on Windows.

There was one forgotten instance of this which was hidden by a `SYMLINK`
prerequisite. Currently, this prevents this test case from being
executed on Windows, but with the upcoming support for symbolic links,
it would become a problem.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 months agot0001: handle `diff --no-index` gracefully
Johannes Schindelin [Wed, 17 Dec 2025 14:18:40 +0000 (14:18 +0000)]
t0001: handle `diff --no-index` gracefully

The test case 're-init to move gitdir symlink' wants to compare the
contents of `newdir/.git`, which is a symbolic link pointing to a file.
However, `git diff --no-index`, which is used by `test_cmp` on Windows,
does not resolve symlinks; It shows the symlink _target_ instead (with a
file mode of 120000). That is totally unexpected by the test case, which
as a consequence fails, meaning that it's a bug in the test case itself.

Co-authored-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 months agomingw: special-case `open(symlink, O_CREAT | O_EXCL)`
Johannes Schindelin [Wed, 17 Dec 2025 14:18:39 +0000 (14:18 +0000)]
mingw: special-case `open(symlink, O_CREAT | O_EXCL)`

The `_wopen()` function would gladly follow a symbolic link to a
non-existent file and create it when given above-mentioned flags.

Git expects the `open()` call to fail, though. So let's add yet another
work-around to pretend that Windows behaves according to POSIX, see:
https://pubs.opengroup.org/onlinepubs/007904875/functions/open.html#:~:text=If%20O_CREAT%20and%20O_EXCL%20are,set%2C%20the%20result%20is%20undefined.

This is required to let t4115.8(--reject removes .rej symlink if it
exists) pass on Windows when enabling the MSYS2 runtime's symbolic link
support.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 months agoapply: symbolic links lack a "trustable executable bit"
Johannes Schindelin [Wed, 17 Dec 2025 14:18:38 +0000 (14:18 +0000)]
apply: symbolic links lack a "trustable executable bit"

When 0482c32c334b (apply: ignore working tree filemode when
!core.filemode, 2023-12-26) fixed `git apply` to stop warning about
executable files, it inadvertently changed the code flow also for
symbolic links and directories.

Let's narrow the scope of the special `!trust_executable_git` code path
to apply only to regular files.

This is needed to let t4115.5(symlink escape when creating new files)
pass on Windows when symbolic link support is enabled in the MSYS2
runtime.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 months agot9700: accommodate for Windows paths
Johannes Schindelin [Wed, 17 Dec 2025 14:18:37 +0000 (14:18 +0000)]
t9700: accommodate for Windows paths

Ever since fe53bbc9beb (Git.pm: Always set Repository to absolute path
if autodetecting, 2009-05-07), the t9700 test _must_ fail on Windows
because of that age-old Unix paths vs Windows paths problem.

The underlying root cause is that Git cannot run with a regular Win32
variant of Perl, the assumption that every path is a Unix path is just
too strong in Git's Perl code.

As a consequence, Git for Windows is basically stuck with using the
MSYS2 variant of Perl which uses a POSIX emulation layer (which is a
friendly fork of Cygwin) _and_ a best-effort Unix <-> Windows paths
conversion whenever crossing the boundary between MSYS2 and regular
Win32 processes. It is best effort only, though, using heuristics to
automagically convert correctly in most cases, but not in all cases.

In the context of this here patch, this means that asking `git.exe` for
the absolute path of the `.git/` directory will return a Win32 path
because `git.exe` is a regular Win32 executable that has no idea about
Unix-ish paths. But above-mentioned commit introduced a test that wants
to verify that this path is identical to the one that the Git Perl
module reports (which refuses to use Win32 paths and uses Unix-ish paths
instead). Obviously, this must fail because no heuristics can kick in at
that layer.

This test failure has not even been caught when Git introduced Windows
support in its CI definition in 2e90484eb4a (ci: add a Windows job to
the Azure Pipelines definition, 2019-01-29), as all tests relying on
Perl had to be disabled even from the start (because the CI runs would
otherwise have resulted in prohibitively long runtimes, not because
Windows is super slow per se, but because Git's test suite keeps
insisting on using technology that requires a POSIX emulation layer,
which _is_ super slow on Windows).

To work around this failure, let's use the `cygpath` utility to convert
the absolute `gitdir` path into the form that the Perl code expects.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 months agoThe ninth batch
Junio C Hamano [Tue, 16 Dec 2025 02:08:23 +0000 (11:08 +0900)]
The ninth batch

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 months agoMerge branch 'rs/ban-mktemp'
Junio C Hamano [Tue, 16 Dec 2025 02:08:34 +0000 (11:08 +0900)]
Merge branch 'rs/ban-mktemp'

Rewrite the only use of "mktemp()" that is subject to TOCTOU race
and Stop using the insecure "mktemp()" function.

* rs/ban-mktemp:
  compat: remove gitmkdtemp()
  banned.h: ban mktemp(3)
  compat: remove mingw_mktemp()
  compat: use git_mkdtemp()
  wrapper: add git_mkdtemp()

6 months agoMerge branch 'gf/win32-pthread-cond-init'
Junio C Hamano [Tue, 16 Dec 2025 02:08:34 +0000 (11:08 +0900)]
Merge branch 'gf/win32-pthread-cond-init'

Emulation code clean-up.

* gf/win32-pthread-cond-init:
  win32: pthread_cond_init should return a value

6 months agoMerge branch 'ps/object-read-stream'
Junio C Hamano [Tue, 16 Dec 2025 02:08:34 +0000 (11:08 +0900)]
Merge branch 'ps/object-read-stream'

The "git_istream" abstraction has been revamped to make it easier
to interface with pluggable object database design.

* ps/object-read-stream:
  streaming: drop redundant type and size pointers
  streaming: move into object database subsystem
  streaming: refactor interface to be object-database-centric
  streaming: move logic to read packed objects streams into backend
  streaming: move logic to read loose objects streams into backend
  streaming: make the `odb_read_stream` definition public
  streaming: get rid of `the_repository`
  streaming: rely on object sources to create object stream
  packfile: introduce function to read object info from a store
  streaming: move zlib stream into backends
  streaming: create structure for filtered object streams
  streaming: create structure for packed object streams
  streaming: create structure for loose object streams
  streaming: create structure for in-core object streams
  streaming: allocate stream inside the backend-specific logic
  streaming: explicitly pass packfile info when streaming a packed object
  streaming: propagate final object type via the stream
  streaming: drop the `open()` callback function
  streaming: rename `git_istream` into `odb_read_stream`

7 months agoThe eighth batch
Junio C Hamano [Sun, 14 Dec 2025 08:04:17 +0000 (17:04 +0900)]
The eighth batch

Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoMerge branch 'je/doc-data-model'
Junio C Hamano [Sun, 14 Dec 2025 08:04:38 +0000 (17:04 +0900)]
Merge branch 'je/doc-data-model'

Docfix.

* je/doc-data-model:
  doc: remove stray text in Git data model

7 months agoMerge branch 'lo/repo-struct-z'
Junio C Hamano [Sun, 14 Dec 2025 08:04:37 +0000 (17:04 +0900)]
Merge branch 'lo/repo-struct-z'

"git repo struct" learned to take "-z" as a synonym to "--format=nul".

* lo/repo-struct-z:
  repo: add -z as an alias for --format=nul to git-repo-structure
  repo: use [--format=... | -z] instead of [-z] in git-repo-info synopsis
  repo: remove blank line from Documentation/git-repo.adoc

7 months agoMerge branch 'kh/advise-w-git-help-in-branch'
Junio C Hamano [Sun, 14 Dec 2025 08:04:37 +0000 (17:04 +0900)]
Merge branch 'kh/advise-w-git-help-in-branch'

A help message from "git branch" now mentions "git help" instead of
"man" when suggesting to read some documentation.

* kh/advise-w-git-help-in-branch:
  branch: advice using git-help(1) instead of man(1)

7 months agoMerge branch 'je/doc-pull'
Junio C Hamano [Sun, 14 Dec 2025 08:04:37 +0000 (17:04 +0900)]
Merge branch 'je/doc-pull'

Doc fixup.

* je/doc-pull:
  doc: git-pull: fix 'git --rebase abort' typo

7 months agoMerge branch 'tc/meson-cross-compile-fix'
Junio C Hamano [Sun, 14 Dec 2025 08:04:37 +0000 (17:04 +0900)]
Merge branch 'tc/meson-cross-compile-fix'

Build fix.

* tc/meson-cross-compile-fix:
  meson: use is_cross_build() where possible
  meson: only detect ICONV_OMITS_BOM if possible
  meson: ignore subprojects/.wraplock

7 months agoMerge branch 'js/last-modified-with-sparse-checkouts'
Junio C Hamano [Sun, 14 Dec 2025 08:04:36 +0000 (17:04 +0900)]
Merge branch 'js/last-modified-with-sparse-checkouts'

"git last-modified" used to mishandle "--" to mark the beginning of
pathspec, which has been corrected.

* js/last-modified-with-sparse-checkouts:
  last-modified: support sparse checkouts

7 months agoMerge branch 'rs/diff-index-find-copies-harder-optim'
Junio C Hamano [Sun, 14 Dec 2025 08:04:36 +0000 (17:04 +0900)]
Merge branch 'rs/diff-index-find-copies-harder-optim'

Halve the memory consumed by artificial filepairs created during
"git diff --find-copioes-harder", also making the operation run
faster.

* rs/diff-index-find-copies-harder-optim:
  diff-index: don't queue unchanged filepairs with diff_change()

7 months agoMerge branch 'tc/last-modified-active-paths-optimization'
Junio C Hamano [Sun, 14 Dec 2025 08:04:36 +0000 (17:04 +0900)]
Merge branch 'tc/last-modified-active-paths-optimization'

Recent optimization to "last-modified" command introduced use of
uninitialized block of memory, which has been corrected.

* tc/last-modified-active-paths-optimization:
  last-modified: fix use of uninitialized memory

7 months agoThe seventh batch
Junio C Hamano [Mon, 8 Dec 2025 22:53:51 +0000 (07:53 +0900)]
The seventh batch

Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoMerge branch 'en/replay-doc-revision-range'
Junio C Hamano [Mon, 8 Dec 2025 22:54:56 +0000 (07:54 +0900)]
Merge branch 'en/replay-doc-revision-range'

The use of "revision" (a connected set of commits) has been
clarified in the "git replay" documentation.

* en/replay-doc-revision-range:
  Documentation/git-replay.adoc: fix errors around revision range

7 months agoMerge branch 'yc/xdiff-patience-optim'
Junio C Hamano [Mon, 8 Dec 2025 22:54:55 +0000 (07:54 +0900)]
Merge branch 'yc/xdiff-patience-optim'

The way patience diff finds LCS has been optimized.

* yc/xdiff-patience-optim:
  xdiff: optimize patience diff's LCS search

7 months agoMerge branch 'bc/zsh-testsuite'
Junio C Hamano [Mon, 8 Dec 2025 22:54:54 +0000 (07:54 +0900)]
Merge branch 'bc/zsh-testsuite'

A few tests have been updated to work under the shell compatible
mode of zsh.

* bc/zsh-testsuite:
  t5564: fix test hang under zsh's sh mode
  t0614: use numerical comparison with test_line_count

7 months agoMerge branch 'pw/replay-exclude-gpgsig-fix'
Junio C Hamano [Mon, 8 Dec 2025 22:54:53 +0000 (07:54 +0900)]
Merge branch 'pw/replay-exclude-gpgsig-fix'

"git replay" forgot to omit the "gpgsig-sha256" extended header
from the resulting commit the same way it omits "gpgsig", which has
been corrected.

* pw/replay-exclude-gpgsig-fix:
  replay: do not copy "gpgsign-sha256" header

7 months agocompat: remove gitmkdtemp()
René Scharfe [Sat, 6 Dec 2025 13:35:39 +0000 (14:35 +0100)]
compat: remove gitmkdtemp()

gitmkdtemp() has become a trivial wrapper around git_mkdtemp().  Remove
this now unnecessary layer of indirection.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agobanned.h: ban mktemp(3)
René Scharfe [Sat, 6 Dec 2025 13:29:43 +0000 (14:29 +0100)]
banned.h: ban mktemp(3)

Older versions of mktemp(3) generate easily guessable file names.  The
function checks if the generated name is used, which is unreliable, as
a file with that name might then be created by some other process before
we can do it ourselves.  The function was dropped from POSIX due to its
security problems.  Forbid its use.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agocompat: remove mingw_mktemp()
René Scharfe [Sat, 6 Dec 2025 13:28:26 +0000 (14:28 +0100)]
compat: remove mingw_mktemp()

Remove the mktemp(3) compatibility function now that its last caller was
removed by the previous commit.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agocompat: use git_mkdtemp()
René Scharfe [Sat, 6 Dec 2025 13:27:47 +0000 (14:27 +0100)]
compat: use git_mkdtemp()

A file might appear at the path returned by mktemp(3) before we call
mkdir(2).  Use the more robust git_mkdtemp() instead, which retries a
number of times and doesn't need to call lstat(2).

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agowrapper: add git_mkdtemp()
René Scharfe [Sat, 6 Dec 2025 13:27:39 +0000 (14:27 +0100)]
wrapper: add git_mkdtemp()

Extend git_mkstemps_mode() to optionally call mkdir(2) instead of
open(2), then use that ability to create a mkdtemp(3) replacement,
git_mkdtemp().  We'll start using it in the next commit.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoThe sixth batch
Junio C Hamano [Fri, 5 Dec 2025 05:49:13 +0000 (14:49 +0900)]
The sixth batch

Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoMerge branch 'rs/config-set-multi-error-message-fix'
Junio C Hamano [Fri, 5 Dec 2025 05:49:59 +0000 (14:49 +0900)]
Merge branch 'rs/config-set-multi-error-message-fix'

The error message given by "git config set", when the variable
being updated has more than one values defined, used old style "git
config" syntax with an incorrect option in its hint, both of which
have been corrected.

* rs/config-set-multi-error-message-fix:
  config: fix suggestion for failed set of multi-valued option

7 months agoMerge branch 'rs/config-unset-opthelp-fix'
Junio C Hamano [Fri, 5 Dec 2025 05:49:59 +0000 (14:49 +0900)]
Merge branch 'rs/config-unset-opthelp-fix'

The option help text given by "git config unset -h" described
the "--all" option to "replace", not "unset", multiple variables,
which has been corrected.

* rs/config-unset-opthelp-fix:
  config: fix short help of unset flags

7 months agoMerge branch 'ps/object-source-management'
Junio C Hamano [Fri, 5 Dec 2025 05:49:58 +0000 (14:49 +0900)]
Merge branch 'ps/object-source-management'

Code refactoring around object database sources.

* ps/object-source-management:
  odb: handle recreation of quarantine directories
  odb: handle changing a repository's commondir
  chdir-notify: add function to unregister listeners
  odb: handle initialization of sources in `odb_new()`
  http-push: stop setting up `the_repository` for each reference
  t/helper: stop setting up `the_repository` repeatedly
  builtin/index-pack: fix deferred fsck outside repos
  oidset: introduce `oidset_equal()`
  odb: move logic to disable ref updates into repo
  odb: refactor `odb_clear()` to `odb_free()`
  odb: adopt logic to close object databases
  setup: convert `set_git_dir()` to have file scope
  path: move `enter_repo()` into "setup.c"

7 months agoMerge branch 'cc/fast-import-strip-if-invalid'
Junio C Hamano [Fri, 5 Dec 2025 05:49:58 +0000 (14:49 +0900)]
Merge branch 'cc/fast-import-strip-if-invalid'

"git fast-import" learns "--strip-if-invalid" option to drop
invalid cryptographic signature from objects.

* cc/fast-import-strip-if-invalid:
  fast-import: add 'strip-if-invalid' mode to --signed-commits=<mode>
  commit: refactor verify_commit_buffer()
  fast-import: refactor finalize_commit_buffer()

7 months agoMerge branch 'js/ci-show-breakage-in-dockerized-jobs'
Junio C Hamano [Fri, 5 Dec 2025 05:49:58 +0000 (14:49 +0900)]
Merge branch 'js/ci-show-breakage-in-dockerized-jobs'

Dockerised jobs at the GitHub Actions CI have been taught to show
more details of failed tests.

* js/ci-show-breakage-in-dockerized-jobs:
  ci(dockerized): do show the result of failing tests again

7 months agoMerge branch 'kh/doc-committer-date-is-author-date'
Junio C Hamano [Fri, 5 Dec 2025 05:49:57 +0000 (14:49 +0900)]
Merge branch 'kh/doc-committer-date-is-author-date'

The "--committer-date-is-author-date" option of "git am/rebase" is
a misguided one.  The documentation is updated to discourage its
use.

* kh/doc-committer-date-is-author-date:
  doc: warn against --committer-date-is-author-date

7 months agoMerge branch 'jc/optional-path'
Junio C Hamano [Fri, 5 Dec 2025 05:49:56 +0000 (14:49 +0900)]
Merge branch 'jc/optional-path'

"git config get --path" segfaulted on an ":(optional)path" that
does not exist, which has been corrected.

* jc/optional-path:
  config: really treat missing optional path as not configured
  config: really pretend missing :(optional) value is not there
  config: mark otherwise unused function as file-scope static

7 months agoMerge branch 'js/strip-scalar-too'
Junio C Hamano [Fri, 5 Dec 2025 05:49:56 +0000 (14:49 +0900)]
Merge branch 'js/strip-scalar-too'

"make strip" has been taught to strip "scalar" as well as "git".

* js/strip-scalar-too:
  make strip: include `scalar`

7 months agoMerge branch 'en/xdiff-cleanup-2'
Junio C Hamano [Fri, 5 Dec 2025 05:49:56 +0000 (14:49 +0900)]
Merge branch 'en/xdiff-cleanup-2'

Code clean-up.

* en/xdiff-cleanup-2:
  xdiff: rename rindex -> reference_index
  xdiff: change rindex from long to size_t in xdfile_t
  xdiff: make xdfile_t.nreff a size_t instead of long
  xdiff: make xdfile_t.nrec a size_t instead of long
  xdiff: split xrecord_t.ha into line_hash and minimal_perfect_hash
  xdiff: use unambiguous types in xdl_hash_record()
  xdiff: use size_t for xrecord_t.size
  xdiff: make xrecord_t.ptr a uint8_t instead of char
  xdiff: use ptrdiff_t for dstart/dend
  doc: define unambiguous type mappings across C and Rust

7 months agorepo: add -z as an alias for --format=nul to git-repo-structure
Lucas Seiki Oshiro [Thu, 4 Dec 2025 20:10:12 +0000 (17:10 -0300)]
repo: add -z as an alias for --format=nul to git-repo-structure

Other Git commands that have nul-terminated output, such as git-config,
git-status, git-ls-files, and git-repo-info have a flag `-z` for using
the null character as the record separator.

Add the `-z` flag to git-repo-structure as an alias for `--format=nul`,
making it consistent with the behavior of the other commands.

Signed-off-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agorepo: use [--format=... | -z] instead of [-z] in git-repo-info synopsis
Lucas Seiki Oshiro [Thu, 4 Dec 2025 20:10:11 +0000 (17:10 -0300)]
repo: use [--format=... | -z] instead of [-z] in git-repo-info synopsis

The flag -z is only an alias for --format=null and even though --format
and -z can be used together and repeated, only the last one is
considered.

Replace `[-z]` in the synopsis of git-repo-info by
`[--format=... | -z]`, expliciting that the use of one of those flags
replace the other.

Signed-off-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agorepo: remove blank line from Documentation/git-repo.adoc
Lucas Seiki Oshiro [Thu, 4 Dec 2025 20:10:10 +0000 (17:10 -0300)]
repo: remove blank line from Documentation/git-repo.adoc

There was an extra blank line in git-repo-structure documentation, which
led to an unwawnted '+' character after generating an HTML or PDF from
that page. This can be seen, for example, in Git 2.52.0 online docs [1].

Remove that extra line.

[1] https://git-scm.com/docs/git-repo/2.52.0

Signed-off-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agomeson: use is_cross_build() where possible
Toon Claes [Wed, 3 Dec 2025 14:53:31 +0000 (15:53 +0100)]
meson: use is_cross_build() where possible

In previous commit the first use of meson.can_run_host_binaries() was
introduced. This is a guard around compiler.run() to ensure it's
actually possible to execute the provided.

In other places we've been having the same issue, but here `not
meson.is_cross_build()` is used as guard. This does the trick, but it
also prevents the code from running even when an exe_wrapper is
configured.

Switch to using meson.can_run_host_binaries() here as well.

There is another place left that still uses `not
meson.is_cross_build()`, but here it's a guard around fs.exists(). That
function will always run on the build machine, so checking for
cross-compilation is still in place here.

Signed-off-by: Toon Claes <toon@iotcl.com>
Acked-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agomeson: only detect ICONV_OMITS_BOM if possible
Toon Claes [Tue, 2 Dec 2025 10:48:09 +0000 (11:48 +0100)]
meson: only detect ICONV_OMITS_BOM if possible

In our Meson setup it automatically detects whether ICONV_OMITS_BOM
should be defined. To check this, a piece of code is compiled and ran.

When cross-compiling, it's not possible to run this piece of code. Guard
this test with a can_run_host_binaries() check to ensure it can run.

Signed-off-by: Toon Claes <toon@iotcl.com>
Acked-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agomeson: ignore subprojects/.wraplock
Toon Claes [Tue, 2 Dec 2025 10:48:08 +0000 (11:48 +0100)]
meson: ignore subprojects/.wraplock

When asking Meson to wrap subprojects, it generates a .wraplock file in
the subprojects/ directory. Ignore this file.

See also https://github.com/mesonbuild/meson/issues/14948.

Signed-off-by: Toon Claes <toon@iotcl.com>
Acked-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agolast-modified: support sparse checkouts
Johannes Schindelin [Sat, 29 Nov 2025 13:43:46 +0000 (13:43 +0000)]
last-modified: support sparse checkouts

In a sparse checkout, a user might want to run `last-modified` on a
directory outside the worktree.

And even in non-sparse checkouts, a user might need to run that command
on a directory that does not exist in the worktree.

These use cases should be supported via the `--` separator between
revision and file arguments, which is even advertised in the
documentation. This patch fixes a tiny bug that prevents that from
working.

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

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Acked-by: Derrick Stolee <stolee@gmail.com>
Acked-by: Toon Claes <toon@iotcl.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agodoc: git-pull: fix 'git --rebase abort' typo
Julia Evans [Wed, 3 Dec 2025 15:34:55 +0000 (15:34 +0000)]
doc: git-pull: fix 'git --rebase abort' typo

An earlier commit e9d221b0 (doc: git-pull: clarify how to exit a
conflicted merge, 2025-10-15) misspelt `git rebase --abort` to
`git --rebase abort`.  Fix it.

Signed-off-by: Julia Evans <julia@jvns.ca>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agodoc: remove stray text in Git data model
Julia Evans [Tue, 2 Dec 2025 18:11:24 +0000 (18:11 +0000)]
doc: remove stray text in Git data model

I meant to delete this sentence fragment when rewriting this paragraph,
but accidentally left it in. It's repetitive (since it was meant to be
deleted) and it's causing some formatting issues with the note.

Signed-off-by: Julia Evans <julia@jvns.ca>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agobranch: advice using git-help(1) instead of man(1)
Kristoffer Haugsbakk [Tue, 2 Dec 2025 15:56:51 +0000 (16:56 +0100)]
branch: advice using git-help(1) instead of man(1)

8fbd903e (branch: advise about ref syntax rules, 2024-03-05) added
an advice about checking git-check-ref-format(1) for the ref syntax
rules. The advice uses man(1). But git(1) is a multi-platform tool and
man(1) may not be available on some platforms. It might also be slightly
jarring to see a suggestion for running a command which is not from
the Git suite.

Let’s instead use git-help(1) in order to stay inside the land of
git(1). This also means that `help.format` (for `man`, `html` or other
formats) will be used if set.

Also change to using single quotes (') to quote the command since that
is more conventional.

While here let’s also update the test to use `{SQ}`, which is more
readable and easier to edit.

Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoThe fifth batch
Junio C Hamano [Mon, 1 Dec 2025 02:31:24 +0000 (18:31 -0800)]
The fifth batch

Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoMerge branch 'jk/asan-bonanza'
Junio C Hamano [Mon, 1 Dec 2025 02:31:41 +0000 (18:31 -0800)]
Merge branch 'jk/asan-bonanza'

Various issues detected by Asan have been corrected.

* jk/asan-bonanza:
  t: enable ASan's strict_string_checks option
  fsck: avoid parse_timestamp() on buffer that isn't NUL-terminated
  fsck: remove redundant date timestamp check
  fsck: avoid strcspn() in fsck_ident()
  fsck: assert newline presence in fsck_ident()
  cache-tree: avoid strtol() on non-string buffer
  Makefile: turn on NO_MMAP when building with ASan
  pack-bitmap: handle name-hash lookups in incremental bitmaps
  compat/mmap: mark unused argument in git_munmap()

7 months agoMerge branch 'je/doc-data-model'
Junio C Hamano [Mon, 1 Dec 2025 02:31:40 +0000 (18:31 -0800)]
Merge branch 'je/doc-data-model'

Add a new manual that describes the data model.

* je/doc-data-model:
  doc: add an explanation of Git's data model

7 months agoMerge branch 'jc/whitespace-incomplete-line'
Junio C Hamano [Mon, 1 Dec 2025 02:31:40 +0000 (18:31 -0800)]
Merge branch 'jc/whitespace-incomplete-line'

Both "git apply" and "git diff" learn a new whitespace error class,
"incomplete-line".

* jc/whitespace-incomplete-line:
  attr: enable incomplete-line whitespace error for this project
  diff: highlight and error out on incomplete lines
  apply: check and fix incomplete lines
  whitespace: allocate a few more bits and define WS_INCOMPLETE_LINE
  apply: revamp the parsing of incomplete lines
  diff: update the way rewrite diff handles incomplete lines
  diff: call emit_callback ecbdata everywhere
  diff: refactor output of incomplete line
  diff: keep track of the type of the last line seen
  diff: correct suppress_blank_empty hack
  diff: emit_line_ws_markup() if/else style fix
  whitespace: correct bit assignment comments

7 months agoMerge branch 'ja/doc-synopsis-style'
Junio C Hamano [Mon, 1 Dec 2025 02:31:39 +0000 (18:31 -0800)]
Merge branch 'ja/doc-synopsis-style'

Doc mark-up updates.

* ja/doc-synopsis-style:
  doc: pull-fetch-param typofix
  doc: convert git push to synopsis style
  doc: convert git pull to synopsis style
  doc: convert git fetch to synopsis style

7 months agoMerge branch 'lo/repo-info-all'
Junio C Hamano [Mon, 1 Dec 2025 02:31:39 +0000 (18:31 -0800)]
Merge branch 'lo/repo-info-all'

"git repo info" learned "--all" option.

* lo/repo-info-all:
  repo: add --all to git-repo-info
  repo: factor out field printing to dedicated function

7 months agodiff-index: don't queue unchanged filepairs with diff_change()
René Scharfe [Sun, 30 Nov 2025 11:47:17 +0000 (12:47 +0100)]
diff-index: don't queue unchanged filepairs with diff_change()

diff_cache() queues unchanged filepairs if the flag find_copies_harder
is set, and uses diff_change() for that.  This function allocates a
filespec for each side, does a few other things that are unnecessary for
unchanged filepairs and always sets the diff_flag has_changes, which is
simply misleading in this case.

Add a new streamlined function for queuing unchanged filepairs and
use it in show_modified(), which is called by diff_cache() via
oneway_diff() and do_oneway_diff().  It allocates only a single filespec
for each filepair and uses it twice with reference counting.  This has a
measurable effect if there are a lot of them, like in the Linux repo:

Benchmark 1: ./git_v2.52.0 -C ../linux diff --cached --find-copies-harder
  Time (mean Â± Ïƒ):      31.8 ms Â±   0.2 ms    [User: 24.2 ms, System: 6.3 ms]
  Range (min â€¦ max):    31.5 ms â€¦  32.3 ms    85 runs

Benchmark 2: ./git -C ../linux diff --cached --find-copies-harder
  Time (mean Â± Ïƒ):      23.9 ms Â±   0.2 ms    [User: 18.1 ms, System: 4.6 ms]
  Range (min â€¦ max):    23.5 ms â€¦  24.4 ms    111 runs

Summary
  ./git -C ../linux diff --cached --find-copies-harder ran
    1.33 Â± 0.01 times faster than ./git_v2.52.0 -C ../linux diff --cached --find-copies-harder

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agolast-modified: fix use of uninitialized memory
Toon Claes [Fri, 28 Nov 2025 16:37:13 +0000 (17:37 +0100)]
last-modified: fix use of uninitialized memory

git-last-modified(1) uses a scratch bitmap to keep track of paths that
have been changed between commits. To avoid reallocating a bitmap on
each call of process_parent(), the scratch bitmap is kept and reused.
Although, it seems an incorrect length is passed to memset(3).

`struct bitmap` uses `eword_t` to for internal storage. This type is
typedef'd to uint64_t. To fully zero the memory used by the bitmap,
multiply the length (saved in `struct bitmap::word_alloc`) by the size
of `eword_t`.

Reported-by: Anders Kaseorg <andersk@mit.edu>
Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Toon Claes <toon@iotcl.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoDocumentation/git-replay.adoc: fix errors around revision range
Elijah Newren [Sat, 29 Nov 2025 04:44:24 +0000 (04:44 +0000)]
Documentation/git-replay.adoc: fix errors around revision range

There was significant confusion in the git-replay manual about what
constitutes a revision range.  As noted in f302c1e4aa09 (revisions(7):
clarify that most commands take a single revision range, 2021-05-18):

   Commands that are specifically designed to take two distinct ranges
   (e.g. "git range-diff R1 R2" to compare two ranges) do exist, but they
   are exceptions. Unless otherwise noted, all "git" commands that operate
   on a set of commits work on a single revision range.

`git replay` is not an exception, but a few places in the manual were
written as though it were.  These appear to have come in revisions to
the original series, between v3->v4 (see
https://lore.kernel.org/git/CAP8UFD3bpLrVW97DH7j=V9H2GsTSAkksC9L3QujQERFk_kLnZA@mail.gmail.com/
, "More than one <revision-range> can be passed") and between v6->v7
(https://lore.kernel.org/git/20231115143327.2441397-1-christian.couder@gmail.com/,
"Takes ranges of commits"), and I missed both of these revisions when
reviewing.  Fix them now.

There was also a reference to the "Commit Limiting options below", but
this page has no such section of options; strike the misleading
reference.

It is worth noting that we are documenting existing behavior, rather
than optimal behavior.  Junio has multiple times suggested introducing
alternative ways to walk revisions and use them in `git replay
--advance`, e.g. at
  * https://lore.kernel.org/git/xmqqy1mqo6kv.fsf@gitster.g/
  * https://lore.kernel.org/git/xmqq8rb3is8c.fsf@gitster.g/
  * https://lore.kernel.org/git/xmqqtsydj2zk.fsf@gitster.g/ (item (2))
If/when we introduce some new revision walking flag that implements one
of these alternate types of revision walks, we can update the --advance
option and this manual appropriately.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoxdiff: optimize patience diff's LCS search
Yee Cheng Chin [Thu, 27 Nov 2025 02:16:06 +0000 (02:16 +0000)]
xdiff: optimize patience diff's LCS search

The find_longest_common_sequence() function in patience diff is
inefficient as it calls binary_search() for every unique line it
encounters when deciding where to put it in the sequence. From
instrumentation (using xctrace) on popular repositories, binary_search()
takes up 50-60% of the run time within patience_diff() when performing a
diff.

To optimize this, add a boundary condition check before binary_search()
is called to see if the encountered unique line is located after the
entire currently tracked longest subsequence. If so, skip the
unnecessary binary search and simply append the entry to the end of
sequence. Given that most files compared in a diff are usually quite
similar to each other, this condition is very common, and should be hit
much more frequently than the binary search.

Below are some end-to-end performance results by timing `git log
--shortstat --oneline -500 --patience` on different repositories with
the old and new code. Generally speaking this seems to give at least
8-10% speed up. The "binary search hit %" column describes how often the
algorithm enters the binary search path instead of the new faster path.
Even in the WebKit case we can see that it's quite rare (1.46%).

| Repo     | Speed difference | binary search hit % |
|----------|------------------|---------------------|
| vim      | 1.27x            | 0.01%               |
| pytorch  | 1.16x            | 0.02%               |
| cpython  | 1.14x            | 0.06%               |
| ripgrep  | 1.14x            | 0.03%               |
| git      | 1.13x            | 0.12%               |
| vscode   | 1.09x            | 0.10%               |
| WebKit   | 1.08x            | 1.46%               |

The benchmarks were done using hyperfine, on an Apple M1 Max laptop,
with git compiled with `-O3 -flto`.

Signed-off-by: Yee Cheng Chin <ychin.git@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agot5564: fix test hang under zsh's sh mode
brian m. carlson [Fri, 28 Nov 2025 01:21:06 +0000 (01:21 +0000)]
t5564: fix test hang under zsh's sh mode

This test starts a SOCKS server in Perl in the background and then kills
it after the tests are done.  However, when using zsh (in sh mode) in
the tests, the start_socks function hangs until the background process
is killed.

Note that this does not reproduce in a simple shell script, so there is
likely some interaction between job handling, our heavy use of eval in
the test framework, and possibly other complexities of our test
framework.  What is clear, however, is that switching from a compound
statement to a subshell fixes the problem entirely and the test passes
with no problem, so do that.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agot0614: use numerical comparison with test_line_count
brian m. carlson [Fri, 28 Nov 2025 01:21:05 +0000 (01:21 +0000)]
t0614: use numerical comparison with test_line_count

In this comparison, we want to know whether the number of lines is
greater than 1.  Our test_line_count function passes the first argument
as the comparison operator to test, so what we want is a numerical
comparison, not a string comparison.  While this does not produce a
functional problem now, it could very well if we expected two or more
items, in which case the value "10" would not match when it should.

Furthermore, the "<" and ">" comparisons are new in POSIX 1003.1-2024
and we don't want to require such a new version of POSIX since many
popular and supported operating systems were released before that
version of POSIX was released.

Finally, zsh's builtin test operator does not like the greater-than sign
in "test", since it is only supported in the double-bracket extension.
This has been reported and will be addressed in a future version, but
since our code is also technically incorrect, as well as not very
compatible, let's fix it by using a numeric comparison.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoThe fourth batch
Junio C Hamano [Wed, 26 Nov 2025 18:22:08 +0000 (10:22 -0800)]
The fourth batch

Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoMerge branch 'gf/win32-pthread-cond-wait-err'
Junio C Hamano [Wed, 26 Nov 2025 18:32:43 +0000 (10:32 -0800)]
Merge branch 'gf/win32-pthread-cond-wait-err'

Emulation code clean-up.

* gf/win32-pthread-cond-wait-err:
  win32: return error if SleepConditionVariableCS fails

7 months agoMerge branch 'jk/ci-windows-meson-test-fix'
Junio C Hamano [Wed, 26 Nov 2025 18:32:43 +0000 (10:32 -0800)]
Merge branch 'jk/ci-windows-meson-test-fix'

"Windows+meson" job at the GitHub Actions CI was hard to debug, as
it did not show and save failed test artifacts, which has been
corrected.

* jk/ci-windows-meson-test-fix:
  ci(windows-meson-test): handle options and output like other test jobs
  unit-test: ignore --no-chain-lint

7 months agoMerge branch 'pw/worktree-list-display-width-fix'
Junio C Hamano [Wed, 26 Nov 2025 18:32:42 +0000 (10:32 -0800)]
Merge branch 'pw/worktree-list-display-width-fix'

"git worktree list" attempts to show paths to worktrees while
aligning them, but miscounted display columns for the paths when
non-ASCII characters were involved, which has been corrected.

* pw/worktree-list-display-width-fix:
  worktree list: quote paths
  worktree list: fix column spacing

7 months agoMerge branch 'js/wincred-get-credential-alloc-fix'
Junio C Hamano [Wed, 26 Nov 2025 18:32:42 +0000 (10:32 -0800)]
Merge branch 'js/wincred-get-credential-alloc-fix'

Under-allocation fix.

* js/wincred-get-credential-alloc-fix:
  wincred: avoid memory corruption

7 months agoMerge branch 'js/cmake-libgit-fix'
Junio C Hamano [Wed, 26 Nov 2025 18:32:42 +0000 (10:32 -0800)]
Merge branch 'js/cmake-libgit-fix'

Makefile based build have recently been updated to build a
libgit.a that also has reftable and xdiff objects; CMake based
build procedure has been updated to match.

* js/cmake-libgit-fix:
  cmake: stop trying to build the reftable and xdiff libraries

7 months agoMerge branch 'js/mingw-assign-comma-fix'
Junio C Hamano [Wed, 26 Nov 2025 18:32:41 +0000 (10:32 -0800)]
Merge branch 'js/mingw-assign-comma-fix'

The "return errno = EFOO, -1" construct, which is heavily used in
compat/mingw.c and triggers warnings under "-Wcomma", has been
rewritten to avoid the warnings.

* js/mingw-assign-comma-fix:
  mingw: avoid the comma operator

7 months agoMerge branch 'js/ci-github-setup-go-update'
Junio C Hamano [Wed, 26 Nov 2025 18:32:41 +0000 (10:32 -0800)]
Merge branch 'js/ci-github-setup-go-update'

Update a version of action used at the GitHub Actrions CI.

* js/ci-github-setup-go-update:
  ci: bump actions/setup-go from 5 to 6

7 months agoMerge branch 'jk/test-mktemp-leakfix'
Junio C Hamano [Wed, 26 Nov 2025 18:32:41 +0000 (10:32 -0800)]
Merge branch 'jk/test-mktemp-leakfix'

Test leakfix.

* jk/test-mktemp-leakfix:
  test-mktemp: plug memory and descriptor leaks

7 months agoMerge branch 'rs/xmkstemp-simplify'
Junio C Hamano [Wed, 26 Nov 2025 18:32:40 +0000 (10:32 -0800)]
Merge branch 'rs/xmkstemp-simplify'

Code simplification.

* rs/xmkstemp-simplify:
  wrapper: simplify xmkstemp()

7 months agoMerge branch 'ad/blame-diff-algorithm'
Junio C Hamano [Wed, 26 Nov 2025 18:32:40 +0000 (10:32 -0800)]
Merge branch 'ad/blame-diff-algorithm'

"git blame" learns "--diff-algorithm=<algo>" option.

* ad/blame-diff-algorithm:
  blame: make diff algorithm configurable
  xdiff: add 'minimal' to XDF_DIFF_ALGORITHM_MASK

7 months agoMerge branch 'en/ort-rename-another-fix'
Junio C Hamano [Wed, 26 Nov 2025 18:32:40 +0000 (10:32 -0800)]
Merge branch 'en/ort-rename-another-fix'

Yet another corner case fix around renames in the "ort" merge
strategy.

* en/ort-rename-another-fix:
  merge-ort: fix failing merges in special corner case
  merge-ort: remove debugging crud
  t6429: update comment to mention correct tool

7 months agoci(dockerized): do show the result of failing tests again
Johannes Schindelin [Mon, 17 Nov 2025 17:04:24 +0000 (17:04 +0000)]
ci(dockerized): do show the result of failing tests again

The quality of tests and test suites is most apparent not when
everything passes, but in how quickly bugs can be identified,
analyzed, and resolved after test failures occur.

As such, it is an unfortunate side effect of 2a21098b98a (github: adapt
containerized jobs to be rootless, 2025-01-10) that the output of failed
test cases, which was shown before that change directly in the build
logs, is now no longer shown at all.

The reason is a side effect of trying to run the build and the tests
with permissions other than the `root` user, but without providing the
prerequisite permissions to signal what tests failed and whose output
hence needs to be included in the logs.

The way this signaling works is for the workflow to write into
special-purpose files whose path is specific to the current workflow
step and which can be accessed via the `$GITHUB_ENV` environment
variable, which differs between workflow steps. It is this file that is
missing write permission for the `builder` user that was introduced in
above-mentioned commit.

The solution is simple: make the file world-writable.

Technically, this write permission should be removed after the step has
completed, if proper security practices were to be upheld, but since
nothing uses that file again, it does not matter, and the fix is more
succinct this way.

This commit is best viewed with `--color-words`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
[jc: squashed Elijah's rewrite of the first paragraph of the log message]
[jc: updated chmod to match "world-writable" in the log message]
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoMerge branch 'master' of https://github.com/j6t/gitk
Junio C Hamano [Wed, 26 Nov 2025 17:35:09 +0000 (09:35 -0800)]
Merge branch 'master' of https://github.com/j6t/gitk

* 'master' of https://github.com/j6t/gitk:
  gitk: add external diff file rename detection
  gitk: show unescaped file names on 'rename' and 'copy' lines
  gitk: fix a 'continue' statement outside a loop to 'return'
  gitk: persist position and size of the Tags and Heads window
  Revert "gitk: Only restore window size from ~/.gitk, not position"

7 months agoreplay: do not copy "gpgsign-sha256" header
Phillip Wood [Wed, 26 Nov 2025 14:33:37 +0000 (14:33 +0000)]
replay: do not copy "gpgsign-sha256" header

When "git replay" replays a commit it copies the extended headers
across from the original commit. However, if the original commit
was signed, we do not want to copy the header associated with the
signature is it wont be valid for the new commit. The code already
knows to avoid coping the "gpgsig" header but does not know to avoid
copying the "gpgsig-sha256" header.  Add that header to the list of
exclusions to match what "git commit --amend" does.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agofast-import: add 'strip-if-invalid' mode to --signed-commits=<mode>
Christian Couder [Mon, 17 Nov 2025 04:34:50 +0000 (05:34 +0100)]
fast-import: add 'strip-if-invalid' mode to --signed-commits=<mode>

Tools like `git filter-repo`[1] use `git fast-export` and
`git fast-import` to rewrite repository history. When rewriting
history using one such tool though, commit signatures might become
invalid because the commits they sign changed due to the changes
in the repository history made by the tool between the fast-export
and the fast-import steps.

Note that as far as signature handling goes:

  * Since fast-export doesn't know what changes filter-repo may make
to the stream, it can't know whether the signatures will still be
valid.

  * Since filter-repo doesn't know what history canonicalizations
fast-export performed (and it performs a few), it can't know whether
the signatures will still be valid.

  * Therefore, fast-import is the only process in the pipeline that
can know whether a specified signature remains valid.

Having invalid signatures in a rewritten repository could be
confusing, so users rewritting history might prefer to simply
discard signatures that are invalid at the fast-import step.

For example a common use case is to rewrite only "recent" history.
While specifying commit ranges corresponding to "recent" commits
could work, users worry about getting it wrong and want to just
automatically rewrite everything, expecting older commit signatures
to be untouched.

To let them do that, let's add a new 'strip-if-invalid' mode to the
`--signed-commits=<mode>` option of `git fast-import`.

It would be interesting for the `--signed-tags=<mode>` option to
have this mode too, but we leave that for a future improvement.

It might also be possible for `git fast-export` to have such a mode
in its `--signed-commits=<mode>` and `--signed-tags=<mode>`
options, but the use cases for it are much less clear, so we also
leave that for possible future improvements.

For now let's just die() if 'strip-if-invalid' is passed to these
options where it hasn't been implemented yet.

[1]: https://github.com/newren/git-filter-repo

Helped-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoMerge branch 'tb/external-diff-renamed'
Johannes Sixt [Wed, 26 Nov 2025 15:04:14 +0000 (16:04 +0100)]
Merge branch 'tb/external-diff-renamed'

* tb/external-diff-renamed:
  gitk: add external diff file rename detection

7 months agoMerge branch 'js/persist-ref-window-geometry'
Johannes Sixt [Wed, 26 Nov 2025 15:02:23 +0000 (16:02 +0100)]
Merge branch 'js/persist-ref-window-geometry'

* js/persist-ref-window-geometry:
  gitk: persist position and size of the Tags and Heads window
  Revert "gitk: Only restore window size from ~/.gitk, not position"

7 months agoodb: handle recreation of quarantine directories
Patrick Steinhardt [Wed, 19 Nov 2025 07:51:01 +0000 (08:51 +0100)]
odb: handle recreation of quarantine directories

In the preceding commit we have moved the logic that reparents object
database sources on chdir(3p) from "setup.c" into "odb.c". Let's also do
the same for any temporary quarantine directories so that the complete
reparenting logic is self-contained in "odb.c".

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoodb: handle changing a repository's commondir
Patrick Steinhardt [Wed, 19 Nov 2025 07:51:00 +0000 (08:51 +0100)]
odb: handle changing a repository's commondir

The function `repo_set_gitdir()` is called in two situations:

  - To initialize the repository with its discovered location. As part
    of this we also set up the new object database.

  - To update the repository's discovered location in case the process
    changes its working directory so that we update relative paths. This
    means we also have to update any relative paths that are potentially
    used in the object database.

In the context of the object database we ideally wouldn't ever have to
worry about the second case: if all paths used by our object database
sources were absolute, then we wouldn't have to update them. But
unfortunately, the paths aren't only used to locate files owned by the
given source, but we also use them for reporting purposes. One such
example is `repo_get_object_directory()`, where we cannot just change
semantics to always return absolute paths, as that is likely to break
tooling out there.

One solution to this would be to have both a "display path" and an
"internal path". This would allow us to use internal paths for all
internal matters, but continue to use the potentially-relative display
paths so that we don't break compatibility. But converting the codebase
to honor this split is quite a messy endeavour, and it wouldn't even
help us with the goal to get rid of the need to update the display path
on chdir(3p).

Another solution would be to rework "setup.c" so that we never have to
update paths in the first place. In that case, we'd only initialize the
repository once we have figured out final locations for all directories.
This would be a significant simplification of that subsystem indeed, but
the current logic is so messy that it would take significant investments
to get there.

Meanwhile though, while object sources may still use relative paths, the
best thing we can do is to handle the reparenting of the object source
paths in the object database itself. This can be done by registering one
callback for each object database so that we get notified whenever the
current working directory changes, and we then perform the reparenting
ourselves.

Ideally, this wouldn't even happen on the object database level, but
instead handled by each object database source. But we don't yet have
proper pluggable object database sources, so this will need to be
handled at a later point in time.

The logic itself is rather simple:

  - We register the callback when creating the object database.

  - We unregister the callback when releasing it again.

  - We split up `set_git_dir_1()` so that it becomes possible to skip
    recreating the object database. This is required because the
    function is called both when the current working directory changes,
    but also when we set up the repository. Calling this function
    without skipping creation of the ODB will result in a bug in case
    it's already created.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agochdir-notify: add function to unregister listeners
Patrick Steinhardt [Wed, 19 Nov 2025 07:50:59 +0000 (08:50 +0100)]
chdir-notify: add function to unregister listeners

While we (obviously) have a way to register new listeners that get
called whenever we chdir(3p), we don't have an equivalent that can be
used to unregister such a listener again.

Add one, as it will be required in a subsequent commit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoodb: handle initialization of sources in `odb_new()`
Patrick Steinhardt [Wed, 19 Nov 2025 07:50:58 +0000 (08:50 +0100)]
odb: handle initialization of sources in `odb_new()`

The logic to set up a new object database is currently distributed
across two functions in "repository.c":

  - In `initialize_repository()` we initialize an empty object database.
    This object database is not fully initialized and doesn't have any
    sources attached to it.

  - The primary object database source is then created in
    `repo_set_gitdir()`.

Ideally though, the logic should be entirely self-contained so that we
can iterate more readily on how exactly the sources themselves get set
up.

Refactor `odb_new()` to handle both allocation and setup of the object
database. This ensures that the object database is always initialized
and ready for use, and it allows us to change how the sources get set up
eventually.

Note that `repo_set_gitdir()` still reaches into the sources when the
function gets called with an already-initialized object database. This
will be fixed in the next commit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agohttp-push: stop setting up `the_repository` for each reference
Patrick Steinhardt [Wed, 19 Nov 2025 07:50:57 +0000 (08:50 +0100)]
http-push: stop setting up `the_repository` for each reference

When pushing references via HTTP we call `repo_init_revisions()` in a
loop for each reference that we're about to push. As third argument we
pass the result of `setup_git_directory()`, which causes us to
reinitialize the repository every single time.

This is an obvious waste of compute, as the repository that we're
working in will never change across any of the initializations. The only
reason that we do this is to retrieve the directory of the repository.
Furthermore, this is about to create issues in a subsequent commit,
where reinitializing the repository will cause a `BUG()`.

Address this by storing the Git directory in a variable instead so that
we don't have to call the function repeatedly.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agot/helper: stop setting up `the_repository` repeatedly
Patrick Steinhardt [Wed, 19 Nov 2025 07:50:56 +0000 (08:50 +0100)]
t/helper: stop setting up `the_repository` repeatedly

The "repository" test helper sets up `the_repository` twice. In fact
though, we don't even have to set it up even once: all we need is to set
up its hash algorithm, because we still depend on some subsystems that
aren't free of `the_repository`.

Refactor the code accordingly. This prepares for a subsequent change,
where setting up the repository repeatedly will lead to a `BUG()`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agobuiltin/index-pack: fix deferred fsck outside repos
Patrick Steinhardt [Wed, 19 Nov 2025 07:50:55 +0000 (08:50 +0100)]
builtin/index-pack: fix deferred fsck outside repos

When asked to perform object consistency checks via the `--fsck-objects`
flag we verify that each object part of the pack is valid. In general,
this check can even be performed outside of a Git repository: we don't
need an initialized object database as we simply read the object from
the packfile directly.

But there's one exception: a subset of the object checks may be deferred
to a later point in time. For now, this only concerns ".gitmodules" and
".gitattributes" files: whenever we see a tree referencing these files
we queue them for a deferred check. This is done because we need to do
some extra checks for those files to ensure that they are well-formed,
and these checks need to be done regardless of whether the corresponding
blobs are part of the packfile or not.

This works inside a repository, but unfortunately the logic leads to a
segfault when running outside of one. This is because we eventually call
`odb_read_object()`, which will crash because the object database has
not been initialized.

There's multiple options here:

  - We could in theory create a purely in-memory database with only a
    packfile store that contains the single packfile. We don't really
    have the infrastructure for this yet though, and it would end up
    being quite hacky.

  - We could refuse to perform consistency checks outside of a
    repository. But most of the checks work alright, so this would be a
    regression.

  - We can skip the finalizing consistency checks when running outside
    of a repository. This is not as invasive as skipping all checks,
    but it's not great to randomly skip a subset of tests, either.

None of these options really feel perfect. The first one would be the
obvious choice if easily possible.

There's another option though: instead of skipping the final object
checks, we can die if there are any queued object checks. With this
change we now die exactly if and only if we would have previously
segfaulted. Like this we ensure that objects that _may_ fail the
consistency checks won't be silently skipped, and at the same time we
give users a much better error message.

Refactor the code accordingly and add a test that would have triggered
the segfault. Note that we also move down the logic to add the packfile
to the store. There is no point doing this any earlier than right before
we execute `fsck_finish()`, and it ensures that the logic to set up and
perform the consistency check is self-contained.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agooidset: introduce `oidset_equal()`
Patrick Steinhardt [Wed, 19 Nov 2025 07:50:54 +0000 (08:50 +0100)]
oidset: introduce `oidset_equal()`

Introduce a new function that allows the caller to verify whether two
oidsets contain the exact same object IDs.

Note that this change requires us to change `oidset_iter_init()` to
accept a `const struct oidset`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoodb: move logic to disable ref updates into repo
Patrick Steinhardt [Wed, 19 Nov 2025 07:50:53 +0000 (08:50 +0100)]
odb: move logic to disable ref updates into repo

Our object database sources have a field `disable_ref_updates`. This
field can obviously be set to disable reference updates, but it is
somewhat curious that this logic is hosted by the object database.

The reason for this is that it was primarily added to keep us from
accidentally updating references while an ODB transaction is ongoing.
Any objects part of the transaction have not yet been committed to disk,
so new references that point to them might get corrupted in case we
never end up committing the transaction. As such, whenever we create a
new transaction we set up a new temporary ODB source and mark it as
disabling reference updates.

This has one (and only one?) upside: once we have committed the
transaction, the temporary source will be dropped and thus we clean up
the disabled reference updates automatically. But other than that, it's
somewhat misdesigned:

  - We can have multiple ODB sources, but only the currently active
    source inhibits reference updates.

  - We're mixing concerns of the refdb with the ODB.

Arguably, the decision of whether we can update references or not should
be handled by the refdb. But that wouldn't be a great fit either, as
there can be one refdb per worktree. So we'd again have the same problem
that a "global" intent becomes localized to a specific instance.

Instead, move the setting into the repository. While at it, convert it
into a boolean.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoconfig: really treat missing optional path as not configured
Junio C Hamano [Thu, 20 Nov 2025 19:45:35 +0000 (11:45 -0800)]
config: really treat missing optional path as not configured

These callers expect that git_config_pathname() that returns 0 is a
signal that the variable they passed has a string they need to act
on.  But with the introduction of ":(optional)path" earlier, that is
no longer the case.  If the path specified by the configuration
variable is missing, their variable will get a NULL in it, and they
need to act on it (often, just refraining from copying it elsewhere).

Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 months agoconfig: really pretend missing :(optional) value is not there
Junio C Hamano [Thu, 20 Nov 2025 19:34:50 +0000 (11:34 -0800)]
config: really pretend missing :(optional) value is not there

Earlier we added support for a value spelled as ":(optional)path"
for configuration variables whose values are of type "path", with
the documented semantics "if the path is missing, behave as if such
a variable definition is not even there."

This has worked OK for code paths that reads configuration files and
stores the configured value as a string, where NULL in such a string
is treated as if the setting is not there, left as the default.

However, there are other code paths that do not _ignore_ such NULL
values and misbehave.  "git config get --path" is one of them.

When git_config_pathname() helper function finds that the value of
the variable is an optional path *and* the path is missing, it
leaves the destination pointer intact (which usually is left to
NULL) and returns 0 to signal a success.  format_config() helper
however assumed that the destination pointer always gets a string,
which no longer is the case, and segfaulted.

Make sure that git_config_pathname() clears the destination pointer
in such a case, and teach format_config() to react to the condition
by returning 1 (which is different from 0 that is a normal success
and negative that is an error) to its callers.  Adjust the callers
to react to this new return value that tells them to pretend as if
they did not even see this partcular <key, value> pair.

Reported-by: Han Jiang <jhcarl0814@gmail.com>
Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>