Compare commits

...

657 Commits

Author SHA1 Message Date
Johannes Schindelin
a5512bdee3 Merge 'readme' into HEAD
Add a README.md for GitHub goodness.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:52 +01:00
Johannes Schindelin
ff8ffb1b7a Merge pull request #2837 from dscho/monitor-component-updates
Start monitoring updates of Git for Windows' component in the open
2026-02-02 18:10:51 +01:00
Johannes Schindelin
f5935cb6ab Merge branch 'deprecate-core.useBuiltinFSMonitor'
Originally introduced as `core.useBuiltinFSMonitor` in Git for Windows
and developed, improved and stabilized there, the built-in FSMonitor
only made it into upstream Git (after unnecessarily long hemming and
hawing and throwing overly perfectionist style review sticks into the
spokes) as `core.fsmonitor = true`.

In Git for Windows, with this topic branch, we re-introduce the
now-obsolete config setting, with warnings suggesting to existing users
how to switch to the new config setting, with the intention to
ultimately drop the patch at some stage.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:51 +01:00
Johannes Schindelin
68c2c1fb1e Merge branch 'phase-out-reset-stdin'
This topic branch re-adds the deprecated --stdin/-z options to `git
reset`. Those patches were overridden by a different set of options in
the upstream Git project before we could propose `--stdin`.

We offered this in MinGit to applications that wanted a safer way to
pass lots of pathspecs to Git, and these applications will need to be
adjusted.

Instead of `--stdin`, `--pathspec-from-file=-` should be used, and
instead of `-z`, `--pathspec-file-nul`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:51 +01:00
Johannes Schindelin
8e98c97bc3 Merge branch 'un-revert-editor-save-and-reset'
A fix for calling `vim` in Windows Terminal caused a regression and was
reverted. We partially un-revert this, to get the fix again.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:51 +01:00
Johannes Schindelin
c19108ca52 Merge pull request #1170 from dscho/mingw-kill-process
Handle Ctrl+C in Git Bash nicely

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:50 +01:00
Johannes Schindelin
5f7201b50f Merge branch 'wsl-file-mode-bits'
This patch introduces support to set special NTFS attributes that are
interpreted by the Windows Subsystem for Linux as file mode bits, UID
and GID.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:50 +01:00
Johannes Schindelin
b6adf7fbee Merge branch 'busybox-w32'
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:50 +01:00
Johannes Schindelin
480e49d67e Merge pull request #1897 from piscisaureus/symlink-attr
Specify symlink type in .gitattributes
2026-02-02 18:10:49 +01:00
Johannes Schindelin
5cd82ea57d mingw: try resetting the read-only bit if rename fails (#4527)
With this patch, Git for Windows works as intended on mounted APFS
volumes (where renaming read-only files would fail).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:49 +01:00
Johannes Schindelin
cd7537428a Merge 'docker-volumes-are-no-symlinks'
This was pull request #1645 from ZCube/master

Support windows container.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:49 +01:00
Johannes Schindelin
75acb209a9 SECURITY.md: document Git for Windows' policies
This is the recommended way on GitHub to describe policies revolving around
security issues and about supported versions.

Helped-by: Sven Strickroth <email@cs-ware.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:48 +01:00
Johannes Schindelin
90cdbf4adf Merge branch 'msys2' 2026-02-02 18:10:48 +01:00
Philip Oakley
fcc0e8ea3f Modify the GitHub Pull Request template (to reflect Git for Windows)
Git for Windows accepts pull requests; Core Git does not. Therefore we
need to adjust the template (because it only matches core Git's
project management style, not ours).

Also: direct Git for Windows enhancements to their contributions page,
space out the text for easy reading, and clarify that the mailing list
is plain text, not HTML.

Signed-off-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:48 +01:00
Johannes Schindelin
9dfe22e227 Merge branch 'long-paths' 2026-02-02 18:10:48 +01:00
Johannes Schindelin
d6547aa5e3 Merge branch 'gitk-and-git-gui-patches'
These are Git for Windows' Git GUI and gitk patches. We will have to
decide at some point what to do about them, but that's a little lower
priority (as Git GUI seems to be unmaintained for the time being, and
the gitk maintainer keeps a very low profile on the Git mailing list,
too).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:48 +01:00
Johannes Schindelin
3427f45c74 dependabot: help keeping GitHub Actions versions up to date
See https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot#enabling-dependabot-version-updates-for-actions for details.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:47 +01:00
Victoria Dye
2a30c2b2aa fsmonitor: reintroduce core.useBuiltinFSMonitor
Reintroduce the 'core.useBuiltinFSMonitor' config setting (originally added
in 0a756b2a25 (fsmonitor: config settings are repository-specific,
2021-03-05)) after its removal from the upstream version of FSMonitor.

Upstream, the 'core.useBuiltinFSMonitor' setting was rendered obsolete by
"overloading" the 'core.fsmonitor' setting to take a boolean value. However,
several applications (e.g., 'scalar') utilize the original config setting,
so it should be preserved for a deprecation period before complete removal:

* if 'core.fsmonitor' is a boolean, the user is correctly using the new
  config syntax; do not use 'core.useBuiltinFSMonitor'.
* if 'core.fsmonitor' is unspecified, use 'core.useBuiltinFSMonitor'.
* if 'core.fsmonitor' is a path, override and use the builtin FSMonitor if
  'core.useBuiltinFSMonitor' is 'true'; otherwise, use the FSMonitor hook
  indicated by the path.

Additionally, for this deprecation period, advise users to switch to using
'core.fsmonitor' to specify their use of the builtin FSMonitor.

Signed-off-by: Victoria Dye <vdye@github.com>
2026-02-02 18:10:47 +01:00
Johannes Schindelin
059e4a9213 reset: reinstate support for the deprecated --stdin option
The `--stdin` option was a well-established paradigm in other commands,
therefore we implemented it in `git reset` for use by Visual Studio.

Unfortunately, upstream Git decided that it is time to introduce
`--pathspec-from-file` instead.

To keep backwards-compatibility for some grace period, we therefore
reinstate the `--stdin` option on top of the `--pathspec-from-file`
option, but mark it firmly as deprecated.

Helped-by: Victoria Dye <vdye@github.com>
Helped-by: Matthew John Cheetham <mjcheetham@outlook.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:47 +01:00
Brendan Forster
0dc4938261 Add an issue template
With improvements by Clive Chan, Adric Norris, Ben Bodenmiller and
Philip Oakley.

Helped-by: Clive Chan <cc@clive.io>
Helped-by: Adric Norris <landstander668@gmail.com>
Helped-by: Ben Bodenmiller <bbodenmiller@hotmail.com>
Helped-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Brendan Forster <brendan@github.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:47 +01:00
Johannes Schindelin
cd97859994 Add a GitHub workflow to monitor component updates
Rather than using private IFTTT Applets that send mails to this
maintainer whenever a new version of a Git for Windows component was
released, let's use the power of GitHub workflows to make this process
publicly visible.

This workflow monitors the Atom/RSS feeds, and opens a ticket whenever a
new version was released.

Note: Bash sometimes releases multiple patched versions within a few
minutes of each other (i.e. 5.1p1 through 5.1p4, 5.0p15 and 5.0p16). The
MSYS2 runtime also has a similar system. We can address those patches as
a group, so we shouldn't get multiple issues about them.

Note further: We're not acting on newlib releases, OpenSSL alphas, Perl
release candidates or non-stable Perl releases. There's no need to open
issues about them.

Co-authored-by: Matthias Aßhauer <mha1993@live.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:47 +01:00
Johannes Schindelin
6661b4c2db README.md: Add a Windows-specific preamble
Includes touch-ups by 마누엘, Philip Oakley and 孙卓识.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:47 +01:00
Derrick Stolee
176c3dfbf6 CONTRIBUTING.md: add guide for first-time contributors
Getting started contributing to Git can be difficult on a Windows
machine. CONTRIBUTING.md contains a guide to getting started, including
detailed steps for setting up build tools, running tests, and
submitting patches to upstream.

[includes an example by Pratik Karki how to submit v2, v3, v4, etc.]

Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
2026-02-02 18:10:47 +01:00
Johannes Schindelin
23b16ad720 Modify the Code of Conduct for Git for Windows
The Git project followed Git for Windows' lead and added their Code of
Conduct, based on the Contributor Covenant v1.4, later updated to v2.0.

We adapt it slightly to Git for Windows.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:47 +01:00
Johannes Schindelin
098d292a2a Describe Git for Windows' architecture [no ci]
The Git for Windows project has grown quite complex over the years,
certainly much more complex than during the first years where the
`msysgit.git` repository was abusing Git for package management purposes
and the `git/git` fork was called `4msysgit.git`.

Let's describe the status quo in a thorough way.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:47 +01:00
Johannes Schindelin
07c3c77e94 Partially un-revert "editor: save and reset terminal after calling EDITOR"
In e3f7e01b50be (Revert "editor: save and reset terminal after calling
EDITOR", 2021-11-22), we reverted the commit wholesale where the
terminal state would be saved and restored before/after calling an
editor.

The reverted commit was intended to fix a problem with Windows Terminal
where simply calling `vi` would cause problems afterwards.

To fix the problem addressed by the revert, but _still_ keep the problem
with Windows Terminal fixed, let's revert the revert, with a twist: we
restrict the save/restore _specifically_ to the case where `vi` (or
`vim`) is called, and do not do the same for any other editor.

This should still catch the majority of the cases, and will bridge the
time until the original patch is re-done in a way that addresses all
concerns.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:46 +01:00
Johannes Schindelin
395930639e mingw: really handle SIGINT
Previously, we did not install any handler for Ctrl+C, but now we really
want to because the MSYS2 runtime learned the trick to call the
ConsoleCtrlHandler when Ctrl+C was pressed.

With this, hitting Ctrl+C while `git log` is running will only terminate
the Git process, but not the pager. This finally matches the behavior on
Linux and on macOS.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:46 +01:00
Johannes Schindelin
c603bf2f0a mingw: kill child processes in a gentler way
The TerminateProcess() function does not actually leave the child
processes any chance to perform any cleanup operations. This is bad
insofar as Git itself expects its signal handlers to run.

A symptom is e.g. a left-behind .lock file that would not be left behind
if the same operation was run, say, on Linux.

To remedy this situation, we use an obscure trick: we inject a thread
into the process that needs to be killed and to let that thread run the
ExitProcess() function with the desired exit status. Thanks J Wyman for
describing this trick.

The advantage is that the ExitProcess() function lets the atexit
handlers run. While this is still different from what Git expects (i.e.
running a signal handler), in practice Git sets up signal handlers and
atexit handlers that call the same code to clean up after itself.

In case that the gentle method to terminate the process failed, we still
fall back to calling TerminateProcess(), but in that case we now also
make sure that processes spawned by the spawned process are terminated;
TerminateProcess() does not give the spawned process a chance to do so
itself.

Please note that this change only affects how Git for Windows tries to
terminate processes spawned by Git's own executables. Third-party
software that *calls* Git and wants to terminate it *still* need to make
sure to imitate this gentle method, otherwise this patch will not have
any effect.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:46 +01:00
xungeng li
fb5c468a8f mingw: optionally enable wsl compability file mode bits
The Windows Subsystem for Linux (WSL) version 2 allows to use `chmod` on
NTFS volumes provided that they are mounted with metadata enabled (see
https://devblogs.microsoft.com/commandline/chmod-chown-wsl-improvements/
for details), for example:

	$ chmod 0755 /mnt/d/test/a.sh

In order to facilitate better collaboration between the Windows
version of Git and the WSL version of Git, we can make the Windows
version of Git also support reading and writing NTFS file modes
in a manner compatible with WSL.

Since this slightly slows down operations where lots of files are
created (such as an initial checkout), this feature is only enabled when
`core.WSLCompat` is set to true. Note that you also have to set
`core.fileMode=true` in repositories that have been initialized without
enabling WSL compatibility.

There are several ways to enable metadata loading for NTFS volumes
in WSL, one of which is to modify `/etc/wsl.conf` by adding:

```
[automount]
enabled = true
options = "metadata,umask=027,fmask=117"
```

And reboot WSL.

It can also be enabled temporarily by this incantation:

	$ sudo umount /mnt/c &&
	  sudo mount -t drvfs C: /mnt/c -o metadata,uid=1000,gid=1000,umask=22,fmask=111

It's important to note that this modification is compatible with, but
does not depend on WSL. The helper functions in this commit can operate
independently and functions normally on devices where WSL is not
installed or properly configured.

Signed-off-by: xungeng li <xungeng@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:45 +01:00
Johannes Schindelin
f9a8ba54de t9200: skip tests when $PWD contains a colon
On Windows, the current working directory is pretty much guaranteed to
contain a colon. If we feed that path to CVS, it mistakes it for a
separator between host and port, though.

This has not been a problem so far because Git for Windows uses MSYS2's
Bash using a POSIX emulation layer that also pretends that the current
directory is a Unix path (at least as long as we're in a shell script).

However, that is rather limiting, as Git for Windows also explores other
ports of other Unix shells. One of those is BusyBox-w32's ash, which is
a native port (i.e. *not* using any POSIX emulation layer, and certainly
not emulating Unix paths).

So let's just detect if there is a colon in $PWD and punt in that case.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:45 +01:00
Johannes Schindelin
2103934d4c t5813: allow for $PWD to be a Windows path
Git for Windows uses MSYS2's Bash to run the test suite, which comes
with benefits but also at a heavy price: on the plus side, MSYS2's
POSIX emulation layer allows us to continue pretending that we are on a
Unix system, e.g. use Unix paths instead of Windows ones, yet this is
bought at a rather noticeable performance penalty.

There *are* some more native ports of Unix shells out there, though,
most notably BusyBox-w32's ash. These native ports do not use any POSIX
emulation layer (or at most a *very* thin one, choosing to avoid
features such as fork() that are expensive to emulate on Windows), and
they use native Windows paths (usually with forward slashes instead of
backslashes, which is perfectly legal in almost all use cases).

And here comes the problem: with a $PWD looking like, say,
C:/git-sdk-64/usr/src/git/t/trash directory.t5813-proto-disable-ssh
Git's test scripts get quite a bit confused, as their assumptions have
been shattered. Not only does this path contain a colon (oh no!), it
also does not start with a slash.

This is a problem e.g. when constructing a URL as t5813 does it:
ssh://remote$PWD. Not only is it impossible to separate the "host" from
the path with a $PWD as above, even prefixing $PWD by a slash won't
work, as /C:/git-sdk-64/... is not a valid path.

As a workaround, detect when $PWD does not start with a slash on
Windows, and simply strip the drive prefix, using an obscure feature of
Windows paths: if an absolute Windows path starts with a slash, it is
implicitly prefixed by the drive prefix of the current directory. As we
are talking about the current directory here, anyway, that strategy
works.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:45 +01:00
Johannes Schindelin
315c8725ea t5605: special-case hardlink test for BusyBox-w32
When t5605 tries to verify that files are hardlinked (or that they are
not), it uses the `-links` option of the `find` utility.

BusyBox' implementation does not support that option, and BusyBox-w32's
lstat() does not even report the number of hard links correctly (for
performance reasons).

So let's just switch to a different method that actually works on
Windows.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:45 +01:00
Johannes Schindelin
4e3ac29bfb t5532: workaround for BusyBox on Windows
While it may seem super convenient to some old Unix hands to simpy
require Perl to be available when running the test suite, this is a
major hassle on Windows, where we want to verify that Perl is not,
actually, required in a NO_PERL build.

As a super ugly workaround, we "install" a script into /usr/bin/perl
reading like this:

	#!/bin/sh

	# We'd much rather avoid requiring Perl altogether when testing
	# an installed Git. Oh well, that's why we cannot have nice
	# things.
	exec c:/git-sdk-64/usr/bin/perl.exe "$@"

The problem with that is that BusyBox assumes that the #! line in a
script refers to an executable, not to a script. So when it encounters
the line #!/usr/bin/perl in t5532's proxy-get-cmd, it barfs.

Let's help this situation by simply executing the Perl script with the
"interpreter" specified explicitly.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:45 +01:00
Johannes Schindelin
5363a21f2e t5003: use binary file from t/lib-diff/
At some stage, t5003-archive-zip wants to add a file that is not ASCII.
To that end, it uses /bin/sh. But that file may actually not exist (it
is too easy to forget that not all the world is Unix/Linux...)! Besides,
we already have perfectly fine binary files intended for use solely by
the tests. So let's use one of them instead.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:45 +01:00
Johannes Schindelin
2cd0ebae88 test-lib: add BUSYBOX prerequisite
When running with BusyBox, we will want to avoid calling executables on
the PATH that are implemented in BusyBox itself.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:45 +01:00
Johannes Schindelin
469062d1b0 tests (mingw): remove Bash-specific pwd option
The -W option is only understood by MSYS2 Bash's pwd command. We already
make sure to override `pwd` by `builtin pwd -W` for MINGW, so let's not
double the effort here.

This will also help when switching the shell to another one (such as
BusyBox' ash) whose pwd does *not* understand the -W option.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:45 +01:00
Johannes Schindelin
1656ddf364 mingw: only use Bash-ism builtin pwd -W when available
Traditionally, Git for Windows' SDK uses Bash as its default shell.
However, other Unix shells are available, too. Most notably, the Win32
port of BusyBox comes with `ash` whose `pwd` command already prints
Windows paths as Git for Windows wants them, while there is not even a
`builtin` command.

Therefore, let's be careful not to override `pwd` unless we know that
the `builtin` command is available.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:45 +01:00
Johannes Schindelin
6e6763c05e tests: use the correct path separator with BusyBox
BusyBox-w32 is a true Win32 application, i.e. it does not come with a
POSIX emulation layer.

That also means that it does *not* use the Unix convention of separating
the entries in the PATH variable using colons, but semicolons.

However, there are also BusyBox ports to Windows which use a POSIX
emulation layer such as Cygwin's or MSYS2's runtime, i.e. using colons
as PATH separators.

As a tell-tale, let's use the presence of semicolons in the PATH
variable: on Unix, it is highly unlikely that it contains semicolons,
and on Windows (without POSIX emulation), it is virtually guaranteed, as
everybody should have both $SYSTEMROOT and $SYSTEMROOT/system32 in their
PATH.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:44 +01:00
Johannes Schindelin
ef9b24f685 tests: only override sort & find if there are usable ones in /usr/bin/
The idea is to allow running the test suite on MinGit with BusyBox
installed in /mingw64/bin/sh.exe. In that case, we will want to exclude
sort & find (and other Unix utilities) from being bundled.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:44 +01:00
Johannes Schindelin
1733d47e9d tests: move test PNGs into t/lib-diff/
We already have a directory where we store files intended for use by
multiple test scripts. The same directory is a better home for the
test-binary-*.png files than t/.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:44 +01:00
Johannes Schindelin
13eb857efb gitattributes: mark .png files as binary
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:44 +01:00
Johannes Schindelin
7b017d4b72 tests(mingw): if iconv is unavailable, use test-helper --iconv
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:44 +01:00
Johannes Schindelin
a7aaba96ac test-tool: learn to act as a drop-in replacement for iconv
It is convenient to assume that everybody who wants to build & test Git
has access to a working `iconv` executable (after all, we already pretty
much require libiconv).

However, that limits esoteric test scenarios such as Git for Windows',
where an end user installation has to ship with `iconv` for the sole
purpose of being testable. That payload serves no other purpose.

So let's just have a test helper (to be able to test Git, the test
helpers have to be available, after all) to act as `iconv` replacement.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:44 +01:00
Johannes Schindelin
8cad447002 mingw: when path_lookup() failed, try BusyBox
BusyBox comes with a ton of applets ("applet" being the identical
concept to Git's "builtins"). And similar to Git's builtins, the applets
can be called via `busybox <command>`, or the BusyBox executable can be
copied/hard-linked to the command name.

The similarities do not end here. Just as with Git's builtins, it is
problematic that BusyBox' hard-linked applets cannot easily be put into
a .zip file: .zip archives have no concept of hard-links and therefore
would store identical copies (and also extract identical copies,
"inflating" the archive unnecessarily).

To counteract that issue, MinGit already ships without hard-linked
copies of the builtins, and the plan is to do the same with BusyBox'
applets: simply ship busybox.exe as single executable, without
hard-linked applets.

To accommodate that, Git is being taught by this commit a very special
trick, exploiting the fact that it is possible to call an executable
with a command-line whose argv[0] is different from the executable's
name: when `sh` is to be spawned, and no `sh` is found in the PATH, but
busybox.exe is, use that executable (with unchanged argv).

Likewise, if any executable to be spawned is not on the PATH, but
busybox.exe is found, parse the output of `busybox.exe --help` to find
out what applets are included, and if the command matches an included
applet name, use busybox.exe to execute it.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:44 +01:00
Bert Belder
c7b36323e6 Win32: symlink: add test for symlink attribute
To verify that the symlink is resolved correctly, we use the fact that
`git.exe` is a native Win32 program, and that `git.exe config -f <path>`
therefore uses the native symlink resolution.

Signed-off-by: Bert Belder <bertbelder@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:43 +01:00
David Lomas
56329c8d07 mingw: work around rename() failing on a read-only file
At least on _some_ APFS network shares, Git fails to rename the object
files because they are marked as read-only, because that has the effect
of setting the uchg flag on APFS, which then means the file can't be
renamed or deleted.

To work around that, when a rename failed, and the read-only flag is
set, try to turn it off and on again.

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

Signed-off-by: David Lomas <dl3@pale-eds.co.uk>
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
2026-02-02 18:10:43 +01:00
Johannes Schindelin
bf309da8c0 mingw: Windows Docker volumes are *not* symbolic links
... even if they may look like them.

As looking up the target of the "symbolic link" (just to see whether it
starts with `/ContainerMappedDirectories/`) is pretty expensive, we
do it when we can be *really* sure that there is a possibility that this
might be the case.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: JiSeop Moon <zcube@zcube.kr>
2026-02-02 18:10:43 +01:00
Johannes Schindelin
2262179861 mingw: explicitly specify with which cmd to prefix the cmdline
The main idea of this patch is that even if we have to look up the
absolute path of the script, if only the basename was specified as
argv[0], then we should use that basename on the command line, too, not
the absolute path.

This patch will also help with the upcoming patch where we automatically
substitute "sh ..." by "busybox sh ..." if "sh" is not in the PATH but
"busybox" is: we will do that by substituting the actual executable, but
still keep prepending "sh" to the command line.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:43 +01:00
Bert Belder
5257028fef mingw: allow to specify the symlink type in .gitattributes
On Windows, symbolic links have a type: a "file symlink" must point at
a file, and a "directory symlink" must point at a directory. If the
type of symlink does not match its target, it doesn't work.

Git does not record the type of symlink in the index or in a tree. On
checkout it'll guess the type, which only works if the target exists
at the time the symlink is created. This may often not be the case,
for example when the link points at a directory inside a submodule.

By specifying `symlink=file` or `symlink=dir` the user can specify what
type of symlink Git should create, so Git doesn't have to rely on
unreliable heuristics.

Signed-off-by: Bert Belder <bertbelder@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:43 +01:00
JiSeop Moon
5e858ed4be mingw: move the file_attr_to_st_mode() function definition
In preparation for making this function a bit more complicated (to allow
for special-casing the `ContainerMappedDirectories` in Windows
containers, which look like a symbolic link, but are not), let's move it
out of the header.

Signed-off-by: JiSeop Moon <zcube@zcube.kr>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:43 +01:00
Johannes Schindelin
cadb2878d5 Introduce helper to create symlinks that knows about index_state
On Windows, symbolic links actually have a type depending on the target:
it can be a file or a directory.

In certain circumstances, this poses problems, e.g. when a symbolic link
is supposed to point into a submodule that is not checked out, so there
is no way for Git to auto-detect the type.

To help with that, we will add support over the course of the next
commits to specify that symlink type via the Git attributes. This
requires an index_state, though, something that Git for Windows'
`symlink()` replacement cannot know about because the function signature
is defined by the POSIX standard and not ours to change.

So let's introduce a helper function to create symbolic links that
*does* know about the index_state.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:43 +01:00
Bert Belder
b3e667d84b Win32: symlink: move phantom symlink creation to a separate function
Signed-off-by: Bert Belder <bertbelder@gmail.com>
2026-02-02 18:10:43 +01:00
Johannes Schindelin
b271aabf38 mingw (git_terminal_prompt): do fall back to CONIN$/CONOUT$ method
To support Git Bash running in a MinTTY, we use a dirty trick to access
the MSYS2 pseudo terminal: we execute a Bash snippet that accesses
/dev/tty.

The idea was to fall back to writing to/reading from CONOUT$/CONIN$ if
that Bash call failed because Bash was not found.

However, we should fall back even in other error conditions, because we
have not successfully read the user input. Let's make it so.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:42 +01:00
Ben Boeckel
f481f5fe01 clean: suggest using core.longPaths if paths are too long to remove
On Windows, git repositories may have extra files which need cleaned
(e.g., a build directory) that may be arbitrarily deep. Suggest using
`core.longPaths` if such situations are encountered.

Fixes: #2715
Signed-off-by: Ben Boeckel <mathstuf@gmail.com>
2026-02-02 18:10:42 +01:00
JiSeop Moon
a0180b7391 mingw: when running in a Windows container, try to rename() harder
It is a known issue that a rename() can fail with an "Access denied"
error at times, when copying followed by deleting the original file
works. Let's just fall back to that behavior.

Signed-off-by: JiSeop Moon <zcube@zcube.kr>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:42 +01:00
Karsten Blees
c620de3a37 compat/terminal.c: only use the Windows console if bash 'read -r' fails
Accessing the Windows console through the special CONIN$ / CONOUT$ devices
doesn't work properly for non-ASCII usernames an passwords.

It also doesn't work for terminal emulators that hide the native console
window (such as mintty), and 'TERM=xterm*' is not necessarily a reliable
indicator for such terminals.

The new shell_prompt() function, on the other hand, works fine for both
MSys1 and MSys2, in native console windows as well as mintty, and properly
supports Unicode. It just needs bash on the path (for 'read -s', which is
bash-specific).

On Windows, try to use the shell to read from the terminal. If that fails
with ENOENT (i.e. bash was not found), use CONIN/OUT as fallback.

Note: To test this, create a UTF-8 credential file with non-ASCII chars,
e.g. in git-bash: 'echo url=http://täst.com > cred.txt'. Then in git-cmd,
'git credential fill <cred.txt' works (shell version), while calling git
without the git-wrapper (i.e. 'mingw64\bin\git credential fill <cred.txt')
mangles non-ASCII chars in both console output and input.

Signed-off-by: Karsten Blees <blees@dcon.de>
2026-02-02 18:10:42 +01:00
Jeff Hostetler
5b3d5e5d9c compat/fsmonitor/fsm-*-win32: support long paths
Update wchar_t buffers to use MAX_LONG_PATH instead of MAX_PATH and call
xutftowcs_long_path() in the Win32 backend source files.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-02-02 18:10:42 +01:00
JiSeop Moon
24b67bdd4f mingw: introduce code to detect whether we're inside a Windows container
This will come in handy in the next commit.

Signed-off-by: JiSeop Moon <zcube@zcube.kr>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:42 +01:00
Karsten Blees
6ab60ee242 mingw: Support git_terminal_prompt with more terminals
The `git_terminal_prompt()` function expects the terminal window to be
attached to a Win32 Console. However, this is not the case with terminal
windows other than `cmd.exe`'s, e.g. with MSys2's own `mintty`.

Non-cmd terminals such as `mintty` still have to have a Win32 Console
to be proper console programs, but have to hide the Win32 Console to
be able to provide more flexibility (such as being resizeable not only
vertically but also horizontally). By writing to that Win32 Console,
`git_terminal_prompt()` manages only to send the prompt to nowhere and
to wait for input from a Console to which the user has no access.

This commit introduces a function specifically to support `mintty` -- or
other terminals that are compatible with MSys2's `/dev/tty` emulation. We
use the `TERM` environment variable as an indicator for that: if the value
starts with "xterm" (such as `mintty`'s "xterm_256color"), we prefer to
let `xterm_prompt()` handle the user interaction.

The most prominent user of `git_terminal_prompt()` is certainly
`git-remote-https.exe`. It is an interesting use case because both
`stdin` and `stdout` are redirected when Git calls said executable, yet
it still wants to access the terminal.

When running inside a `mintty`, the terminal is not accessible to the
`git-remote-https.exe` program, though, because it is a MinGW program
and the `mintty` terminal is not backed by a Win32 console.

To solve that problem, we simply call out to the shell -- which is an
*MSys2* program and can therefore access `/dev/tty`.

Helped-by: nalla <nalla@hamal.uberspace.de>
Signed-off-by: Karsten Blees <blees@dcon.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:42 +01:00
Johannes Schindelin
cec282001c win32(long path support): leave drive-less absolute paths intact
When trying to ensure that long paths are handled correctly, we
first normalize absolute paths as we encounter them.

However, if the path is a so-called "drive-less" absolute path, i.e. if
it is relative to the current drive but _does_ start with a directory
separator, we would want the normalized path to be such a drive-less
absolute path, too.

Let's do that, being careful to still include the drive prefix when we
need to go through the `\\?\` dance (because there, the drive prefix is
absolutely required).

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

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:42 +01:00
Karsten Blees
ca4facf604 mingw: support long paths
Windows paths are typically limited to MAX_PATH = 260 characters, even
though the underlying NTFS file system supports paths up to 32,767 chars.
This limitation is also evident in Windows Explorer, cmd.exe and many
other applications (including IDEs).

Particularly annoying is that most Windows APIs return bogus error codes
if a relative path only barely exceeds MAX_PATH in conjunction with the
current directory, e.g. ERROR_PATH_NOT_FOUND / ENOENT instead of the
infinitely more helpful ERROR_FILENAME_EXCED_RANGE / ENAMETOOLONG.

Many Windows wide char APIs support longer than MAX_PATH paths through the
file namespace prefix ('\\?\' or '\\?\UNC\') followed by an absolute path.
Notable exceptions include functions dealing with executables and the
current directory (CreateProcess, LoadLibrary, Get/SetCurrentDirectory) as
well as the entire shell API (ShellExecute, SHGetSpecialFolderPath...).

Introduce a handle_long_path function to check the length of a specified
path properly (and fail with ENAMETOOLONG), and to optionally expand long
paths using the '\\?\' file namespace prefix. Short paths will not be
modified, so we don't need to worry about device names (NUL, CON, AUX).

Contrary to MSDN docs, the GetFullPathNameW function doesn't seem to be
limited to MAX_PATH (at least not on Win7), so we can use it to do the
heavy lifting of the conversion (translate '/' to '\', eliminate '.' and
'..', and make an absolute path).

Add long path error checking to xutftowcs_path for APIs with hard MAX_PATH
limit.

Add a new MAX_LONG_PATH constant and xutftowcs_long_path function for APIs
that support long paths.

While improved error checking is always active, long paths support must be
explicitly enabled via 'core.longpaths' option. This is to prevent end
users from shooting themselves in the foot by checking out files that Windows
Explorer, cmd/bash or their favorite IDE cannot handle.

Test suite:
Test the case is when the full pathname length of a dir is close
to 260 (MAX_PATH).
Bug report and an original reproducer by Andrey Rogozhnikov:
https://github.com/msysgit/git/pull/122#issuecomment-43604199

[jes: adjusted test number to avoid conflicts, added support for
chdir(), etc]

Thanks-to: Martin W. Kirst <maki@bitkings.de>
Thanks-to: Doug Kelly <dougk.ff7@gmail.com>
Original-test-by: Andrey Rogozhnikov <rogozhnikov.andrey@gmail.com>
Signed-off-by: Karsten Blees <blees@dcon.de>
Signed-off-by: Stepan Kasal <kasal@ucw.cz>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Josh Soref <jsoref@gmail.com>
2026-02-02 18:10:42 +01:00
Doug Kelly
3e6d7bf80f pack-objects (mingw): demonstrate a segmentation fault with large deltas
There is a problem in the way 9ac3f0e5b3e4 (pack-objects: fix
performance issues on packing large deltas, 2018-07-22) initializes that
mutex in the `packing_data` struct. The problem manifests in a
segmentation fault on Windows, when a mutex (AKA critical section) is
accessed without being initialized. (With pthreads, you apparently do
not really have to initialize them?)

This was reported in https://github.com/git-for-windows/git/issues/1839.

Signed-off-by: Doug Kelly <dougk.ff7@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:41 +01:00
Johannes Schindelin
945ef1b85b Merge branch 'dont-clean-junctions-fscache'
We already avoid traversing NTFS junction points in `git clean -dfx`.
With this topic branch, we do that when the FSCache is enabled, too.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:41 +01:00
Johannes Schindelin
16e58542e5 Merge remote-tracking branch 'benpeart/fscache-per-thread-gfw'
This brings substantial wins in performance because the FSCache is now
per-thread, being merged to the primary thread only at the end, so we do
not have to lock (except while merging).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:41 +01:00
Johannes Schindelin
e47ea2eac8 Merge pull request #1909 from benpeart/free-fscache-after-status-gfw
status: disable and free fscache at the end of the status command
2026-02-02 18:10:41 +01:00
Johannes Schindelin
cc3a447c67 Merge branch 'fscache' 2026-02-02 18:10:41 +01:00
Johannes Schindelin
6b3bfd4195 clean: make use of FSCache
The `git clean` command needs to enumerate plenty of files and
directories, and can therefore benefit from the FSCache.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:40 +01:00
Ben Peart
a56b3712e8 fscache: teach fscache to use NtQueryDirectoryFile
Using FindFirstFileExW() requires the OS to allocate a 64K buffer for each
directory and then free it when we call FindClose().  Update fscache to call
the underlying kernel API NtQueryDirectoryFile so that we can do the buffer
management ourselves.  That allows us to allocate a single buffer for the
lifetime of the cache and reuse it for each directory.

This change improves performance of 'git status' by 18% in a repo with ~200K
files and 30k folders.

Documentation for NtQueryDirectoryFile can be found at:

https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntifs/nf-ntifs-ntquerydirectoryfile
https://docs.microsoft.com/en-us/windows/desktop/FileIO/file-attribute-constants
https://docs.microsoft.com/en-us/windows/desktop/fileio/reparse-point-tags

To determine if the specified directory is a symbolic link, inspect the
FileAttributes member to see if the FILE_ATTRIBUTE_REPARSE_POINT flag is
set. If so, EaSize will contain the reparse tag (this is a so far
undocumented feature, but confirmed by the NTFS developers). To
determine if the reparse point is a symbolic link (and not some other
form of reparse point), test whether the tag value equals the value
IO_REPARSE_TAG_SYMLINK.

The NtQueryDirectoryFile() call works best (and on Windows 8.1 and
earlier, it works *only*) with buffer sizes up to 64kB. Which is 32k
wide characters, so let's use that as our buffer size.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:40 +01:00
Johannes Schindelin
2b581320fd fscache: implement an FSCache-aware is_mount_point()
When FSCache is active, we can cache the reparse tag and use it directly
to determine whether a path refers to an NTFS junction, without any
additional, costly I/O.

Note: this change only makes a difference with the next commit, which
will make use of the FSCache in `git clean` (contingent on
`core.fscache` set, of course).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:40 +01:00
Ben Peart
ff0f9f515e fscache: make fscache_enable() thread safe
The recent change to make fscache thread specific relied on fscache_enable()
being called first from the primary thread before being called in parallel
from worker threads.  Make that more robust and protect it with a critical
section to avoid any issues.

Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Ben Peart <benpeart@microsoft.com>
2026-02-02 18:10:40 +01:00
Johannes Schindelin
c77679e117 fscache: remember the reparse tag for each entry
We will use this in the next commit to implement an FSCache-aware
version of is_mount_point().

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:40 +01:00
Ben Peart
5ca977108d fscache: teach fscache to use mempool
Now that the fscache is single threaded, take advantage of the mem_pool as
the allocator to significantly reduce the cost of allocations and frees.

With the reduced cost of free, in future patches, we can start freeing the
fscache at the end of commands instead of just leaking it.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:40 +01:00
Ben Peart
b0a887679c fscache: update fscache to be thread specific instead of global
The threading model for fscache has been to have a single, global cache.
This puts requirements on it to be thread safe so that callers like
preload-index can call it from multiple threads.  This was implemented
with a single mutex and completion events which introduces contention
between the calling threads.

Simplify the threading model by making fscache thread specific.  This allows
us to remove the global mutex and synchronization events entirely and instead
associate a fscache with every thread that requests one. This works well with
the current multi-threading which divides the cache entries into blocks with
a separate thread processing each block.

At the end of each worker thread, if there is a fscache on the primary
thread, merge the cached results from the worker into the primary thread
cache. This enables us to reuse the cache later especially when scanning for
untracked files.

In testing, this reduced the time spent in preload_index() by about 25% and
also reduced the CPU utilization significantly.  On a repo with ~200K files,
it reduced overall status times by ~12%.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
2026-02-02 18:10:40 +01:00
Ben Peart
4156ddbc5a status: disable and free fscache at the end of the status command
At the end of the status command, disable and free the fscache so that we
don't leak the memory and so that we can dump the fscache statistics.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
2026-02-02 18:10:39 +01:00
Derrick Stolee
35dc411ae2 unpack-trees: enable fscache for sparse-checkout
When updating the skip-worktree bits in the index to align with new
values in a sparse-checkout file, Git scans the entire working
directory with lstat() calls. In a sparse-checkout, many of these
lstat() calls are for paths that do not exist.

Enable the fscache feature during this scan. Since enable_fscache()
calls nest, the disable_fscache() method decrements a counter and
would only clear the cache if that counter reaches zero.

In a local test of a repo with ~2.2 million paths, updating the index
with git read-tree -m -u HEAD with a sparse-checkout file containing
only /.gitattributes improved from 2-3 minutes to ~6 seconds.

Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:39 +01:00
Ben Peart
df825b45d1 fscache: fscache takes an initial size
Update enable_fscache() to take an optional initial size parameter which is
used to initialize the hashmap so that it can avoid having to rehash as
additional entries are added.

Add a separate disable_fscache() macro to make the code clearer and easier
to read.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:39 +01:00
Ben Peart
7fd352ff64 fscache: add fscache hit statistics
Track fscache hits and misses for lstat and opendir requests.  Reporting of
statistics is done when the cache is disabled for the last time and freed
and is only reported if GIT_TRACE_FSCACHE is set.

Sample output is:

11:33:11.836428 compat/win32/fscache.c:433 fscache: lstat 3775, opendir 263, total requests/misses 4052/269

Signed-off-by: Ben Peart <benpeart@microsoft.com>
2026-02-02 18:10:39 +01:00
Ben Peart
c92f2f7a34 mem_pool: add GIT_TRACE_MEMPOOL support
Add tracing around initializing and discarding mempools. In discard report
on the amount of memory unused in the current block to help tune setting
the initial_size.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
2026-02-02 18:10:39 +01:00
Ben Peart
5b6d26df40 fscache: add GIT_TEST_FSCACHE support
Add support to fscache to enable running the entire test suite with the
fscache enabled.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
2026-02-02 18:10:39 +01:00
Ben Peart
12f3aea29d fscache: use FindFirstFileExW to avoid retrieving the short name
Use FindFirstFileExW with FindExInfoBasic to avoid forcing NTFS to look up
the short name.  Also switch to a larger (64K vs 4K) buffer using
FIND_FIRST_EX_LARGE_FETCH to minimize round trips to the kernel.

In a repo with ~200K files, this drops warm cache status times from 3.19
seconds to 2.67 seconds for a 16% savings.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
2026-02-02 18:10:39 +01:00
Ben Peart
e0773980fe Enable the filesystem cache (fscache) in refresh_index().
On file systems that support it, this can dramatically speed up operations
like add, commit, describe, rebase, reset, rm that would otherwise have to
lstat() every file to "re-match" the stat information in the index to that
of the file system.

On a synthetic repo with 1M files, "git reset" dropped from 52.02 seconds to
14.42 seconds for a savings of 72%.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
2026-02-02 18:10:38 +01:00
Takuto Ikuta
f04f932525 checkout.c: enable fscache for checkout again
This is retry of #1419.

I added flush_fscache macro to flush cached stats after disk writing
with tests for regression reported in #1438 and #1442.

git checkout checks each file path in sorted order, so cache flushing does not
make performance worse unless we have large number of modified files in
a directory containing many files.

Using chromium repository, I tested `git checkout .` performance when I
delete 10 files in different directories.
With this patch:
TotalSeconds: 4.307272
TotalSeconds: 4.4863595
TotalSeconds: 4.2975562
Avg: 4.36372923333333

Without this patch:
TotalSeconds: 20.9705431
TotalSeconds: 22.4867685
TotalSeconds: 18.8968292
Avg: 20.7847136

I confirmed this patch passed all tests in t/ with core_fscache=1.

Signed-off-by: Takuto Ikuta <tikuta@chromium.org>
2026-02-02 18:10:38 +01:00
Takuto Ikuta
deaa5a51ad fetch-pack.c: enable fscache for stats under .git/objects
When I do git fetch, git call file stats under .git/objects for each
refs. This takes time when there are many refs.

By enabling fscache, git takes file stats by directory traversing and that
improved the speed of fetch-pack for repository having large number of
refs.

In my windows workstation, this improves the time of `git fetch` for
chromium repository like below. I took stats 3 times.

* With this patch
TotalSeconds: 9.9825165
TotalSeconds: 9.1862075
TotalSeconds: 10.1956256
Avg: 9.78811653333333

* Without this patch
TotalSeconds: 15.8406702
TotalSeconds: 15.6248053
TotalSeconds: 15.2085938
Avg: 15.5580231

Signed-off-by: Takuto Ikuta <tikuta@chromium.org>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:38 +01:00
Jeff Hostetler
2fe9937172 dir.c: regression fix for add_excludes with fscache
Fix regression described in:
https://github.com/git-for-windows/git/issues/1392

which was introduced in:
b2353379bb

Problem Symptoms
================
When the user has a .gitignore file that is a symlink, the fscache
optimization introduced above caused the stat-data from the symlink,
rather that of the target file, to be returned.  Later when the ignore
file was read, the buffer length did not match the stat.st_size field
and we called die("cannot use <path> as an exclude file")

Optimization Rationale
======================
The above optimization calls lstat() before open() primarily to ask
fscache if the file exists.  It gets the current stat-data as a side
effect essentially for free (since we already have it in memory).
If the file does not exist, it does not need to call open().  And
since very few directories have .gitignore files, we can greatly
reduce time spent in the filesystem.

Discussion of Fix
=================
The above optimization calls lstat() rather than stat() because the
fscache only intercepts lstat() calls.  Calls to stat() stay directed
to the mingw_stat() completly bypassing fscache.  Furthermore, calls
to mingw_stat() always call {open, fstat, close} so that symlinks are
properly dereferenced, which adds *additional* open/close calls on top
of what the original code in dir.c is doing.

Since the problem only manifests for symlinks, we add code to overwrite
the stat-data when the path is a symlink.  This preserves the effect of
the performance gains provided by the fscache in the normal case.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-02-02 18:10:38 +01:00
Jeff Hostetler
4cc5912579 fscache: make fscache_enabled() public
Make fscache_enabled() function public rather than static.
Remove unneeded fscache_is_enabled() function.
Change is_fscache_enabled() macro to call fscache_enabled().

is_fscache_enabled() now takes a pathname so that the answer
is more precise and mean "is fscache enabled for this pathname",
since fscache only stores repo-relative paths and not absolute
paths, we can avoid attempting lookups for absolute paths.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-02-02 18:10:38 +01:00
Jeff Hostetler
957859f626 dir.c: make add_excludes aware of fscache during status
Teach read_directory_recursive() and add_excludes() to
be aware of optional fscache and avoid trying to open()
and fstat() non-existant ".gitignore" files in every
directory in the worktree.

The current code in add_excludes() calls open() and then
fstat() for a ".gitignore" file in each directory present
in the worktree.  Change that when fscache is enabled to
call lstat() first and if present, call open().

This seems backwards because both lstat needs to do more
work than fstat.  But when fscache is enabled, fscache will
already know if the .gitignore file exists and can completely
avoid the IO calls.  This works because of the lstat diversion
to mingw_lstat when fscache is enabled.

This reduced status times on a 350K file enlistment of the
Windows repo on a NVMe SSD by 0.25 seconds.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-02-02 18:10:38 +01:00
Jeff Hostetler
e56081b94c add: use preload-index and fscache for performance
Teach "add" to use preload-index and fscache features
to improve performance on very large repositories.

During an "add", a call is made to run_diff_files()
which calls check_remove() for each index-entry.  This
calls lstat().  On Windows, the fscache code intercepts
the lstat() calls and builds a private cache using the
FindFirst/FindNext routines, which are much faster.

Somewhat independent of this, is the preload-index code
which distributes some of the start-up costs across
multiple threads.

We need to keep the call to read_cache() before parsing the
pathspecs (and hence cannot use the pathspecs to limit any preload)
because parse_pathspec() is using the index to determine whether a
pathspec is, in fact, in a submodule. If we would not read the index
first, parse_pathspec() would not error out on a path that is inside
a submodule, and t7400-submodule-basic.sh would fail with

	not ok 47 - do not add files from a submodule

We still want the nice preload performance boost, though, so we simply
call read_cache_preload(&pathspecs) after parsing the pathspecs.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:38 +01:00
Johannes Schindelin
e5da8f7490 fscache: add a test for the dir-not-found optimization
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:38 +01:00
Jeff Hostetler
9de01b7f16 fscache: remember not-found directories
Teach FSCACHE to remember "not found" directories.

This is a performance optimization.

FSCACHE is a performance optimization available for Windows.  It
intercepts Posix-style lstat() calls into an in-memory directory
using FindFirst/FindNext.  It improves performance on Windows by
catching the first lstat() call in a directory, using FindFirst/
FindNext to read the list of files (and attribute data) for the
entire directory into the cache, and short-cut subsequent lstat()
calls in the same directory.  This gives a major performance
boost on Windows.

However, it does not remember "not found" directories.  When STATUS
runs and there are missing directories, the lstat() interception
fails to find the parent directory and simply return ENOENT for the
file -- it does not remember that the FindFirst on the directory
failed. Thus subsequent lstat() calls in the same directory, each
re-attempt the FindFirst.  This completely defeats any performance
gains.

This can be seen by doing a sparse-checkout on a large repo and
then doing a read-tree to reset the skip-worktree bits and then
running status.

This change reduced status times for my very large repo by 60%.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:38 +01:00
Jeff Hostetler
1d27d42582 fscache: add key for GIT_TRACE_FSCACHE
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:38 +01:00
Johannes Schindelin
e1956bffb4 Merge branch 'git-gui-askyesno'
These changes are necessary to support better Git for Windows' new
auto-update feature.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:37 +01:00
Karsten Blees
c7bec347d5 fscache: load directories only once
If multiple threads access a directory that is not yet in the cache, the
directory will be loaded by each thread. Only one of the results is added
to the cache, all others are leaked. This wastes performance and memory.

On cache miss, add a future object to the cache to indicate that the
directory is currently being loaded. Subsequent threads register themselves
with the future object and wait. When the first thread has loaded the
directory, it replaces the future object with the result and notifies
waiting threads.

Signed-off-by: Karsten Blees <blees@dcon.de>
2026-02-02 18:10:37 +01:00
Johannes Schindelin
2f254b499b git-gui--askyesno (mingw): use Git for Windows' icon, if available
For additional GUI goodness.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:37 +01:00
Karsten Blees
efb2db143b mingw: add a cache below mingw's lstat and dirent implementations
Checking the work tree status is quite slow on Windows, due to slow
`lstat()` emulation (git calls `lstat()` once for each file in the
index). Windows operating system APIs seem to be much better at scanning
the status of entire directories than checking single files.

Add an `lstat()` implementation that uses a cache for lstat data. Cache
misses read the entire parent directory and add it to the cache.
Subsequent `lstat()` calls for the same directory are served directly
from the cache.

Also implement `opendir()`/`readdir()`/`closedir()` so that they create
and use directory listings in the cache.

The cache doesn't track file system changes and doesn't plug into any
modifying file APIs, so it has to be explicitly enabled for git functions
that don't modify the working copy.

Note: in an earlier version of this patch, the cache was always active and
tracked file system changes via ReadDirectoryChangesW. However, this was
much more complex and had negative impact on the performance of modifying
git commands such as 'git checkout'.

Signed-off-by: Karsten Blees <blees@dcon.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:37 +01:00
Johannes Schindelin
2a24970bcf git-gui--askyesno: fix funny text wrapping
The text wrapping seems to be aligned to the right side of the Yes
button, leaving an awful lot of empty space.

Let's try to counter this by using pixel units.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:37 +01:00
Karsten Blees
2eae55f50e mingw: add infrastructure for read-only file system level caches
Add a macro to mark code sections that only read from the file system,
along with a config option and documentation.

This facilitates implementation of relatively simple file system level
caches without the need to synchronize with the file system.

Enable read-only sections for 'git status' and preload_index.

Signed-off-by: Karsten Blees <blees@dcon.de>
2026-02-02 18:10:37 +01:00
Karsten Blees
3af31fe4ff Win32: make the lstat implementation pluggable
Emulating the POSIX lstat API on Windows via GetFileAttributes[Ex] is quite
slow. Windows operating system APIs seem to be much better at scanning the
status of entire directories than checking single files. A caching
implementation may improve performance by bulk-reading entire directories
or reusing data obtained via opendir / readdir.

Make the lstat implementation pluggable so that it can be switched at
runtime, e.g. based on a config option.

Signed-off-by: Karsten Blees <blees@dcon.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:37 +01:00
Karsten Blees
adb55cab7e mingw: make the dirent implementation pluggable
Emulating the POSIX `dirent` API on Windows via
`FindFirstFile()`/`FindNextFile()` is pretty staightforward, however,
most of the information provided in the `WIN32_FIND_DATA` structure is
thrown away in the process. A more sophisticated implementation may
cache this data, e.g. for later reuse in calls to `lstat()`.

Make the `dirent` implementation pluggable so that it can be switched at
runtime, e.g. based on a config option.

Define a base DIR structure with pointers to `readdir()`/`closedir()`
that match the `opendir()` implementation (similar to vtable pointers in
Object-Oriented Programming). Define `readdir()`/`closedir()` so that
they call the function pointers in the `DIR` structure. This allows to
choose the `opendir()` implementation on a call-by-call basis.

Make the fixed-size `dirent.d_name` buffer a flex array, as `d_name` may
be implementation specific (e.g. a caching implementation may allocate a
`struct dirent` with _just_ the size needed to hold the `d_name` in
question).

Signed-off-by: Karsten Blees <blees@dcon.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:37 +01:00
Karsten Blees
9ebeafd91b Win32: dirent.c: Move opendir down
Move opendir down in preparation for the next patch.

Signed-off-by: Karsten Blees <blees@dcon.de>
2026-02-02 18:10:37 +01:00
Karsten Blees
86c0c24ad4 Win32: make FILETIME conversion functions public
We will use them in the upcoming "FSCache" patches (to accelerate
sequential lstat() calls).

Signed-off-by: Karsten Blees <blees@dcon.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:37 +01:00
Johannes Schindelin
36806f5e8c ci(macos): skip the git p4 tests (#5954)
Historically, the macOS jobs have always been among the longest-running
ones, and recently the `git p4` tests became another liability: They
started to fail much more often (maybe as of the switch away from the
`macos-13` pool?), requiring re-runs of the jobs that already were
responsible for long CI build times.

Of the 35 test scripts that exercise `git p4`, 32 are actually run on
macOS (3 are skipped for reasons like case-sensitivee filesystem), and
they take an accumulated runtime of over half an hour.

Furthermore, the `git p4` command is not really affected by Git for
Windows' patches, at least not as far as macOS is concerned, therefore
it is not only causing developer friction to have these long-running,
frequently failing tests, it is also quite wasteful: There has not been
a single instance so far where any `git p4` test failure in Git for
Windows had demonstrated an actionable bug.

So let's just disable those tests in the CI runs, at least on macOS.
2026-02-02 18:10:36 +01:00
Johannes Schindelin
9832b2867f git-svn: mark it as unsupported by the Git for Windows project (#5923)
There have been too many challenges supporting `git svn`, including lack
of participation in developing/maintaining the required stack.

See https://github.com/git-for-windows/git/issues/5405 for full details.
2026-02-02 18:10:36 +01:00
Johannes Schindelin
13f6cc2e9c ci(macos): skip the git p4 tests
Historically, the macOS jobs have always been among the longest-running
ones, and recently the `git p4` tests became another liability: They
started to fail much more often (maybe as of the switch away from the
`macos-13` pool?), requiring re-runs of the jobs that already were
responsible for long CI build times.

Of the 35 test scripts that exercise `git p4`, 32 are actually run on
macOS (3 are skipped for reasons like case-sensitivee filesystem), and
they take an accumulated runtime of over half an hour.

Furthermore, the `git p4` command is not really affected by Git for
Windows' patches, at least not as far as macOS is concerned, therefore
it is not only causing developer friction to have these long-running,
frequently failing tests, it is also quite wasteful: There has not been
a single instance so far where any `git p4` test failure in Git for
Windows had demonstrated an actionable bug.

While upstream Git is confident to have addressed the flakiness of the
`git p4` tests via ffff0bb0dac1 (Use Perforce arm64 binary on macOS CI
jobs, 2025-11-16) (which got slipped in at the 11th hour into the
v2.52.0 release, fast-tracked without ever hitting `seen` even after
-rc2 was released), I am not quite so confident, and besides, the
runtime penalty of running those tests in Git for Windows' CI runs is
still a worrisome burden.

So let's just disable those tests in the CI runs, at least on macOS.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:36 +01:00
Johannes Schindelin
4e6e6d8f27 Merge branch 'ready-for-upstream'
This is the branch thicket of patches in Git for Windows that are
considered ready for upstream. To keep them in a ready-to-submit shape,
they are kept as close to the beginning of the branch thicket as
possible.
2026-02-02 18:10:36 +01:00
Johannes Schindelin
dcafeddeec git-svn: mark it as unsupported by the Git for Windows project
There have been too many challenges supporting `git svn`, including lack
of participation in developing/maintaining the required stack.

See https://github.com/git-for-windows/git/issues/5405 for full details.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:36 +01:00
Johannes Schindelin
b7605e3fd4 t/t5571-prep-push-hook.sh: Add test with writing to stderr (#6063)
Git v2.53.0-rc0 included f406b895529 (Merge branch
'ar/run-command-hook', 2026-01-06), which caused a regression on
Windows. While this merge was reverted for independent reasons in
a3d1f391d35 (Revert "Merge branch 'ar/run-command-hook'", 2026-01-15),
it seems worthwhile to ensure that writing to standard error from a
`pre-push` hook remains unbroken.

The symptom, when running this regression test case against
v2.53.0-rc0.windows.1 is that the `git push` fails, with this message
printed to standard error:

.git/hooks/pre-push: line 2: /dev/stderr: No such file or
direct[61/1940]
   error: failed to push some refs to 'repo1'

When that hook runs, `/dev/stderr` is a symlink to `/proc/self/fd/2`, as
always, but `ls -l /proc/self/fd/` shows this in the failing run

  total 0
  lrwxrwxrwx 1 me 4096 0 Jan 27 14:34 0 -> pipe:[0]
  lrwxrwxrwx 1 me 4096 0 Jan 27 14:34 1 -> pipe:[0]
  lrwxrwxrwx 1 me 4096 0 Jan 27 14:34 2 -> pipe:[0]

instead of the expected contents (which are shown when running this
against v2.53.0-rc1.windows.1):

  total 0
  lrwxrwxrwx 1 me 4096 0 Jan 27 14:53 0 -> 'pipe:[0]'
  lrwxrwxrwx 1 me 4096 0 Jan 27 14:53 1 -> /dev/cons1
lrwxrwxrwx 1 me 4096 0 Jan 27 14:53 2 -> '/path/to/git/t/trash
directory.t5571-pre-push-hook/actual'

This suggests that the underlying reason might be that `stdout` has an
exclusive handle to that pipe, and opening `stderr` (which points to the
same pipe) fails because of that exclusively-opened `stdout` handle.

This closes https://github.com/git-for-windows/git/issues/6053.
2026-02-02 18:10:35 +01:00
Johannes Schindelin
b1ccc383e9 Merge branch 'check-whitespace-only-downstream'
To avoid `check-whitespace` failures when rebasing Git for Windows onto
new Git versions, let's limit that job's scope to downstream commits.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:35 +01:00
Johannes Schindelin
1fd85740a4 Merge branch 'reftable-vs-custom-allocators'
Currently not _strictly_ necessary, but still good to have.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:35 +01:00
Johannes Schindelin
72cc152761 credential-cache: handle ECONNREFUSED gracefully (#5329)
I should probably add some tests for this.
2026-02-02 18:10:34 +01:00
Johannes Schindelin
d8b13f1e7d Add experimental 'git survey' builtin (#5174)
This introduces `git survey` to Git for Windows ahead of upstream for
the express purpose of getting the path-based analysis in the hands of
more folks.

The inspiration of this builtin is
[`git-sizer`](https://github.com/github/git-sizer), but since that
command relies on `git cat-file --batch` to get the contents of objects,
it has limits to how much information it can provide.

This is mostly a rewrite of the `git survey` builtin that was introduced
into the `microsoft/git` fork in microsoft/git#667. That version had a
lot more bells and whistles, including an analysis much closer to what
`git-sizer` provides.

The biggest difference in this version is that this one is focused on
using the path-walk API in order to visit batches of objects based on a
common path. This allows identifying, for instance, the path that is
contributing the most to the on-disk size across all versions at that
path.

For example, here are the top ten paths contributing to my local Git
repository (which includes `microsoft/git` and `gitster/git`):

```
TOP FILES BY DISK SIZE
============================================================================
                                    Path | Count | Disk Size | Inflated Size
-----------------------------------------+-------+-----------+--------------
                       whats-cooking.txt |  1373 |  11637459 |      37226854
             t/helper/test-gvfs-protocol |     2 |   6847105 |      17233072
                      git-rebase--helper |     1 |   6027849 |      15269664
                          compat/mingw.c |  6111 |   5194453 |     463466970
             t/helper/test-parse-options |     1 |   3420385 |       8807968
                  t/helper/test-pkt-line |     1 |   3408661 |       8778960
      t/helper/test-dump-untracked-cache |     1 |   3408645 |       8780816
            t/helper/test-dump-fsmonitor |     1 |   3406639 |       8776656
                                po/vi.po |   104 |   1376337 |      51441603
                                po/de.po |   210 |   1360112 |      71198603
```

This kind of analysis has been helpful in identifying the reasons for
growth in a few internal monorepos. Those findings motivated the changes
in #5157 and #5171.

With this early version in Git for Windows, we can expand the reach of
the experimental tool in advance of it being contributed to the upstream
project.

Unfortunately, this will mean that in the next `microsoft/git` rebase,
Jeff Hostetler's version will need to be pulled out since there are
enough conflicts. These conflicts include how tables are stored and
generated, as the version in this PR is slightly more general to allow
for different kinds of data.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:34 +01:00
Derrick Stolee
fe741e9438 Add path walk API and its use in 'git pack-objects' (#5171)
This is a follow up to #5157 as well as motivated by the RFC in
gitgitgadget/git#1786.

We have ways of walking all objects, but it is focused on visiting a
single commit and then expanding the new trees and blobs reachable from
that commit that have not been visited yet. This means that objects
arrive without any locality based on their path.

Add a new "path walk API" that focuses on walking objects in batches
according to their type and path. This will walk all annotated tags, all
commits, all root trees, and then start a depth-first search among all
paths in the repo to collect trees and blobs in batches.

The most important application for this is being fast-tracked to Git for
Windows: `git pack-objects --path-walk`. This application of the path
walk API discovers the objects to pack via this batched walk, and
automatically groups objects that appear at a common path so they can be
checked for delta comparisons.

This use completely avoids any name-hash collisions (even the collisions
that sometimes occur with the new `--full-name-hash` option) and can be
much faster to compute since the first pass of delta calculations does
not waste time on objects that are unlikely to be diffable.

Some statistics are available in the commit messages.
2026-02-02 18:10:34 +01:00
Johannes Schindelin
b27729e123 pack-objects: create new name-hash algorithm (#5157)
This is an updated version of gitgitgadget/git#1785, intended for early
consumption into Git for Windows.

The idea here is to add a new `--full-name-hash` option to `git
pack-objects` and `git repack`. This adjusts the name-hash value used
for finding delta bases in such a way that uses the full path name with
a lower likelihood of collisions than the default name-hash algorithm.
In many repositories with name-hash collisions and many versions of
those paths, this can significantly reduce the size of a full repack. It
can also help in certain cases of `git push`, but only if the pack is
already artificially inflated by name-hash collisions; cases that find
"sibling" deltas as better choices become worse with `--full-name-hash`.

Thus, this option is currently recommended for full repacks of large
repos, and on client machines without reachability bitmaps.

Some care is taken to ignore this option when using bitmaps, either
writing bitmaps or using a bitmap walk during reads. The bitmap file
format contains name-hash values, but no way to indicate which function
is used, so compatibility is a concern for bitmaps. Future work could
explore this idea.

After this PR is merged, then the more-involved `--path-walk` option may
be considered.
2026-02-02 18:10:34 +01:00
Johannes Schindelin
da1d6773c2 Merge branch 'run-command-be-helpful-when-Git-LFS-fails-on-Windows-7'
Since Git LFS v3.5.x implicitly dropped Windows 7 support, we now want
users to be advised _what_ is going wrong on that Windows version. This
topic branch goes out of its way to provide users with such guidance.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:33 +01:00
Johannes Schindelin
e555cc00ed Merge branch 'Fallback-to-AppData-if-XDG-CONFIG-HOME-is-unset'
This topic branch adds support for a more Windows-native user-wide
config file than `XDG_CONFIG_HOME` (or `~/.config/`) will ever be.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:33 +01:00
Johannes Schindelin
089407ca0d Merge branch 'Fix-i686-build-with-GCC-v14'
This fixes a long-time compile warning turned error by GCC v14.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:33 +01:00
Johannes Schindelin
8b5fc78015 Merge branch 'run-t5601-and-t7406-with-symlinks-on-windows-10'
This topic branch contains a patch that made it into Git for Windows
v2.45.1 but not into Git v2.45.1 (because the latter does not come with
symlink support on Windows).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:33 +01:00
Johannes Schindelin
149556782f common-main.c: fflush stdout buffer when exit (#4901) 2026-02-02 18:10:33 +01:00
Johannes Schindelin
0d77daa687 win32: use native ANSI sequence processing, if possible (#4700)
Windows 10 version 1511 (also known as Anniversary Update), according to
https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
introduced native support for ANSI sequence processing. This allows
using colors from the entire 24-bit color range.

All we need to do is test whether the console's "virtual processing
support" can be enabled. If it can, we do not even need to start the
`console_thread` to handle ANSI sequences.

Incidentally, this addresses
https://github.com/git-for-windows/git/issues/3712.
2026-02-02 18:10:32 +01:00
Johannes Schindelin
26127c0d42 Additional error checks for issuing the windows.appendAtomically warning (#4528)
Another (hopefully clean) PR for showing the error warning about atomic
append on windows after failure on APFS, which returns EBADF not EINVAL.

Signed-off-by: David Lomas <dl3@pale-eds.co.uk>
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
2026-02-02 18:10:32 +01:00
Johannes Schindelin
e223df5827 Merge branch 'nano-server'
This patch adds a GitHub workflow (to be triggered manually) to allow
for conveniently verifying that Git and Scalar still work as intended in
Windows Nano Server (a relatively small container base image that is
frequently used where a "small Windows" is needed, e.g. in automation
;-))

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:32 +01:00
Johannes Schindelin
5e7e72b113 Lazy load libcurl, allowing for an SSL/TLS backend-specific libcurl (#4410)
As per
https://github.com/git-for-windows/git/issues/4350#issuecomment-1485041503,
the major block for upgrading Git for Windows' OpenSSL from v1.1 to v3
is the tricky part where such an upgrade would break `git fetch`/`git
clone` and `git push` because the libcurl depends on the OpenSSL DLL,
and the major version bump will _change_ the file name of said DLL.

To overcome that, the plan is to build libcurl flavors for each
supported SSL/TLS backend, aligning with the way MSYS2 builds libcurl,
then switch Git for Windows' SDK to the Secure Channel-flavored libcurl,
and teach Git to look for the specific flavor of libcurl corresponding
to the `http.sslBackend` setting (if that was configured).

Here is the PR to teach Git that trick.
2026-02-02 18:10:32 +01:00
Johannes Schindelin
8b753e2754 ARM64: Embed manifest properly (#4718)
Teach our ARM64 based builds to embed the manifest file correctly.

This fixes #4707
2026-02-02 18:10:31 +01:00
Johannes Schindelin
96b5c58220 Merge pull request #2974 from derrickstolee/maintenance-and-headless
Include Windows-specific maintenance and headless-git
2026-02-02 18:10:31 +01:00
Johannes Schindelin
65bffa24c7 Merge pull request #2506 from dscho/issue-2283
Allow running Git directly from `C:\Program Files\Git\mingw64\bin\git.exe`
2026-02-02 18:10:31 +01:00
Johannes Schindelin
0ede355f4f Add full mingw-w64-git (i.e. regular MSYS2 ecosystem) support (#5971)
Every once in a while, there are bug reports in Git for Windows' bug
tracker that describe an issue running [inside MSYS2
proper](https://gitforwindows.org/install-inside-msys2-proper), totally
ignoring the big, honking warning on top of [the
page](https://gitforwindows.org/install-inside-msys2-proper) that spells
out clearly that this is an unsupported use case.

At the same time, we cannot easily deflect and say "just use MSYS2
directly" (and leave the "and stop pestering us" out). We cannot do that
because there is only an _MSYS_ `git` package in MSYS2 (i.e. a Git that
uses the quite slow POSIX emulation layer provided by the MSYS2
runtime), but no `mingw-w64-git` package (which would be equivalent in
speed to Git for Windows).

In https://github.com/msys2/MINGW-packages/pull/26470, I am preparing to
change that. As part of that PR, I noticed and fixed a couple of issues
_in `git-for-windows/git` that prevented full support for
`mingw-w64-git` in MSYS2, such as problems with CLANG64 and UCRT64.

While at it, I simplified the entire setup to trust MSYS2's
`MINGW_PREFIX` & related environment variables instead of hard-coding
values like the installation prefix and what `MSYSTEM` to fall back on
if it is unset.
2026-02-02 18:10:31 +01:00
Johannes Schindelin
8adf96688c Skip linking the "dashed" git-<command>s for built-ins (#4252)
It is merely a historical wart that, say, `git-commit` exists in the
`libexec/git-core/` directory, a tribute to the original idea to let Git
be essentially a bunch of Unix shell scripts revolving around very few
"plumbing" (AKA low-level) commands.

Git has evolved a lot from there. These days, most of Git's
functionality is contained within the `git` executable, in the form of
"built-in" commands.

To accommodate for scripts that use the "dashed" form of Git commands,
even today, Git provides hard-links that make the `git` executable
available as, say, `git-commit`, just in case that an old script has not
been updated to invoke `git commit`.

Those hard-links do not come cheap: they take about half a minute for
every build of Git on Windows, they are mistaken for taking up huge
amounts of space by some Windows Explorer versions that do not
understand hard-links, and therefore many a "bug" report had to be
addressed.

The "dashed form" has been officially deprecated in Git version 1.5.4,
which was released on February 2nd, 2008, i.e. a very long time ago.
This deprecation was never finalized by skipping these hard-links, but
we can start the process now, in Git for Windows.

This addresses the concern raised in
https://github.com/git-for-windows/git/pull/4185#discussion_r1051661894
2026-02-02 18:10:30 +01:00
Johannes Schindelin
235716d21e Fix global repository field not being cleared (#4083)
It is checked for w.r.t. global repository struct down in the callstack
in compatibility layer for MinGW before being assigned in the function
that `free()`'d it.
2026-02-02 18:10:30 +01:00
Johannes Schindelin
31bcf2915e Fix Windows version resources (#4092)
Add `FileVersion`, which is a required string ([Microsoft
documentation](https://learn.microsoft.com/en-us/windows/win32/menurc/versioninfo-resource))
in the `StringFileInfo` block.
As not all required strings were present in the block, none were being
included.
Fixes #4090

After including the `FileVersion` string, all other defined strings are
now being included on executables.

File version information for `git.exe` has changed from:
```
PS C:\Program Files\Git\bin> [System.Diagnostics.FileVersionInfo]::GetVersionInfo("C:\Data\git-sdk-64\usr\src\git\git.exe") | Select-Object *

FileVersionRaw     : 2.38.1.1
ProductVersionRaw  : 2.38.1.1
Comments           :
CompanyName        :
FileBuildPart      : 1
FileDescription    :
FileMajorPart      : 2
FileMinorPart      : 38
FileName           : C:\Data\git-sdk-64\usr\src\git\git.exe
FilePrivatePart    : 1
FileVersion        :
InternalName       :
IsDebug            : False
IsPatched          : False
IsPrivateBuild     : False
IsPreRelease       : False
IsSpecialBuild     : False
Language           : English (United States)
LegalCopyright     :
LegalTrademarks    :
OriginalFilename   :
PrivateBuild       :
ProductBuildPart   : 1
ProductMajorPart   : 2
ProductMinorPart   : 38
ProductName        :
ProductPrivatePart : 1
ProductVersion     :
SpecialBuild       :
```

To the following:
```
PS C:\Program Files\Git\bin> [System.Diagnostics.FileVersionInfo]::GetVersionInfo("C:\Data\git-sdk-64\usr\src\git\git.exe") | Select-Object *

FileVersionRaw     : 2.38.1.1
ProductVersionRaw  : 2.38.1.1
Comments           :
CompanyName        : The Git Development Community
FileBuildPart      : 1
FileDescription    : Git for Windows
FileMajorPart      : 2
FileMinorPart      : 38
FileName           : C:\Data\git-sdk-64\usr\src\git\git.exe
FilePrivatePart    : 1
FileVersion        : 2.38.1.windows.1.10.g6ed65a6fab
InternalName       : git
IsDebug            : False
IsPatched          : False
IsPrivateBuild     : False
IsPreRelease       : False
IsSpecialBuild     : False
Language           : English (United States)
LegalCopyright     :
LegalTrademarks    :
OriginalFilename   : git.exe
PrivateBuild       :
ProductBuildPart   : 1
ProductMajorPart   : 2
ProductMinorPart   : 38
ProductName        : Git
ProductPrivatePart : 1
ProductVersion     : 2.38.1.windows.1.10.g6ed65a6fab
SpecialBuild       :
```

I wasn't really expecting `GIT_VERSION` to contain the Git commit, I was
hoping for just `2.38.1` or `2.38.1.1`, at least for the `FileVersion`
string.

Anybody know if it's possible to concatenate the `MAJOR`, `MINOR`,
`MICRO`, and `PATCHLEVEL` fields with dots, or if there's another
variable that can be used (with or without `PATCHLEVEL`)?
Alternatively, use the complete `GIT_VERSION` for both `FileVersion` and
`ProductVersion`.
2026-02-02 18:10:30 +01:00
Johannes Schindelin
04eafd0886 Merge pull request #3942 from rimrul/mingw-tsaware
MinGW: link as terminal server aware
2026-02-02 18:10:30 +01:00
Johannes Schindelin
7a087e0e7f Merge branch 'fsync-object-files-always'
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:30 +01:00
Johannes Schindelin
44ce36c47f Merge branch 'optionally-dont-append-atomically-on-windows'
Fix append failure issue under remote directories #2753

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:29 +01:00
Johannes Schindelin
49a54e17e7 Merge pull request #3875 from 1480c1/wine/detect_msys_tty
winansi: check result before using Name for pty
2026-02-02 18:10:29 +01:00
Johannes Schindelin
3efc561460 Merge pull request #3751 from rkitover/native-term
mingw: set $env:TERM=xterm-256color for newer OSes
2026-02-02 18:10:29 +01:00
Derrick Stolee
74f06ad817 Merge pull request #3791: Various fixes around safe.directory
The first three commits are rebased versions of those in gitgitgadget/git#1215. These allow the following:

1. Fix `git config --global foo.bar <path>` from allowing the `<path>`. As a bonus, users with a config value starting with `/` will not get a warning about "old-style" paths needing a "`%(prefix)/`".

2. When in WSL, the path starts with `/` so it needs to be interpolated properly. Update the warning to include `%(prefix)/` to get the right value for WSL users. (This is specifically for using Git for Windows from Git Bash, but in a WSL directory.)

3. When using WSL, the ownership check fails and reports an error message. This is noisy, and happens even if the user has marked the path with `safe.directory`. Remove that error message.
2026-02-02 18:10:29 +01:00
Johannes Schindelin
ee01a66a89 Merge pull request #3533 from PhilipOakley/hashliteral_t
Begin `unsigned long`->`size_t` conversion to support large files on Windows
2026-02-02 18:10:28 +01:00
Johannes Schindelin
2433cd45dc Merge pull request #3306 from PhilipOakley/vs-sln
Make Git for Windows start builds in modern Visual Studio
2026-02-02 18:10:28 +01:00
Johannes Schindelin
110b167658 Merge pull request #3349 from vdye/feature/ci-subtree-tests
Add `contrib/subtree` test execution to CI builds
2026-02-02 18:10:28 +01:00
Johannes Schindelin
ec8534c08d Merge pull request #3293 from pascalmuller/http-support-automatically-sending-client-certificate
http: Add support for enabling automatic sending of SSL client certificate
2026-02-02 18:10:28 +01:00
Johannes Schindelin
ff1ef3e7f2 Merge pull request #3220 from dscho/there-is-no-vs/master-anymore
Let the documentation reflect that there is no vs/master anymore
2026-02-02 18:10:28 +01:00
Johannes Schindelin
5c0926b288 Merge pull request #3165 from dscho/increase-allowed-length-of-interpreter-path
mingw: allow for longer paths in `parse_interpreter()`
2026-02-02 18:10:27 +01:00
Johannes Schindelin
1b9d977641 Merge pull request #3327 from dennisameling/fix-host-cpu
cmake(): allow setting HOST_CPU for cross-compilation
2026-02-02 18:10:27 +01:00
Johannes Schindelin
69890446a4 Merge pull request #2915 from dennisameling/windows-arm64-support
Windows arm64 support
2026-02-02 18:10:27 +01:00
Johannes Schindelin
726e592652 Merge pull request #2351 from PhilipOakley/vcpkg-tip
Vcpkg Install: detect lack of working Git, and note possible vcpkg time outs
2026-02-02 18:10:27 +01:00
Johannes Schindelin
02cbe2619c Merge 'git-gui/js/intent-to-add'
This merges the current version of the patch that tries to address Git
GUI's problems with intent-to-add files.

This patch will likely be improved substantially before it is merged
into Git GUI's main branch, but we want to have _something_ resembling a
fix already in Git for Windows v2.29.0.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:27 +01:00
Johannes Schindelin
0ac775733d Merge pull request #2655 from jglathe/jg/t0014_trace_extra_info
t/t0014: fix: eliminate additional lines from trace
2026-02-02 18:10:26 +01:00
Johannes Schindelin
643277409c Merge pull request #2714 from lbonanomi/crlf-scissors
Rationalize line endings for scissors-cleanup
2026-02-02 18:10:26 +01:00
Johannes Schindelin
dbaab26c33 Merge 'add-p-many-files'
This topic branch allows `add -p` and `add -i` with a large number of
files. It is kind of a hack that was never really meant to be
upstreamed. Let's see if we can do better in the built-in `add -p`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:26 +01:00
Johannes Schindelin
1e759ad94b Merge pull request #2618 from dscho/avoid-d/f-conflict-in-vs/master
ci: avoid d/f conflict in vs/master
2026-02-02 18:10:26 +01:00
Johannes Schindelin
8143b15428 Merge pull request #2535 from dscho/schannel-revoke-best-effort
Introduce and use the new "best effort" strategy for Secure Channel revoke checking
2026-02-02 18:10:25 +01:00
Johannes Schindelin
5bfc13c201 Merge pull request #2504 from dscho/access-repo-via-junction
Handle `git add <file>` where <file> traverses an NTFS junction
2026-02-02 18:10:25 +01:00
Johannes Schindelin
2fe32210dd Merge pull request #2501 from jeffhostetler/clink-debug-curl
clink.pl: fix MSVC compile script to handle libcurl-d.lib
2026-02-02 18:10:25 +01:00
Johannes Schindelin
78a487b970 Merge pull request #2488 from bmueller84/master
mingw: fix fatal error working on mapped network drives on Windows
2026-02-02 18:10:25 +01:00
Johannes Schindelin
27c9cb23a8 Merge pull request #2375 from assarbad/reintroduce-sideband-config
Config option to disable side-band-64k for transport
2026-02-02 18:10:24 +01:00
Johannes Schindelin
4adf5e3632 Update mimalloc to v2.2.7 (#6048)
After releasing v2.2.6, they followed up really quickly with a v2.2.7,
which indicates some urgency in taking this update. The diff of this PR
is pretty informative, too.

This closes https://github.com/git-for-windows/git/issues/6046
2026-02-02 18:10:24 +01:00
Johannes Schindelin
a062e95d38 Merge branch 'msys2-python'
In MSYS2, we have two Python interpreters at our disposal, so we can
include the Python stuff in the build.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:24 +01:00
Johannes Schindelin
4cd258cc3b Merge branch 'dont-clean-junctions'
This topic branch teaches `git clean` to respect NTFS junctions and Unix
bind mounts: it will now stop at those boundaries.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:24 +01:00
Thomas Braun
d79dacef79 t/t5571-prep-push-hook.sh: Add test with writing to stderr
The 2.53.0.rc0.windows release candidate had a regression where
writing to stderr from a pre-push hook would error out.

The regression was fixed in 2.53.0.rc1.windows and the test here ensures
that this stays fixed.

Signed-off-by: Thomas Braun <thomas.braun@virtuell-zuhause.de>
2026-02-02 18:10:23 +01:00
Johannes Schindelin
c5e15230f9 check-whitespace: avoid alerts about upstream commits
Every once in a while, whitespace errors are introduced in Git for
Windows' rebases to newer Git versions, simply by virtue of integrating
upstream commits that do not follow upstream Git's own whitespace rule.
In Git v2.50.0-rc0, for example, 03f2915541a4 (xdiff: disable
cleanup_records heuristic with --minimal, 2025-04-29) introduced a
trailing space.

Arguably, non-actionable alerts are worse than no alerts at all, so
let's suppress those alerts that we cannot do anything about, anyway.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:23 +01:00
Johannes Schindelin
75df29ef89 reftable: do make sure to use custom allocators
The reftable library goes out of its way to use its own set of allocator
functions that can be configured using `reftable_set_alloc()`. However,
Git does not configure this.

That is not typically a problem, except when Git uses a custom allocator
via some definitions in `git-compat-util.h`, as is the case in Git for
Windows (which switched away from the long-unmaintained nedmalloc to
mimalloc).

Then, it is quite possible that Git assigns a `strbuf` (allocated via
the custom allocator) to, say, the `refname` field of a
`reftable_log_record` in `write_transaction_table()`, and later on asks
the reftable library function `reftable_log_record_release()` to release
it, but that function was compiled without using `git-compat-util.h` and
hence calls regular `free()` (i.e. _not_ the custom allocator's own
function).

This has been a problem for a long time and it was a matter of some sort
of "luck" that 1) reftables are not commonly used on Windows, and 2)
mimalloc can often ignore gracefully when it is asked to release memory
that it has not allocated.

However, a recent update to `seen` brought this problem to the
forefront, letting t1460 fail in Git for Windows, with symptoms much in
the same way as the problem I had to address in d02c37c3e6ba
(t-reftable-basics: allow for `malloc` to be `#define`d, 2025-01-08)
where exit code 127 was also produced in lieu of
`STATUS_HEAP_CORRUPTION` (C0000374) because exit codes are only 7 bits
wide.

It was not possible to figure out what change in particular caused these
new failures within a reasonable time frame, as there are too many
changes in `seen` that conflict with Git for Windows' patches, I had to
stop the investigation after spending four hours on it fruitlessly.

To verify that this patch fixes the issue, I avoided using mimalloc and
temporarily patched in a "custom allocator" that would more reliably
point out problems, like this:

  diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
  index 68f38291f84c..9421d630b9f5 100644
  --- a/refs/reftable-backend.c
  +++ b/refs/reftable-backend.c
  @@ -353,6 +353,69 @@ static int reftable_be_fsync(int fd)
   	return fsync_component(FSYNC_COMPONENT_REFERENCE, fd);
   }

  +#define DEBUG_REFTABLE_ALLOC
  +#ifdef DEBUG_REFTABLE_ALLOC
  +#include "khash.h"
  +
  +static inline khint_t __ac_X31_hash_ptr(void *ptr)
  +{
  +	union {
  +		void *ptr;
  +		char s[sizeof(void *)];
  +	} u;
  +	size_t i;
  +	khint_t h;
  +
  +	u.ptr = ptr;
  +	h = (khint_t)*u.s;
  +	for (i = 0; i < sizeof(void *); i++)
  +		h = (h << 5) - h + (khint_t)u.s[i];
  +	return h;
  +}
  +
  +#define kh_ptr_hash_func(key) __ac_X31_hash_ptr(key)
  +#define kh_ptr_hash_equal(a, b) ((a) == (b))
  +
  +KHASH_INIT(ptr, void *, int, 0, kh_ptr_hash_func, kh_ptr_hash_equal)
  +
  +static kh_ptr_t *my_malloced;
  +
  +static void *my_malloc(size_t sz)
  +{
  +	int dummy;
  +	void *ptr = malloc(sz);
  +	if (ptr)
  +		kh_put_ptr(my_malloced, ptr, &dummy);
  +	return ptr;
  +}
  +
  +static void *my_realloc(void *ptr, size_t sz)
  +{
  +	int dummy;
  +	if (ptr) {
  +		khiter_t pos = kh_get_ptr(my_malloced, ptr);
  +		if (pos >= kh_end(my_malloced))
  +			die("Was not my_malloc()ed: %p", ptr);
  +		kh_del_ptr(my_malloced, pos);
  +	}
  +	ptr = realloc(ptr, sz);
  +	if (ptr)
  +		kh_put_ptr(my_malloced, ptr, &dummy);
  +	return ptr;
  +}
  +
  +static void my_free(void *ptr)
  +{
  +	if (ptr) {
  +		khiter_t pos = kh_get_ptr(my_malloced, ptr);
  +		if (pos >= kh_end(my_malloced))
  +			die("Was not my_malloc()ed: %p", ptr);
  +		kh_del_ptr(my_malloced, pos);
  +	}
  +	free(ptr);
  +}
  +#endif
  +
   static struct ref_store *reftable_be_init(struct repository *repo,
   					  const char *gitdir,
   					  unsigned int store_flags)
  @@ -362,6 +425,11 @@ static struct ref_store *reftable_be_init(struct repository *repo,
   	int is_worktree;
   	mode_t mask;

  +#ifdef DEBUG_REFTABLE_ALLOC
  +	my_malloced = kh_init_ptr();
  +	reftable_set_alloc(my_malloc, my_realloc, my_free);
  +#endif
  +
   	mask = umask(0);
   	umask(mask);

I briefly considered contributing this "custom allocator" patch, too,
but it is unwieldy (for example, it would not work at all when compiling
with mimalloc support) and it would only waste space (or even time, if a
compile flag was introduced and exercised as part of the CI builds).
Given that it is highly unlikely that Git will lose the new
`reftable_set_alloc()` call by mistake, I rejected that idea as simply
too wasteful.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:23 +01:00
Johannes Schindelin
61903c659a Merge branch 'drive-prefix'
This topic branch allows us to specify absolute paths without the drive
prefix e.g. when cloning.

Example:

	C:\Users\me> git clone https://github.com/git/git \upstream-git

This will clone into a new directory C:\upstream-git, in line with how
Windows interprets absolute paths.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:23 +01:00
Johannes Schindelin
618c1a49f1 Merge 'remote-hg-prerequisites' into HEAD
These fixes were necessary for Sverre Rabbelier's remote-hg to work,
but for some magic reason they are not necessary for the current
remote-hg. Makes you wonder how that one gets away with it.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:23 +01:00
Matthias Aßhauer
ff27f65ff1 credential-cache: handle ECONNREFUSED gracefully
In 245670c (credential-cache: check for windows specific errors, 2021-09-14)
we concluded that on Windows we would always encounter ENETDOWN where we
would expect ECONNREFUSED on POSIX systems, when connecting to unix sockets.
As reported in [1], we do encounter ECONNREFUSED on Windows if the
socket file doesn't exist, but the containing directory does and ENETDOWN if
neither exists. We should handle this case like we do on non-windows systems.

[1] https://github.com/git-for-windows/git/pull/4762#issuecomment-2545498245

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

Helped-by: M Hickford <mirth.hickford@gmail.com>
Signed-off-by: Matthias Aßhauer <mha1993@live.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:22 +01:00
Johannes Schindelin
1c4faa6680 survey: clearly note the experimental nature in the output
While this command is definitely something we _want_, chances are that
upstreaming this will require substantial changes.

We still want to be able to experiment with this before that, to focus
on what we need out of this command: To assist with diagnosing issues
with large repositories, as well as to help monitoring the growth and
the associated painpoints of such repositories.

To that end, we are about to integrate this command into
`microsoft/git`, to get the tool into the hands of users who need it
most, with the idea to iterate in close collaboration between these
users and the developers familar with Git's internals.

However, we will definitely want to avoid letting anybody have the
impression that this command, its exact inner workings, as well as its
output format, are anywhere close to stable. To make that fact utterly
clear (and thereby protect the freedom to iterate and innovate freely
before upstreaming the command), let's mark its output as experimental
in all-caps, as the first thing we do.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:22 +01:00
Matthias Aßhauer
9bd8b6dda0 t0301: actually test credential-cache on Windows
Commit 2406bf5 (Win32: detect unix socket support at runtime,
2024-04-03) introduced a runtime detection for whether the operating
system supports unix sockets for Windows, but a mistake snuck into the
tests. When building and testing Git without NO_UNIX_SOCKETS we
currently skip t0301-credential-cache on Windows if unix sockets are
supported and run the tests if they aren't.

Flip that logic to actually work the way it was intended.

Signed-off-by: Matthias Aßhauer <mha1993@live.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:22 +01:00
Derrick Stolee
e15b0f337c survey: add --top=<N> option and config
The 'git survey' builtin provides several detail tables, such as "top
files by on-disk size". The size of these tables defaults to 10,
currently.

Allow the user to specify this number via a new --top=<N> option or the
new survey.top config key.

Signed-off-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:22 +01:00
Matthias Aßhauer
6c78e58121 compat/mingw: drop outdated comment
This comment has been true for the longest time; The combination of the
two preceding commits made it incorrect, so let's drop that comment.

Signed-off-by: Matthias Aßhauer <mha1993@live.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:22 +01:00
Derrick Stolee
fbbd39233f survey: add report of "largest" paths
Since we are already walking our reachable objects using the path-walk API,
let's now collect lists of the paths that contribute most to different
metrics. Specifically, we care about

 * Number of versions.
 * Total size on disk.
 * Total inflated size (no delta or zlib compression).

This information can be critical to discovering which parts of the
repository are causing the most growth, especially on-disk size. Different
packing strategies might help compress data more efficiently, but the toal
inflated size is a representation of the raw size of all snapshots of those
paths. Even when stored efficiently on disk, that size represents how much
information must be processed to complete a command such as 'git blame'.

The exact disk size seems to be not quite robust enough for testing, as
could be seen by the `linux-musl-meson` job consistently failing, possibly
because of zlib-ng deflates differently: t8100.4(git survey
(default)) was failing with a symptom like this:

   TOTAL OBJECT SIZES BY TYPE
   ===============================================
   Object Type | Count | Disk Size | Inflated Size
   ------------+-------+-----------+--------------
  -    Commits |    10 |      1523 |          2153
  +    Commits |    10 |      1528 |          2153
         Trees |    10 |       495 |          1706
         Blobs |    10 |       191 |           101
  -       Tags |     4 |       510 |           528
  +       Tags |     4 |       547 |           528

This means: the disk size is unlikely something we can verify robustly.
Since zlib-ng seems to increase the disk size of the tags from 528 to
547, we cannot even assume that the disk size is always smaller than the
inflated size. We will most likely want to either skip verifying the
disk size altogether, or go for some kind of fuzzy matching, say, by
replacing `s/ 1[45][0-9][0-9] / ~1.5k /` and `s/ [45][0-9][0-9] / ~½k /`
or something like that.

Signed-off-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:22 +01:00
Matthias Aßhauer
6fe1792d20 compat/mingw: handle WSA errors in strerror
We map WSAGetLastError() errors to errno errors in winsock_error_to_errno(),
but the MSVC strerror() implementation only produces "Unknown error" for
most of them. Produce some more meaningful error messages in these
cases.

Our builds for ARM64 link against the newer UCRT strerror() that does know
these errors, so we won't change the strerror() used there.

The wording of the messages is copied from glibc strerror() messages.

Reported-by: M Hickford <mirth.hickford@gmail.com>
Signed-off-by: Matthias Aßhauer <mha1993@live.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:22 +01:00
Derrick Stolee
45c38ff2d4 survey: add ability to track prioritized lists
In future changes, we will make use of these methods. The intention is to
keep track of the top contributors according to some metric. We don't want
to store all of the entries and do a sort at the end, so track a
constant-size table and remove rows that get pushed out depending on the
chosen sorting algorithm.

Co-authored-by: Jeff Hostetler <git@jeffhostetler.com>
Signed-off-by; Jeff Hostetler <git@jeffhostetler.com>
Signed-off-by: Derrick Stolee <stolee@gmail.com>
2026-02-02 18:10:22 +01:00
Johannes Schindelin
7694f25a70 mingw: make sure errno is set correctly when socket operations fail
The winsock2 library provides functions that work on different data
types than file descriptors, therefore we wrap them.

But that is not the only difference: they also do not set `errno` but
expect the callers to enquire about errors via `WSAGetLastError()`.

Let's translate that into appropriate `errno` values whenever the socket
operations fail so that Git's code base does not have to change its
expectations.

This closes https://github.com/git-for-windows/git/issues/2404

Helped-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:22 +01:00
Derrick Stolee
997a7f8061 survey: show progress during object walk
Signed-off-by: Derrick Stolee <stolee@gmail.com>
2026-02-02 18:10:22 +01:00
Derrick Stolee
fee3aa19bf survey: summarize total sizes by object type
Now that we have explored objects by count, we can expand that a bit more to
summarize the data for the on-disk and inflated size of those objects. This
information is helpful for diagnosing both why disk space (and perhaps
clone or fetch times) is growing but also why certain operations are slow
because the inflated size of the abstract objects that must be processed is
so large.

Note: zlib-ng is slightly more efficient even at those small sizes. Even
between zlib versions, there are slight differences in compression. To
accommodate for that in the tests, not the exact numbers but some rough
approximations are validated (the test should validate `git survey`,
after all, not zlib).

Signed-off-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:22 +01:00
Johannes Schindelin
c8050f6ae5 ci: work around a problem with HTTP/2 vs libcurl v8.10.0
As reported in https://lore.kernel.org/git/ZuPKvYP9ZZ2mhb4m@pks.im/,
libcurl v8.10.0 had a regression that was picked up by Git's t5559.30
"large fetch-pack requests can be sent using chunked encoding".

This bug was fixed in libcurl v8.10.1.

Sadly, the macos-13 runner image was updated in the brief window between
these two libcurl versions, breaking each and every CI build, as
reported at https://github.com/git-for-windows/git/issues/5159.

This would usually not matter, we would just ignore the failing CI
builds until the macos-13 runner image is rebuilt in a couple of days,
and then the CI builds would succeed again.

However.

As has become the custom, a surprise Git version was released, and now
that Git for Windows wants to follow suit, since Git for Windows has
this custom of trying to never release a version with a failing CI
build, we _must_ work around it.

This patch implements this work-around, basically for the sake of Git
for Windows v2.46.2's CI build.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:21 +01:00
Derrick Stolee
6d45db5265 revision: create mark_trees_uninteresting_dense()
The sparse tree walk algorithm was created in d5d2e93577e (revision:
implement sparse algorithm, 2019-01-16) and involves using the
mark_trees_uninteresting_sparse() method. This method takes a repository
and an oidset of tree IDs, some of which have the UNINTERESTING flag and
some of which do not.

Create a method that has an equivalent set of preconditions but uses a
"dense" walk (recursively visits all reachable trees, as long as they
have not previously been marked UNINTERESTING). This is an important
difference from mark_tree_uninteresting(), which short-circuits if the
given tree has the UNINTERESTING flag.

A use of this method will be added in a later change, with a condition
set whether the sparse or dense approach should be used.

Signed-off-by: Derrick Stolee <stolee@gmail.com>
2026-02-02 18:10:21 +01:00
Johannes Schindelin
57dc6fe0e1 run-command: be helpful with Git LFS fails on Windows 7
Git LFS is now built with Go 1.21 which no longer supports Windows 7.
However, Git for Windows still wants to support Windows 7.

Ideally, Git LFS would re-introduce Windows 7 support until Git for
Windows drops support for Windows 7, but that's not going to happen:
https://github.com/git-for-windows/git/issues/4996#issuecomment-2176152565

The next best thing we can do is to let the users know what is
happening, and how to get out of their fix, at least.

This is not quite as easy as it would first seem because programs
compiled with Go 1.21 or newer will simply throw an exception and fail
with an Access Violation on Windows 7.

The only way I found to address this is to replicate the logic from Go's
very own `version` command (which can determine the Go version with
which a given executable was built) to detect the situation, and in that
case offer a helpful error message.

This addresses https://github.com/git-for-windows/git/issues/4996.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:21 +01:00
Ariel Lourenco
0ffc3fb598 Fallback to AppData if XDG_CONFIG_HOME is unset
In order to be a better Windows citizenship, Git should
save its configuration files on AppData folder. This can
enables git configuration files be replicated between machines
using the same Microsoft account logon which would reduce the
friction of setting up Git on new systems. Therefore, if
%APPDATA%\Git\config exists, we use it; otherwise
$HOME/.config/git/config is used.

Signed-off-by: Ariel Lourenco <ariellourenco@users.noreply.github.com>
2026-02-02 18:10:21 +01:00
Derrick Stolee
82d00d3aa0 survey: add object count summary
At the moment, nothing is obvious about the reason for the use of the
path-walk API, but this will become more prevelant in future iterations. For
now, use the path-walk API to sum up the counts of each kind of object.

For example, this is the reachable object summary output for my local repo:

REACHABLE OBJECT SUMMARY
========================
Object Type |  Count
------------+-------
       Tags |   1343
    Commits | 179344
      Trees | 314350
      Blobs | 184030

Signed-off-by: Derrick Stolee <stolee@gmail.com>
2026-02-02 18:10:21 +01:00
Derrick Stolee
f22c068462 survey: start pretty printing data in table form
When 'git survey' provides information to the user, this will be presented
in one of two formats: plaintext and JSON. The JSON implementation will be
delayed until the functionality is complete for the plaintext format.

The most important parts of the plaintext format are headers specifying the
different sections of the report and tables providing concreted data.

Create a custom table data structure that allows specifying a list of
strings for the row values. When printing the table, check each column for
the maximum width so we can create a table of the correct size from the
start.

The table structure is designed to be flexible to the different kinds of
output that will be implemented in future changes.

Signed-off-by: Derrick Stolee <stolee@gmail.com>
2026-02-02 18:10:21 +01:00
Jeff Hostetler
19c4520e22 survey: add command line opts to select references
By default we will scan all references in "refs/heads/", "refs/tags/"
and "refs/remotes/".

Add command line opts let the use ask for all refs or a subset of them
and to include a detached HEAD.

Signed-off-by: Jeff Hostetler <git@jeffhostetler.com>
Signed-off-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
2026-02-02 18:10:21 +01:00
Jeff Hostetler
393174616c survey: stub in new experimental 'git-survey' command
Start work on a new 'git survey' command to scan the repository
for monorepo performance and scaling problems.  The goal is to
measure the various known "dimensions of scale" and serve as a
foundation for adding additional measurements as we learn more
about Git monorepo scaling problems.

The initial goal is to complement the scanning and analysis performed
by the GO-based 'git-sizer' (https://github.com/github/git-sizer) tool.
It is hoped that by creating a builtin command, we may be able to take
advantage of internal Git data structures and code that is not
accessible from GO to gain further insight into potential scaling
problems.

Co-authored-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Jeff Hostetler <git@jeffhostetler.com>
Signed-off-by: Derrick Stolee <stolee@gmail.com>
2026-02-02 18:10:21 +01:00
Johannes Schindelin
ebafe20390 win32: ensure that localtime_r() is declared even in i686 builds
The `__MINGW64__` constant is defined, surprise, surprise, only when
building for a 64-bit CPU architecture.

Therefore using it as a guard to define `_POSIX_C_SOURCE` (so that
`localtime_r()` is declared, among other functions) is not enough, we
also need to check `__MINGW32__`.

Technically, the latter constant is defined even for 64-bit builds. But
let's make things a bit easier to understand by testing for both
constants.

Making it so fixes this compile warning (turned error in GCC v14.1):

  archive-zip.c: In function 'dos_time':
  archive-zip.c:612:9: error: implicit declaration of function 'localtime_r';
  did you mean 'localtime_s'? [-Wimplicit-function-declaration]
    612 |         localtime_r(&time, &tm);
        |         ^~~~~~~~~~~
        |         localtime_s

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:20 +01:00
Johannes Schindelin
28220a90e3 t5601/t7406(mingw): do run tests with symlink support
A long time ago, we decided to run tests in Git for Windows' SDK with
the default `winsymlinks` mode: copying instead of linking. This is
still the default mode of MSYS2 to this day.

However, this is not how most users run Git for Windows: As the majority
of Git for Windows' users seem to be on Windows 10 and newer, likely
having enabled Developer Mode (which allows creating symbolic links
without administrator privileges), they will run with symlink support
enabled.

This is the reason why it is crucial to get the fixes for CVE-2024-? to
the users, and also why it is crucial to ensure that the test suite
exercises the related test cases. This commit ensures the latter.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:20 +01:00
MinarKotonoha
662e2b13ea common-main.c: fflush stdout buffer upon exit
By default, the buffer type of Windows' `stdout` is unbuffered (_IONBF),
and there is no need to manually fflush `stdout`.

But some programs, such as the Windows Filtering Platform driver
provided by the security software, may change the buffer type of
`stdout` to full buffering. This nees `fflush(stdout)` to be called
manually, otherwise there will be no output to `stdout`.

Signed-off-by: MinarKotonoha <chengzhuo5@qq.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:20 +01:00
Johannes Schindelin
9868204c17 win32: use native ANSI sequence processing, if possible
Windows 10 version 1511 (also known as Anniversary Update), according to
https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
introduced native support for ANSI sequence processing. This allows
using colors from the entire 24-bit color range.

All we need to do is test whether the console's "virtual processing
support" can be enabled. If it can, we do not even need to start the
`console_thread` to handle ANSI sequences.

Or, almost all we need to do: When `console_thread()` does its work, it
uses the Unicode-aware `write_console()` function to write to the Win32
Console, which supports Git for Windows' implicit convention that all
text that is written is encoded in UTF-8. The same is not necessarily
true if native ANSI sequence processing is used, as the output is then
subject to the current code page. Let's ensure that the code page is set
to `CP_UTF8` as long as Git writes to it.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:20 +01:00
David Lomas
d793256688 mingw: suggest windows.appendAtomically in more cases
When running Git for Windows on a remote APFS filesystem, it would
appear that the `mingw_open_append()`/`write()` combination would fail
almost exactly like on some CIFS-mounted shares as had been reported in
https://github.com/git-for-windows/git/issues/2753, albeit with a
different `errno` value.

Let's handle that `errno` value just the same, by suggesting to set
`windows.appendAtomically=false`.

Signed-off-by: David Lomas <dl3@pale-eds.co.uk>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:20 +01:00
Johannes Schindelin
8deeb1d89e Add a GitHub workflow to verify that Git/Scalar work in Nano Server
In Git for Windows v2.39.0, we fixed a regression where `git.exe` would
no longer work in Windows Nano Server (frequently used in Docker
containers).

This GitHub workflow can be used to verify manually that the Git/Scalar
executables work in Nano Server.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:20 +01:00
Johannes Schindelin
c17d3cb3ff mingw: do load libcurl dynamically by default
This will help with Git for Windows' maintenance going forward: It
allows Git for Windows to switch its primary libcurl to a variant
without the OpenSSL backend, while still loading an alternate when
setting `http.sslBackend = openssl`.

This is necessary to avoid maintenance headaches with upgrading OpenSSL:
its major version name is encoded in the shared library's file name and
hence major version updates (temporarily) break libraries that are
linked against the OpenSSL library.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:19 +01:00
Matthias Aßhauer
edeb8fc60b git.rc: include winuser.h
winuser.h contains the definition of RT_MANIFEST that our LLVM based
toolchain needs to understand that we want to embed
compat/win32/git.manifest as an application manifest. It currently just
embeds it as additional data that Windows doesn't understand.

This also helps our GCC based toolchain understand that we only want one
copy embedded. It currently embeds one working assembly manifest and one
nearly identical, but useless copy as additional data.

This also teaches our Visual Studio based buildsystems to pick up the
manifest file from git.rc. This means we don't have to explicitly specify
it in contrib/buildsystems/Generators/Vcxproj.pm anymore. Slightly
counter-intuitively this also means we have to explicitly tell Cmake
not to embed a default manifest.

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

Signed-off-by: Matthias Aßhauer <mha1993@live.de>
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
2026-02-02 18:10:19 +01:00
Yuyi Wang
8000293e39 cmake: install headless-git.
headless-git is a git executable without opening a console window. It is
useful when other GUI executables want to call git. We should install it
together with git on Windows.

Signed-off-by: Yuyi Wang <Strawberry_Str@hotmail.com>
2026-02-02 18:10:19 +01:00
Johannes Schindelin
6f319a4227 http: when loading libcurl lazily, allow for multiple SSL backends
The previous commits introduced a compile-time option to load libcurl
lazily, but it uses the hard-coded name "libcurl-4.dll" (or equivalent
on platforms other than Windows).

To allow for installing multiple libcurl flavors side by side, where
each supports one specific SSL/TLS backend, let's first look whether
`libcurl-<backend>-4.dll` exists, and only use `libcurl-4.dll` as a fall
back.

That will allow us to ship with a libcurl by default that only supports
the Secure Channel backend for the `https://` protocol. This libcurl
won't suffer from any dependency problem when upgrading OpenSSL to a new
major version (which will change the DLL name, and hence break every
program and library that depends on it).

This is crucial because Git for Windows relies on libcurl to keep
working when building and deploying a new OpenSSL package because that
library is used by `git fetch` and `git clone`.

Note that this feature is by no means specific to Windows. On Ubuntu,
for example, a `git` built using `LAZY_LOAD_LIBCURL` will use
`libcurl.so.4` for `http.sslbackend=openssl` and `libcurl-gnutls.so.4`
for `http.sslbackend=gnutls`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:19 +01:00
Jeff Hostetler
3d7685d361 clink.pl: move default linker options for MSVC=1 builds
Move the default `-ENTRY` and `-SUBSYSTEM` arguments for
MSVC=1 builds from `config.mak.uname` into `clink.pl`.
These args are constant for console-mode executables.

Add support to `clink.pl` for generating a Win32 GUI application
using the `-mwindows` argument (to match how GCC does it).  This
changes the `-ENTRY` and `-SUBSYSTEM` arguments accordingly.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-02-02 18:10:19 +01:00
Johannes Schindelin
7f75726208 http: support lazy-loading libcurl also on Windows
This implements the Windows-specific support code, because everything is
slightly different on Windows, even loading shared libraries.

Note: I specifically do _not_ use the code from
`compat/win32/lazyload.h` here because that code is optimized for
loading individual functions from various system DLLs, while we
specifically want to load _many_ functions from _one_ DLL here, and
distinctly not a system DLL (we expect libcurl to be located outside
`C:\Windows\system32`, something `INIT_PROC_ADDR` refuses to work with).
Also, the `curl_easy_getinfo()`/`curl_easy_setopt()` functions are
declared as vararg functions, which `lazyload.h` cannot handle. Finally,
we are about to optionally override the exact file name that is to be
loaded, which is a goal contrary to `lazyload.h`'s design.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:19 +01:00
Johannes Schindelin
e8fb572152 http: optionally load libcurl lazily
This compile-time option allows to ask Git to load libcurl dynamically
at runtime.

Together with a follow-up patch that optionally overrides the file name
depending on the `http.sslBackend` setting, this kicks open the door for
installing multiple libcurl flavors side by side, and load the one
corresponding to the (runtime-)configured SSL/TLS backend.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:19 +01:00
Johannes Schindelin
4f767c3fc9 mingw: ignore HOMEDRIVE/HOMEPATH if it points to Windows' system directory
Internally, Git expects the environment variable `HOME` to be set, and
to point to the current user's home directory.

This environment variable is not set by default on Windows, and
therefore Git tries its best to construct one if it finds `HOME` unset.

There are actually two different approaches Git tries: first, it looks
at `HOMEDRIVE`/`HOMEPATH` because this is widely used in corporate
environments with roaming profiles, and a user generally wants their
global Git settings to be in a roaming profile.

Only when `HOMEDRIVE`/`HOMEPATH` is either unset or does not point to a
valid location, Git will fall back to using `USERPROFILE` instead.

However, starting with Windows Vista, for secondary logons and services,
the environment variables `HOMEDRIVE`/`HOMEPATH` point to Windows'
system directory (usually `C:\Windows\system32`).

That is undesirable, and that location is usually write-protected anyway.

So let's verify that the `HOMEDRIVE`/`HOMEPATH` combo does not point to
Windows' system directory before using it, falling back to `USERPROFILE`
if it does.

This fixes git-for-windows#2709

Initial-Path-by: Ivan Pozdeev <vano@mail.mipt.ru>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:18 +01:00
Jeff Hostetler
807ffc67e0 clink.pl: ignore no-stack-protector arg on MSVC=1 builds
Ignore the `-fno-stack-protector` compiler argument when building
with MSVC.  This will be used in a later commit that needs to build
a Win32 GUI app.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-02-02 18:10:18 +01:00
Johannes Schindelin
d1d783f9b2 mingw: allow git.exe to be used instead of the "Git wrapper"
Git for Windows wants to add `git.exe` to the users' `PATH`, without
cluttering the latter with unnecessary executables such as `wish.exe`.
To that end, it invented the concept of its "Git wrapper", i.e. a tiny
executable located in `C:\Program Files\Git\cmd\git.exe` (originally a
CMD script) whose sole purpose is to set up a couple of environment
variables and then spawn the _actual_ `git.exe` (which nowadays lives in
`C:\Program Files\Git\mingw64\bin\git.exe` for 64-bit, and the obvious
equivalent for 32-bit installations).

Currently, the following environment variables are set unless already
initialized:

- `MSYSTEM`, to make sure that the MSYS2 Bash and the MSYS2 Perl
  interpreter behave as expected, and

- `PLINK_PROTOCOL`, to force PuTTY's `plink.exe` to use the SSH
  protocol instead of Telnet,

- `PATH`, to make sure that the `bin` folder in the user's home
  directory, as well as the `/mingw64/bin` and the `/usr/bin`
  directories are included. The trick here is that the `/mingw64/bin/`
  and `/usr/bin/` directories are relative to the top-level installation
  directory of Git for Windows (which the included Bash interprets as
  `/`, i.e. as the MSYS pseudo root directory).

Using the absence of `MSYSTEM` as a tell-tale, we can detect in
`git.exe` whether these environment variables have been initialized
properly. Therefore we can call `C:\Program Files\Git\mingw64\bin\git`
in-place after this change, without having to call Git through the Git
wrapper.

Obviously, above-mentioned directories must be _prepended_ to the `PATH`
variable, otherwise we risk picking up executables from unrelated Git
installations. We do that by constructing the new `PATH` value from
scratch, appending `$HOME/bin` (if `HOME` is set), then the MSYS2 system
directories, and then appending the original `PATH`.

Side note: this modification of the `PATH` variable is independent of
the modification necessary to reach the executables and scripts in
`/mingw64/libexec/git-core/`, i.e. the `GIT_EXEC_PATH`. That
modification is still performed by Git, elsewhere, long after making the
changes described above.

While we _still_ cannot simply hard-link `mingw64\bin\git.exe` to `cmd`
(because the former depends on a couple of `.dll` files that are only in
`mingw64\bin`, i.e. calling `...\cmd\git.exe` would fail to load due to
missing dependencies), at least we can now avoid that extra process of
running the Git wrapper (which then has to wait for the spawned
`git.exe` to finish) by calling `...\mingw64\bin\git.exe` directly, via
its absolute path.

Testing this is in Git's test suite tricky: we set up a "new" MSYS
pseudo-root and copy the `git.exe` file into the appropriate location,
then verify that `MSYSTEM` is set properly, and also that the `PATH` is
modified so that scripts can be found in `$HOME/bin`, `/mingw64/bin/`
and `/usr/bin/`.

This addresses https://github.com/git-for-windows/git/issues/2283

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:18 +01:00
Jeff Hostetler
2e2f698342 config.mak.uname: add git.rc to MSVC builds
Teach MSVC=1 builds to depend on the `git.rc` file so that
the resulting executables have Windows-style resources and
version number information within them.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-02-02 18:10:18 +01:00
Jeff Hostetler
3c3cd2b517 vcbuild: add support for compiling Windows resource files
Create a wrapper for the Windows Resource Compiler (RC.EXE)
for use by the MSVC=1 builds. This is similar to the CL.EXE
and LIB.EXE wrappers used for the MSVC=1 builds.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-02-02 18:10:18 +01:00
Jeff Hostetler
2776758034 Makefile: clean up .ilk files when MSVC=1
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-02-02 18:10:18 +01:00
Jeff Hostetler
3236403d93 clink.pl: fix libexpatd.lib link error when using MSVC
When building with `make MSVC=1 DEBUG=1`, link to `libexpatd.lib`
rather than `libexpat.lib`.

It appears that the `vcpkg` package for "libexpat" has changed and now
creates `libexpatd.lib` for debug mode builds.  Previously, both debug
and release builds created a ".lib" with the same basename.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-02-02 18:10:18 +01:00
Johannes Schindelin
634b97810d Merge branch 'dscho-avoid-d-f-conflict-in-vs-master'
Merge this early to resolve merge conflicts early.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:18 +01:00
Johannes Schindelin
47d7ce745f max_tree_depth: lower it for clang builds in general on Windows
In 436a42215e5 (max_tree_depth: lower it for clangarm64 on Windows,
2025-04-23), I provided a work-around for a nasty issue with clangarm
builds, where the stack is exhausted before the maximal tree depth is
reached, and the resulting error cannot easily be handled by Git
(because it would require Windows-specific handling).

Turns out that this is not at all limited to ARM64. In my tests with
CLANG64 in MSYS2 on the GitHub Actions runners, the test t6700.4 failed
in the exact same way. What's worse: The limit needs to be quite a bit
lower for x86_64 than for aarch64. In aforementioned tests, the breaking
point was 1232: With 1231 it still worked as expected, with 1232 it
would fail with the `STATUS_STACK_OVERFLOW` incorrectly mapped to exit
code 127. For comparison, in my tests on GitHub Actions' Windows/ARM64
runners, the breaking point was 1439 instead.

Therefore the condition needs to be adapted once more, to accommodate
(with some safety margin) both aarch64 and x86_64 in clang-based builds
on Windows, to let that test pass.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:17 +01:00
Johannes Schindelin
505d490b5c windows: skip linking git-<command> for built-ins
It is merely a historical wart that, say, `git-commit` exists in the
`libexec/git-core/` directory, a tribute to the original idea to let Git
be essentially a bunch of Unix shell scripts revolving around very few
"plumbing" (AKA low-level) commands.

Git has evolved a lot from there. These days, most of Git's
functionality is contained within the `git` executable, in the form of
"built-in" commands.

To accommodate for scripts that use the "dashed" form of Git commands,
even today, Git provides hard-links that make the `git` executable
available as, say, `git-commit`, just in case that an old script has not
been updated to invoke `git commit`.

Those hard-links do not come cheap: they take about half a minute for
every build of Git on Windows, they are mistaken for taking up huge
amounts of space by some Windows Explorer versions that do not
understand hard-links, and therefore many a "bug" report had to be
addressed.

The "dashed form" has been officially deprecated in Git version 1.5.4,
which was released on February 2nd, 2008, i.e. a very long time ago.
This deprecation was never finalized by skipping these hard-links, but
we can start the process now, in Git for Windows.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:17 +01:00
Johannes Schindelin
56d23020de mingw: ensure valid CTYPE
A change between versions 2.4.1 and 2.6.0 of the MSYS2 runtime modified
how Cygwin's runtime (and hence Git for Windows' MSYS2 runtime
derivative) handles locales: d16a56306d (Consolidate wctomb/mbtowc calls
for POSIX-1.2008, 2016-07-20).

An unintended side-effect is that "cold-calling" into the POSIX
emulation will start with a locale based on the current code page,
something that Git for Windows is very ill-prepared for, as it expects
to be able to pass a command-line containing non-ASCII characters to the
shell without having those characters munged.

One symptom of this behavior: when `git clone` or `git fetch` shell out
to call `git-upload-pack` with a path that contains non-ASCII
characters, the shell tried to interpret the entire command-line
(including command-line parameters) as executable path, which obviously
must fail.

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

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:17 +01:00
Johannes Schindelin
58719bb028 mingw: always define ETC_* for MSYS2 environments
Special-casing even more configurations simply does not make sense.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:17 +01:00
Johannes Schindelin
222947b4fa mingw: rely on MSYS2's metadata instead of hard-coding it
MSYS2 defines some helpful environment variables, e.g. `MSYSTEM`. There
is code in Git for Windows to ensure that that `MSYSTEM` variable is
set, hard-coding a default.

However, the existing solution jumps through hoops to reconstruct the
proper default, and is even incomplete doing so, as we found out when we
extended it to support CLANGARM64.

This is absolutely unnecessary because there is already a perfectly
valid `MSYSTEM` value we can use at build time. This is even true when
building the MINGW32 variant on a MINGW64 system because `makepkg-mingw`
will override the `MSYSTEM` value as per the `MINGW_ARCH` array.

The same is equally true for the `/mingw64`, `/mingw32` and
`/clangarm64` prefix: those values are already available via the
`MINGW_PREFIX` environment variable, and we just need to pass that
setting through.

Only when `MINGW_PREFIX` is not set (as is the case in Git for Windows'
minimal SDK, where only `MSYSTEM` is guaranteed to be set correctly), we
use as fall-back the top-level directory whose name is the down-cased
value of the `MSYSTEM` variable.

Incidentally, this also broadens the support to all the configurations
supported by the MSYS2 project, i.e. clang64 & ucrt64, too.

Note: This keeps the same, hard-coded MSYSTEM platform support for CMake
as before, but drops it for Meson (because it is unclear how Meson could
do this in a more flexible manner).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:17 +01:00
Johannes Schindelin
4bf941968a mingw: only enable the MSYS2-specific stuff when compiling in MSYS2
The tell-tale is the presence of the `MSYSTEM` value while compiling, of
course. In that case, we want to ensure that `MSYSTEM` is set when
running `git.exe`, and also enable the magic MSYS2 tty detection.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:17 +01:00
Johannes Schindelin
298ff81724 mingw: set the prefix and HOST_CPU as per MSYS2's settings
MSYS2 already defines a couple of helpful environment variables, and we
can use those to infer the installation location as well as the CPU. No
need for hard-coding ;-)

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:17 +01:00
Johannes Schindelin
10bfa90252 mingw: avoid over-specifying --pic-executable
In bf2d5d8239e (Don't let ld strip relocations, 2016-01-16) (picked from
https://github.com/git-for-windows/git/pull/612/commits/6a237925bf10),
Git for Windows introduced the `-Wl,-pic-executable` flag, specifying
the exact entry point via `-e`. This required discerning between i686
and x86_64 code because the former required the symbol to be prefixed
with an underscore, the latter did not.

As per https://sourceware.org/bugzilla/show_bug.cgi?id=10865, the
specified symbols are already the default, though.

So let's drop the overly-specific definition.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:17 +01:00
Johannes Schindelin
5dfb8d9b26 mingw: only use -Wl,--large-address-aware for 32-bit builds
That option only matters there, and is in fact only really understood in
those builds; UCRT64 versions of GCC, for example, do not know what to
do with that option.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:17 +01:00
Johannes Schindelin
ee99a7ccca mingw: drop the -D_USE_32BIT_TIME_T option
This option was added in fa93bb20d72 (MinGW: Fix stat definitions to
work with MinGW runtime version 4.0, 2013-09-11), i.e. a _long_ time
ago. So long, in fact, that it still targeted MinGW. But we switched to
mingw-w64 in 2015, which seems not to share the problem, and therefore
does not require a fix.

Even worse: This flag is incompatible with UCRT64, which we are about to
support by way of upstreaming `mingw-w64-git` to the MSYS2 project, see
https://github.com/msys2/MINGW-packages/pull/26470 for details.

So let's send that option into its well-deserved retirement.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:17 +01:00
Johannes Schindelin
4e98b9b849 mingw: stop hard-coding CC = gcc
This is no longer true in general, not with supporting Clang out of the
box.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:17 +01:00
Andrey Zabavnikov
be899febc5 status: fix for old-style submodules with commondir
In f9b7573f6b00 (repository: free fields before overwriting them,
2017-09-05), Git was taught to release memory before overwriting it, but
357a03ebe9e0 (repository.c: move env-related setup code back to
environment.c, 2018-03-03) changed the code so that it would not
_always_ be overwritten.

As a consequence, the `commondir` attribute would point to
already-free()d memory.

This seems not to cause problems in core Git, but there are add-on
patches in Git for Windows where the `commondir` attribute is
subsequently used and causing invalid memory accesses e.g. in setups
containing old-style submodules (i.e. the ones with a `.git` directory
within theirs worktrees) that have `commondir` configured.

This fixes https://github.com/git-for-windows/git/pull/4083.

Signed-off-by: Andrey Zabavnikov <zabavnikov@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:16 +01:00
Kiel Hurley
be3c3d7372 Fix Windows version resources
Add FileVersion, which is a required field
As not all required fields were present, none were being included
Fixes #4090

Signed-off-by: Kiel Hurley <kielhurley@gmail.com>
2026-02-02 18:10:16 +01:00
Matthias Aßhauer
a21822501e MinGW: link as terminal server aware
Whith Windows 2000, Microsoft introduced a flag to the PE header to mark executables as
"terminal server aware". Windows terminal servers provide a redirected Windows directory and
redirected registry hives when launching legacy applications without this flag set. Since we
do not use any INI files in the Windows directory and don't write to the registry, we don't
need  this additional preparation. Telling the OS that we don't need this should provide
slightly improved startup times in terminal server environments.

When building for supported Windows Versions with MSVC the /TSAWARE linker flag is
automatically set, but MinGW requires us to set the --tsaware flag manually.

This partially addresses https://github.com/git-for-windows/git/issues/3935.

Signed-off-by: Matthias Aßhauer <mha1993@live.de>
2026-02-02 18:10:16 +01:00
Johannes Schindelin
e3bb377fb1 mingw: change core.fsyncObjectFiles = 1 by default
From the documentation of said setting:

	This boolean will enable fsync() when writing object files.

	This is a total waste of time and effort on a filesystem that
	orders data writes properly, but can be useful for filesystems
	that do not use journalling (traditional UNIX filesystems) or
	that only journal metadata and not file contents (OS X’s HFS+,
	or Linux ext3 with "data=writeback").

The most common file system on Windows (NTFS) does not guarantee that
order, therefore a sudden loss of power (or any other event causing an
unclean shutdown) would cause corrupt files (i.e. files filled with
NULs). Therefore we need to change the default.

Note that the documentation makes it sound as if this causes really bad
performance. In reality, writing loose objects is something that is done
only rarely, and only a handful of files at a time.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:16 +01:00
孙卓识
d3c2c74d84 Add config option windows.appendAtomically
Atomic append on windows is only supported on local disk files, and it may
cause errors in other situations, e.g. network file system. If that is the
case, this config option should be used to turn atomic append off.

Co-Authored-By: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: 孙卓识 <sunzhuoshi@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:16 +01:00
Christopher Degawa
0150490358 winansi: check result and Buffer before using Name
NtQueryObject under Wine can return a success but fill out no name.
In those situations, Wine will set Buffer to NULL, and set result to
the sizeof(OBJECT_NAME_INFORMATION).

Running a command such as

echo "$(git.exe --version 2>/dev/null)"

will crash due to a NULL pointer dereference when the code attempts to
null terminate the buffer, although, weirdly, removing the subshell or
redirecting stdout to a file will not trigger the crash.

Code has been added to also check Buffer and Length to ensure the check
is as robust as possible due to the current behavior being fragile at
best, and could potentially change in the future

This code is based on the behavior of NtQueryObject under wine and
reactos.

Signed-off-by: Christopher Degawa <ccom@randomderp.com>
2026-02-02 18:10:16 +01:00
Rafael Kitover
01fd0c63c0 mingw: $env:TERM="xterm-256color" for newer OSes
For Windows builds >= 15063 set $env:TERM to "xterm-256color" instead of
"cygwin" because they have a more capable console system that supports
this. Also set $env:COLORTERM="truecolor" if unset.

$env:TERM is initialized so that ANSI colors in color.c work, see
29a3963484 (Win32: patch Windows environment on startup, 2012-01-15).

See git-for-windows/git#3629 regarding problems caused by always setting
$env:TERM="cygwin".

This is the same heuristic used by the Cygwin runtime.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:16 +01:00
Derrick Stolee
d27654c585 compat/mingw.c: do not warn when failing to get owner
In the case of Git for Windows (say, in a Git Bash window) running in a
Windows Subsystem for Linux (WSL) directory, the GetNamedSecurityInfoW()
call in is_path_owned_By_current_side() returns an error code other than
ERROR_SUCCESS. This is consistent behavior across this boundary.

In these cases, the owner would always be different because the WSL
owner is a different entity than the Windows user.

The change here is to suppress the error message that looks like this:

  error: failed to get owner for '//wsl.localhost/...' (1)

Before this change, this warning happens for every Git command,
regardless of whether the directory is marked with safe.directory.

Signed-off-by: Derrick Stolee <derrickstolee@github.com>
2026-02-02 18:10:15 +01:00
Philip Oakley
12e8ed0f18 hash-object: add a >4GB/LLP64 test case using filtered input
To verify that the `clean` side of the `clean`/`smudge` filter code is
correct with regards to LLP64 (read: to ensure that `size_t` is used
instead of `unsigned long`), here is a test case using a trivial filter,
specifically _not_ writing anything to the object store to limit the
scope of the test case.

As in previous commits, the `big` file from previous test cases is
reused if available, to save setup time, otherwise re-generated.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:15 +01:00
Philip Oakley
47c7ebc010 CMake: show Win32 and Generator_platform build-option values
Ensure key CMake option values are part of the CMake output to
facilitate user support when tool updates impact the wider CMake
actions, particularly ongoing 'improvements' in Visual Studio.

These CMake displays perform the same function as the build-options.txt
provided in the main Git for Windows. CMake is already chatty.
The setting of CMAKE_EXPORT_COMPILE_COMMANDS is also reported.

Include the environment's CMAKE_EXPORT_COMPILE_COMMANDS value which
may have been propogated to CMake's internal value.

Testing the CMAKE_EXPORT_COMPILE_COMMANDS processing can be difficult
in the Visual Studio environment, as it may be cached in many places.
The 'environment' may include the OS, the user shell, CMake's
own environment, along with the Visual Studio presets and caches.

See previous commit for arefacts that need removing for a clean test.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
2026-02-02 18:10:15 +01:00
Derrick Stolee
2a1b51df93 setup: properly use "%(prefix)/" when in WSL
Signed-off-by: Derrick Stolee <derrickstolee@github.com>
2026-02-02 18:10:15 +01:00
Philip Oakley
75438ded8b hash-object: add another >4GB/LLP64 test case
To complement the `--stdin` and `--literally` test cases that verify
that we can hash files larger than 4GB on 64-bit platforms using the
LLP64 data model, here is a test case that exercises `hash-object`
_without_ any options.

Just as before, we use the `big` file from the previous test case if it
exists to save on setup time, otherwise generate it.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:15 +01:00
Philip Oakley
ea977e73fb CMakeLists: add default "x64-windows" arch for Visual Studio
In Git-for-Windows, work on using ARM64 has progressed. The
commit 2d94b77b27 (cmake: allow building for Windows/ARM64, 2020-12-04)
failed to notice that /compat/vcbuild/vcpkg_install.bat will default to
using the "x64-windows" architecture for the vcpkg installation if not set,
but CMake is not told of this default. Commit 635b6d99b3 (vcbuild: install
ARM64 dependencies when building ARM64 binaries, 2020-01-31) later updated
vcpkg_install.bat to accept an arch (%1) parameter, but retained the default.

This default is neccessary for the use case where the project directory is
opened directly in Visual Studio, which will find and build a CMakeLists.txt
file without any parameters, thus expecting use of the default setting.

Also Visual studio will generate internal .sln solution and .vcxproj project
files needed for some extension tools. Inform users of the additional
.sln/.vcxproj generation.

** How to test:
 rm -rf '.vs' # remove old visual studio settings
 rm -rf 'compat/vcbuild/vcpkg' # remove any vcpkg downloads
 rm -rf 'contrib/buildsystems/out' # remove builds & CMake artifacts
 with a fresh Visual Studio Community Edition, File>>Open>>(git *folder*)
   to load the project (which will take some time!).
 check for successful compilation.
The implicit .sln (etc.) are in the hidden .vs directory created by
Visual Studio.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
2026-02-02 18:10:15 +01:00
Philip Oakley
ba32090f42 hash-object --stdin: verify that it works with >4GB/LLP64
Just like the `hash-object --literally` code path, the `--stdin` code
path also needs to use `size_t` instead of `unsigned long` to represent
memory sizes, otherwise it would cause problems on platforms using the
LLP64 data model (such as Windows).

To limit the scope of the test case, the object is explicitly not
written to the object store, nor are any filters applied.

The `big` file from the previous test case is reused to save setup time;
To avoid relying on that side effect, it is generated if it does not
exist (e.g. when running via `sh t1007-*.sh --long --run=1,41`).

Signed-off-by: Philip Oakley <philipoakley@iee.email>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:15 +01:00
Philip Oakley
c980bcf324 .gitignore: add Visual Studio CMakeSetting.json file
The CMakeSettings.json file is tool generated. Developers may track it
should they provide additional settings.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
2026-02-02 18:10:15 +01:00
Philip Oakley
141c37bdc9 hash algorithms: use size_t for section lengths
Continue walking the code path for the >4GB `hash-object --literally`
test to the hash algorithm step for LLP64 systems.

This patch lets the SHA1DC code use `size_t`, making it compatible with
LLP64 data models (as used e.g. by Windows).

The interested reader of this patch will note that we adjust the
signature of the `git_SHA1DCUpdate()` function without updating _any_
call site. This certainly puzzled at least one reviewer already, so here
is an explanation:

This function is never called directly, but always via the macro
`platform_SHA1_Update`, which is usually called via the macro
`git_SHA1_Update`. However, we never call `git_SHA1_Update()` directly
in `struct git_hash_algo`. Instead, we call `git_hash_sha1_update()`,
which is defined thusly:

    static void git_hash_sha1_update(git_hash_ctx *ctx,
                                     const void *data, size_t len)
    {
        git_SHA1_Update(&ctx->sha1, data, len);
    }

i.e. it contains an implicit downcast from `size_t` to `unsigned long`
(before this here patch). With this patch, there is no downcast anymore.

With this patch, finally, the t1007-hash-object.sh "files over 4GB hash
literally" test case is fixed.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:15 +01:00
Philip Oakley
b756394d62 object-file.c: use size_t for header lengths
Continue walking the code path for the >4GB `hash-object --literally`
test. The `hash_object_file_literally()` function internally uses both
`hash_object_file()` and `write_object_file_prepare()`. Both function
signatures use `unsigned long` rather than `size_t` for the mem buffer
sizes. Use `size_t` instead, for LLP64 compatibility.

While at it, convert those function's object's header buffer length to
`size_t` for consistency. The value is already upcast to `uintmax_t` for
print format compatibility.

Note: The hash-object test still does not pass. A subsequent commit
continues to walk the call tree's lower level hash functions to identify
further fixes.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:15 +01:00
Philip Oakley
67e7b9480b hash-object: demonstrate a >4GB/LLP64 problem
On LLP64 systems, such as Windows, the size of `long`, `int`, etc. is
only 32 bits (for backward compatibility). Git's use of `unsigned long`
for file memory sizes in many places, rather than size_t, limits the
handling of large files on LLP64 systems (commonly given as `>4GB`).

Provide a minimum test for handling a >4GB file. The `hash-object`
command, with the  `--literally` and without `-w` option avoids
writing the object, either loose or packed. This avoids the code paths
hitting the `bigFileThreshold` config test code, the zlib code, and the
pack code.

Subsequent patches will walk the test's call chain, converting types to
`size_t` (which is larger in LLP64 data models) where appropriate.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:15 +01:00
Victoria Dye
79b84ada96 ci: run contrib/subtree tests in CI builds
Because `git subtree` (unlike most other `contrib` modules) is included as
part of the standard release of Git for Windows, its stability should be
verified as consistently as it is for the rest of git. By including the
`git subtree` tests in the CI workflow, these tests are as much of a gate to
merging and indicator of stability as the standard test suite.

Signed-off-by: Victoria Dye <vdye@github.com>
2026-02-02 18:10:14 +01:00
Pascal Muller
278adc237e http: optionally send SSL client certificate
This adds support for a new http.sslAutoClientCert config value.

In cURL 7.77 or later the schannel backend does not automatically send
client certificates from the Windows Certificate Store anymore.

This config value is only used if http.sslBackend is set to "schannel",
and can be used to opt in to the old behavior and force cURL to send
client certificates.

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

Signed-off-by: Pascal Muller <pascalmuller@gmail.com>
2026-02-02 18:10:14 +01:00
Johannes Schindelin
38ab1f0b07 compat/vcbuild: document preferred way to build in Visual Studio
We used to have that `make vcxproj` hack, but a hack it is. In the
meantime, we have a much cleaner solution: using CMake, either
explicitly, or even more conveniently via Visual Studio's built-in CMake
support (simply open Git's top-level directory via File>Open>Folder...).

Let's let the `README` reflect this.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:14 +01:00
Johannes Schindelin
7f53a0b2d7 mingw: allow for longer paths in parse_interpreter()
As reported in https://github.com/newren/git-filter-repo/pull/225, it
looks like 99 bytes is not really sufficient to represent e.g. the full
path to Python when installed via Windows Store (and this path is used
in the hasb bang line when installing scripts via `pip`).

Let's increase it to what is probably the maximum sensible path size:
MAX_PATH. This makes `parse_interpreter()` in line with what
`lookup_prog()` handles.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Vilius Šumskas <vilius@sumskas.eu>
2026-02-02 18:10:14 +01:00
Dennis Ameling
979a842f0d cmake(): allow setting HOST_CPU for cross-compilation
Git's regular Makefile mentions that HOST_CPU should be defined when cross-compiling Git: 37796bca76/Makefile (L438-L439)

This is then used to set the GIT_HOST_CPU variable when compiling Git: 37796bca76/Makefile (L1337-L1341)

Then, when the user runs `git version --build-options`, it returns that value: 37796bca76/help.c (L658)

This commit adds the same functionality to the CMake configuration. Users can now set -DHOST_CPU= to set the target architecture.

Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
2026-02-02 18:10:14 +01:00
Dennis Ameling
39d8a15ee6 Add schannel to curl installation
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
2026-02-02 18:10:14 +01:00
Philip Oakley
2cf4567e90 CMake: default Visual Studio generator has changed
Correct some wording and inform users regarding the Visual Studio
changes (from V16.6) to the default generator.

Subsequent commits ensure that Git for Windows can be directly
opened in modern Visual Studio without needing special configuration
of the CMakeLists settings.

It appeares that internally Visual Studio creates it's own version of the
.sln file (etc.) for extension tools that expect them.

The large number of references below document the shifting of Visual Studio
default and CMake setting options.

refs: https://docs.microsoft.com/en-us/search/?scope=C%2B%2B&view=msvc-150&terms=Ninja

1. https://docs.microsoft.com/en-us/cpp/linux/cmake-linux-configure?view=msvc-160
(note the linux bit)
 "In Visual Studio 2019 version 16.6 or later ***, Ninja is the default
generator for configurations targeting a remote system or WSL. For more
information, see this post on the C++ Team Blog
[https://devblogs.microsoft.com/cppblog/linux-development-with-visual-studio-first-class-support-for-gdbserver-improved-build-times-with-ninja-and-updates-to-the-connection-manager/].

For more information about these settings, see CMakeSettings.json reference
[https://docs.microsoft.com/en-us/cpp/build/cmakesettings-reference?view=msvc-160]."

2. https://docs.microsoft.com/en-us/cpp/build/cmake-presets-vs?view=msvc-160
"CMake supports two files that allow users to specify common configure,
build, and test options and share them with others: CMakePresets.json
and CMakeUserPresets.json."

" Both files are supported in Visual Studio 2019 version 16.10 or later.
***"
3. https://devblogs.microsoft.com/cppblog/linux-development-with-visual-studio-first-class-support-for-gdbserver-improved-build-times-with-ninja-and-updates-to-the-connection-manager/
" Ninja has been the default generator (underlying build system) for
CMake configurations targeting Windows for some time***, but in Visual
Studio 2019 version 16.6 Preview 3*** we added support for Ninja on Linux."

4. https://docs.microsoft.com/en-us/cpp/build/cmakesettings-reference?view=msvc-160
" `generator`: specifies CMake generator to use for this configuration.
May be one of:

    Visual Studio 2019 only:
        Visual Studio 16 2019
        Visual Studio 16 2019 Win64
        Visual Studio 16 2019 ARM

    Visual Studio 2017 and later:
        Visual Studio 15 2017
        Visual Studio 15 2017 Win64
        Visual Studio 15 2017 ARM
        Visual Studio 14 2015
        Visual Studio 14 2015 Win64
        Visual Studio 14 2015 ARM
        Unix Makefiles
        Ninja

Because Ninja is designed for fast build speeds instead of flexibility
and function, it is set as the default. However, some CMake projects may
be unable to correctly build using Ninja. If this occurs, you can
instruct CMake to generate Visual Studio projects instead.

To specify a Visual Studio generator in Visual Studio 2017, open the
settings editor from the main menu by choosing CMake | Change CMake
Settings. Delete "Ninja" and type "V". This activates IntelliSense,
which enables you to choose the generator you want."

"To specify a Visual Studio generator in Visual Studio 2019, right-click
on the CMakeLists.txt file in Solution Explorer and choose CMake
Settings for project > Show Advanced Settings > CMake Generator.

When the active configuration specifies a Visual Studio generator, by
default MSBuild.exe is invoked with` -m -v:minimal` arguments."

5. https://docs.microsoft.com/en-us/cpp/build/cmake-presets-vs?view=msvc-160#enable-cmakepresetsjson-integration-in-visual-studio-2019
"Enable CMakePresets.json integration in Visual Studio 2019

CMakePresets.json integration isn't enabled by default in Visual Studio
2019. You can enable it for all CMake projects in Tools > Options >
CMake > General: (tick a box)" ... see more.

6. https://docs.microsoft.com/en-us/cpp/build/cmakesettings-reference?view=msvc-140
(whichever v140 is..)
"CMake projects are supported in Visual Studio 2017 and later."

7. https://docs.microsoft.com/en-us/cpp/overview/what-s-new-for-cpp-2017?view=msvc-150
"Support added for the CMake Ninja generator."

8. https://docs.microsoft.com/en-us/cpp/overview/what-s-new-for-cpp-2017?view=msvc-150#cmake-support-via-open-folder
"CMake support via Open Folder
Visual Studio 2017 introduces support for using CMake projects without
converting to MSBuild project files (.vcxproj). For more information,
see CMake projects in Visual
Studio[https://docs.microsoft.com/en-us/cpp/build/cmake-projects-in-visual-studio?view=msvc-150].
Opening CMake projects with Open Folder automatically configures the
environment for C++ editing, building, and debugging." ... +more!

9. https://docs.microsoft.com/en-us/cpp/build/cmake-presets-vs?view=msvc-160#supported-cmake-and-cmakepresetsjson-versions
"Visual Studio reads and evaluates CMakePresets.json and
CMakeUserPresets.json itself and doesn't invoke CMake directly with the
--preset option. So, CMake version 3.20 or later isn't strictly required
when you're building with CMakePresets.json inside Visual Studio. We
recommend using CMake version 3.14 or later."

10. https://docs.microsoft.com/en-us/cpp/build/cmake-presets-vs?view=msvc-160#enable-cmakepresetsjson-integration-in-visual-studio-2019
"If you don't want to enable CMakePresets.json integration for all CMake
projects, you can enable CMakePresets.json integration for a single
CMake project by adding a CMakePresets.json file to the root of the open
folder. You must close and reopen the folder in Visual Studio to
activate the integration.

11. https://docs.microsoft.com/en-us/cpp/build/cmake-presets-vs?view=msvc-160#default-configure-presets
***(doesn't actually say which version..)
"Default Configure Presets
If no CMakePresets.json or CMakeUserPresets.json file exists, or if
CMakePresets.json or CMakeUserPresets.json is invalid, Visual Studio
will fall back*** on the following default Configure Presets:

Windows example
JSON
{
  "name": "windows-default",
  "displayName": "Windows x64 Debug",
  "description": "Sets Ninja generator, compilers, x64 architecture,
build and install directory, debug build type",
  "generator": "Ninja",
  "binaryDir": "${sourceDir}/out/build/${presetName}",
  "architecture": {
    "value": "x64",
    "strategy": "external"
  },
  "cacheVariables": {
    "CMAKE_BUILD_TYPE": "Debug",
    "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}"
  },
  "vendor": {
    "microsoft.com/VisualStudioSettings/CMake/1.0": {
      "hostOS": [ "Windows" ]
    }
  }
},
"

Signed-off-by: Philip Oakley <philipoakley@iee.email>
2026-02-02 18:10:14 +01:00
Victoria Dye
7d91cd6d6a subtree: update contrib/subtree test target
The intention of this change is to align with how the top-level git
`Makefile` defines its own test target (which also internally calls
`$(MAKE) -C t/ all`). This change also ensures the consistency of
`make -C contrib/subtree test` with other testing in CI executions
(which rely on `$DEFAULT_TEST_TARGET` being defined as `prove`).

Signed-off-by: Victoria Dye <vdye@github.com>
2026-02-02 18:10:14 +01:00
Philip Oakley
81f3b95871 vcpkg_install: add comment regarding slow network connections
The vcpkg downloads may not succeed. Warn careful readers of the time out.

A simple retry will usually resolve the issue.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:13 +01:00
Johannes Schindelin
9078dfd973 git-gui: accommodate for intent-to-add files
As of Git v2.28.0, the diff for files staged via `git add -N` marks them
as new files. Git GUI was ill-prepared for that, and this patch teaches
Git GUI about them.

Please note that this will not even fix things with v2.28.0, as the
`rp/apply-cached-with-i-t-a` patches are required on Git's side, too.

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

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Pratyush Yadav <me@yadavpratyush.com>
2026-02-02 18:10:13 +01:00
Jens Glathe
3870ed72fe t0014: fix indentation
For some reason, this test case was indented with 4 spaces instead of 1
horizontal tab. The other test cases in the same test script are fine.

Signed-off-by: Jens Glathe <jens.glathe@oldschoolsolutions.biz>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:13 +01:00
Luke Bonanomi
b0660801ee commit: accept "scissors" with CR/LF line endings
This change enhances `git commit --cleanup=scissors` by detecting
scissors lines ending in either LF (UNIX-style) or CR/LF (DOS-style).

Regression tests are included to specifically test for trailing
comments after a CR/LF-terminated scissors line.

Signed-off-by: Luke Bonanomi <lbonanomi@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:13 +01:00
Dennis Ameling
73186ddbcc ci(vs-build) also build Windows/ARM64 artifacts
There are no Windows/ARM64 agents in GitHub Actions yet, therefore we
just skip adjusting the `vs-test` job for now.

Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:13 +01:00
Philip Oakley
e79df317fb vcpkg_install: detect lack of Git
The vcpkg_install batch file depends on the availability of a
working Git on the CMD path. This may not be present if the user
has selected the 'bash only' option during Git-for-Windows install.

Detect and tell the user about their lack of a working Git in the CMD
window.

Fixes #2348.
A separate PR https://github.com/git-for-windows/build-extra/pull/258
now highlights the recommended path setting during install.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
2026-02-02 18:10:13 +01:00
Dennis Ameling
4c07fece4c cmake: allow building for Windows/ARM64
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:13 +01:00
Ian Bearman
9ab3f336e2 vcbuild: add an option to install individual 'features'
In this context, a "feature" is a dependency combined with its own
dependencies.

Signed-off-by: Ian Bearman <ianb@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:13 +01:00
Ian Bearman
68933346b6 vcbuild: install ARM64 dependencies when building ARM64 binaries
Co-authored-by: Dennis Ameling <dennis@dennisameling.com>
Signed-off-by: Ian Bearman <ianb@microsoft.com>
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:13 +01:00
Johannes Schindelin
1eaae85b36 t3701: verify that we can add *lots* of files interactively
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:12 +01:00
Johannes Schindelin
e79815d934 t5505/t5516: fix white-space around redirectors
The convention in Git project's shell scripts is to have white-space
_before_, but not _after_ the `>` (or `<`).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:12 +01:00
Johannes Schindelin
0ab9505c28 http: use new "best effort" strategy for Secure Channel revoke checking
The native Windows HTTPS backend is based on Secure Channel which lets
the caller decide how to handle revocation checking problems caused by
missing information in the certificate or offline CRL distribution
points.

Unfortunately, cURL chose to handle these problems differently than
OpenSSL by default: while OpenSSL happily ignores those problems
(essentially saying "¯\_(ツ)_/¯"), the Secure Channel backend will error
out instead.

As a remedy, the "no revoke" mode was introduced, which turns off
revocation checking altogether. This is a bit heavy-handed. We support
this via the `http.schannelCheckRevoke` setting.

In https://github.com/curl/curl/pull/4981, we contributed an opt-in
"best effort" strategy that emulates what OpenSSL seems to do.

In Git for Windows, we actually want this to be the default. This patch
makes it so, introducing it as a new value for the
`http.schannelCheckRevoke" setting, which now becmes a tristate: it
accepts the values "false", "true" or "best-effort" (defaulting to the
last one).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:12 +01:00
Johannes Schindelin
01fbee75e0 mingw: implement a platform-specific strbuf_realpath()
There is a Win32 API function to resolve symbolic links, and we can use
that instead of resolving them manually. Even better, this function also
resolves NTFS junction points (which are somewhat similar to bind
mounts).

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

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:12 +01:00
Johannes Schindelin
24aaf209dc t5505/t5516: allow running without .git/branches/ in the templates
When we commit the template directory as part of `make vcxproj`, the
`branches/` directory is not actually commited, as it is empty.

Two tests were not prepared for that situation.

This developer tried to get rid of the support for `.git/branches/` a
long time ago, but that effort did not bear fruit, so the best we can do
is work around in these here tests.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:12 +01:00
Johannes Schindelin
349dbbd060 strbuf_realpath(): use platform-dependent API if available
Some platforms (e.g. Windows) provide API functions to resolve paths
much quicker. Let's offer a way to short-cut `strbuf_realpath()` on
those platforms.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:12 +01:00
Jeff Hostetler
a13c86801f clink.pl: fix MSVC compile script to handle libcurl-d.lib
Update clink.pl to link with either libcurl.lib or libcurl-d.lib
depending on whether DEBUG=1 is set.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:11 +01:00
Bjoern Mueller
56ad2e94fc mingw: fix fatal error working on mapped network drives on Windows
In 1e64d18 (mingw: do resolve symlinks in `getcwd()`) a problem was
introduced that causes git for Windows to stop working with certain
mapped network drives (in particular, drives that are mapped to
locations with long path names). Error message was "fatal: Unable to
read current working directory: No such file or directory". Present
change fixes this issue as discussed in
https://github.com/git-for-windows/git/issues/2480

Signed-off-by: Bjoern Mueller <bjoernm@gmx.de>
2026-02-02 18:10:11 +01:00
Thomas Braun
72fa6d5220 transport: optionally disable side-band-64k
Since commit 0c499ea60fda (send-pack: demultiplex a sideband stream with
status data, 2010-02-05) the send-pack builtin uses the side-band-64k
capability if advertised by the server.

Unfortunately this breaks pushing over the dump git protocol if used
over a network connection.

The detailed reasons for this breakage are (by courtesy of Jeff Preshing,
quoted from https://groups.google.com/d/msg/msysgit/at8D7J-h7mw/eaLujILGUWoJ):

	MinGW wraps Windows sockets in CRT file descriptors in order to
	mimic the functionality of POSIX sockets. This causes msvcrt.dll
	to treat sockets as Installable File System (IFS) handles,
	calling ReadFile, WriteFile, DuplicateHandle and CloseHandle on
	them. This approach works well in simple cases on recent
	versions of Windows, but does not support all usage patterns. In
	particular, using this approach, any attempt to read & write
	concurrently on the same socket (from one or more processes)
	will deadlock in a scenario where the read waits for a response
	from the server which is only invoked after the write. This is
	what send_pack currently attempts to do in the use_sideband
	codepath.

The new config option `sendpack.sideband` allows to override the
side-band-64k capability of the server, and thus makes the dumb git
protocol work.

Other transportation methods like ssh and http/https still benefit from
the sideband channel, therefore the default value of `sendpack.sideband`
is still true.

Signed-off-by: Thomas Braun <thomas.braun@byte-physics.de>
Signed-off-by: Oliver Schneider <oliver@assarbad.net>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:11 +01:00
Johannes Schindelin
2ab1d46a69 mingw: use mimalloc
Thorough benchmarking with repacking a subset of linux.git (the commit
history reachable from 93a6fefe2f ([PATCH] fix the SYSCTL=n compilation,
2007-02-28), to be precise) suggest that this allocator is on par, in
multi-threaded situations maybe even better than nedmalloc:

`git repack -adfq` with mimalloc, 8 threads:

31.166991900 27.576763800 28.712311000 27.373859000 27.163141900

`git repack -adfq` with nedmalloc, 8 threads:

31.915032900 27.149883100 28.244933700 27.240188800 28.580849500

In a different test using GitHub Actions build agents (probably
single-threaded, a core-strength of nedmalloc)):

`git repack -q -d -l -A --unpack-unreachable=2.weeks.ago` with mimalloc:

943.426 978.500 939.709 959.811 954.605

`git repack -q -d -l -A --unpack-unreachable=2.weeks.ago` with nedmalloc:

995.383 952.179 943.253 963.043 980.468

While these measurements were not executed with complete scientific
rigor, as no hardware was set aside specifically for these benchmarks,
it shows that mimalloc and nedmalloc perform almost the same, nedmalloc
with a bit higher variance and also slightly higher average (further
testing suggests that nedmalloc performs worse in multi-threaded
situations than in single-threaded ones).

In short: mimalloc seems to be slightly better suited for our purposes
than nedmalloc.

Seeing that mimalloc is developed actively, while nedmalloc ceased to
see any updates in eight years, let's use mimalloc on Windows instead.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:11 +01:00
Johannes Schindelin
ca6c3405a8 mingw: demonstrate a git add issue with NTFS junctions
NTFS junctions are somewhat similar in spirit to Unix bind mounts: they
point to a different directory and are resolved by the filesystem
driver. As such, they appear to `lstat()` as if they are directories,
not as if they are symbolic links.

_Any_ user can create junctions, while symbolic links can only be
created by non-administrators in Developer Mode on Windows 10. Hence
NTFS junctions are much more common "in the wild" than NTFS symbolic
links.

It was reported in https://github.com/git-for-windows/git/issues/2481
that adding files via an absolute path that traverses an NTFS junction:
since 1e64d18 (mingw: do resolve symlinks in `getcwd()`), we resolve not
only symbolic links but also NTFS junctions when determining the
absolute path of the current directory. The same is not true for `git
add <file>`, where symbolic links are resolved in `<file>`, but not NTFS
junctions.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:11 +01:00
Johannes Schindelin
32bd17203d mimalloc: offer a build-time option to enable it
By defining `USE_MIMALLOC`, Git can now be compiled with that
nicely-fast and small allocator.

Note that we have to disable a couple `DEVELOPER` options to build
mimalloc's source code, as it makes heavy use of declarations after
statements, among other things that disagree with Git's conventions.

We even have to silence some GCC warnings in non-DEVELOPER mode. For
example, the `-Wno-array-bounds` flag is needed because in `-O2` builds,
trying to call `NtCurrentTeb()` (which `_mi_thread_id()` does on
Windows) causes the bogus warning about a system header, likely related
to https://sourceforge.net/p/mingw-w64/mailman/message/37674519/ and to
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578:

C:/git-sdk-64-minimal/mingw64/include/psdk_inc/intrin-impl.h:838:1:
        error: array subscript 0 is outside array bounds of 'long long unsigned int[0]' [-Werror=array-bounds]
  838 | __buildreadseg(__readgsqword, unsigned __int64, "gs", "q")
      | ^~~~~~~~~~~~~~

Also: The `mimalloc` library uses C11-style atomics, therefore we must
require that standard when compiling with GCC if we want to use
`mimalloc` (instead of requiring "only" C99). This is what we do in the
CMake definition already, therefore this commit does not need to touch
`contrib/buildsystems/`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:11 +01:00
Johannes Schindelin
177a10fc2d mingw: include the Python parts in the build
While Git for Windows does not _ship_ Python (in order to save on
bandwidth), MSYS2 provides very fine Python interpreters that users can
easily take advantage of, by using Git for Windows within its SDK.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:10 +01:00
Johannes Schindelin
24c6749a3c clean: remove mount points when possible
Windows' equivalent to "bind mounts", NTFS junction points, can be
unlinked without affecting the mount target. This is clearly what users
expect to happen when they call `git clean -dfx` in a worktree that
contains NTFS junction points: the junction should be removed, and the
target directory of said junction should be left alone (unless it is
inside the worktree).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:10 +01:00
Johannes Schindelin
99a655240b mingw: prevent regressions with "drive-less" absolute paths
On Windows, there are several categories of absolute paths. One such
category starts with a backslash and is implicitly relative to the drive
associated with the current working directory. Example:

	c:
	git clone https://github.com/git-for-windows/git \G4W

should clone into C:\G4W.

Back in 2017, Juan Carlos Arevalo Baeza reported a bug in Git's handling
of those absolute paths was identified, and fixed. Let's make sure that
it stays fixed.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:10 +01:00
Johannes Schindelin
5a27f1a3f8 mimalloc: adjust for building inside Git
We want to compile mimalloc's source code as part of Git, rather than
requiring the code to be built as an external library: mimalloc uses a
CMake-based build, which is not necessarily easy to integrate into the
flavors of Git for Windows (which will be the main benefitting port).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Matthias Aßhauer <mha1993@live.de>
2026-02-02 18:10:10 +01:00
Johannes Schindelin
a2d95548ed clean: do not traverse mount points
It seems to be not exactly rare on Windows to install NTFS junction
points (the equivalent of "bind mounts" on Linux/Unix) in worktrees,
e.g. to map some development tools into a subdirectory.

In such a scenario, it is pretty horrible if `git clean -dfx` traverses
into the mapped directory and starts to "clean up".

Let's just not do that. Let's make sure before we traverse into a
directory that it is not a mount point (or junction).

This addresses https://github.com/git-for-windows/git/issues/607

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:10 +01:00
Johannes Schindelin
2add928bae Import the source code of mimalloc v2.2.7
Update to newer mimalloc versions like this:

  update_mimalloc ()
  {
      test $# = 1 || {
          echo "Need a mimalloc version" 1>&2;
          return 1
      };
      for oneline in 'mimalloc: adjust for building inside Git' 'Import the source code of mimalloc';
      do
          git revert -n HEAD^{/^"$oneline"} && git checkout HEAD -- Makefile && git commit -sm "Temporarily revert \"$oneline\"" -m 'In preparation for upgrading to a newer mimalloc version.' || return 1;
      done;
      for file in $(git show --format='%n' --name-only --diff-filter=A HEAD^{/^"Import the source code of mimalloc "}) compat/mimalloc/arena-abandon.c compat/mimalloc/free.c compat/mimalloc/libc.c compat/mimalloc/prim/prim.c compat/mimalloc/mimalloc-stats.h;
      do
          file2=${file#compat/mimalloc/};
          case "$file2" in
              segment-cache.c)
                  : no longer needed;
                  continue
              ;;
              bitmap.h | *.c)
                  file2=src/$file2
              ;;
              *.h)
                  file2=include/$file2
              ;;
          esac;
          mkdir -p "${file%/*}" && git -C /usr/src/mimalloc/ show "$1":$file2 > "$file" && git add "$file" || {
              echo "Failed: $file2 -> $file" 1>&2;
              return 1
          };
      done;
      conv_sed='sed -n "/^ *eval/d;/      /p"' && git commit -sm "Import the source code of mimalloc $1" -m "Update to newer mimalloc versions like this:" -m "$(set | sed -n '/^update_mimalloc *() *$/,/^}/{s/^./  &/;p}')" -m '  update_mimalloc $MIMALLOC_VERSION' -m 'For convenience, you can set `MIMALLOC_VERSION` and then run:' -m '  eval "$(git show -s <this-commit> | '"$conv_sed"')"' || return 1;
      git cherry-pick HEAD^{/^'mimalloc: adjust for building inside Git'} || return 1
  }

  update_mimalloc $MIMALLOC_VERSION

For convenience, you can set `MIMALLOC_VERSION` and then run:

  eval "$(git show -s <this-commit> | sed -n "/^ *eval/d;/      /p")"

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:10 +01:00
Johannes Schindelin
cff64d03c8 git-compat-util: avoid redeclaring _DEFAULT_SOURCE
We are about to vendor in `mimalloc`'s source code which we will want to
include `compat/posix.h` after defining that constant.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:10 +01:00
Johannes Schindelin
18d8514591 win32/pthread: avoid name clashes with winpthread
When asking the mingw-w64 variant of GCC to compile C11 code, it seems
to link implicitly to libwinpthread, which does implement a pthread
emulation (that is more complete than Git's).

In preparation for vendoring in mimalloc (which requires C11 support),
let's keep preferring Git's own pthread emulation.

To avoid linker errors where it thinks that the `pthread_self` and the
`pthread_create` symbols are defined twice, let's give our version a
`win32_` prefix, just like we already do for `pthread_join()`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:10 +01:00
Johannes Schindelin
d74db2d801 Merge branch 'fixes-from-the-git-mailing-list'
These fixes have been sent to the Git mailing list but have not been
picked up by the Git project yet.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:09 +01:00
Johannes Schindelin
53c5243711 Always auto-gc after calling a fast-import transport
After importing anything with fast-import, we should always let the
garbage collector do its job, since the objects are written to disk
inefficiently.

This brings down an initial import of http://selenic.com/hg from about
230 megabytes to about 14.

In the future, we may want to make this configurable on a per-remote
basis, or maybe teach fast-import about it in the first place.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:09 +01:00
Jeff King
f1b0016b13 grep: prevent ^$ false match at end of file
In some implementations, `regexec_buf()` assumes that it is fed lines;
Without `REG_NOTEOL` it thinks the end of the buffer is the end of a
line. Which makes sense, but trips up this case because we are not
feeding lines, but rather a whole buffer. So the final newline is not
the start of an empty line, but the true end of the buffer.

This causes an interesting bug:

  $ echo content >file.txt
  $ git grep --no-index -n '^$' file.txt
  file.txt:2:

This bug is fixed by making the end of the buffer consistently the end
of the final line.

The patch was applied from
https://lore.kernel.org/git/20250113062601.GD767856@coredump.intra.peff.net/

Reported-by: Olly Betts <olly@survex.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:09 +01:00
Sverre Rabbelier
026b2966ec remote-helper: check helper status after import/export
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
2026-02-02 18:10:09 +01:00
Sverre Rabbelier
b840ba6753 transport-helper: add trailing --
[PT: ensure we add an additional element to the argv array]

Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:09 +01:00
Sverre Rabbelier
1f061cab9c t9350: point out that refs are not updated correctly
This happens only when the corresponding commits are not exported in
the current fast-export run. This can happen either when the relevant
commit is already marked, or when the commit is explicitly marked
as UNINTERESTING with a negative ref by another argument.

This breaks fast-export basec remote helpers.

Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
2026-02-02 18:10:09 +01:00
Johannes Schindelin
7ca734fce0 Merge branch 'disallow-control-characters-in-sideband-channel'
This addresses:

- CVE-2024-52005:

	Insufficient neutralization of ANSI escape sequences in sideband
	payload can be used to mislead Git users into believing that
	certain remote-generated messages actually originate from Git.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
2026-02-02 18:10:08 +01:00
Johannes Schindelin
70565d9f20 unix-socket: avoid leak when initialization fails
When a Unix socket is initialized, the current directory's path is
stored so that the cleanup code can `chdir()` back to where it was
before exit.

If the path that needs to be stored exceeds the default size of the
`sun_path` attribute of `struct sockaddr_un` (which is defined as a
108-sized byte array on Linux), a larger buffer needs to be allocated so
that it can hold the path, and it is the responsibility of the
`unix_sockaddr_cleanup()` function to release that allocated memory.

In Git's CI, this stack allocation is not necessary because the code is
checked out to `/home/runner/work/git/git`. Concatenate the path
`t/trash directory.t0301-credential-cache/.cache/git/credential/socket`
and a terminating NUL, and you end up with 96 bytes, 12 shy of the
default `sun_path` size.

However, I use worktrees with slightly longer paths:
`/home/me/projects/git/yes/i/nest/worktrees/to/organize/them/` is more
in line with what I have. When I recently tried to locally reproduce a
failure of the `linux-leaks` CI job, this t0301 test failed (where it
had not failed in CI).

The reason: When `credential-cache` tries to reach its daemon initially
by calling `unix_sockaddr_init()`, it is expected that the daemon cannot
be reached (the idea is to spin up the daemon in that case and try
again). However, when this first call to `unix_sockaddr_init()` fails,
the code returns early from the `unix_stream_connect()` function
_without_ giving the cleanup code a chance to run, skipping the
deallocation of above-mentioned path.

The fix is easy: do not return early but instead go directly to the
cleanup code.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:08 +01:00
Johannes Schindelin
e6a90de08e sideband: do allow ANSI color sequences by default
The preceding two commits introduced special handling of the sideband
channel to neutralize ANSI escape sequences before sending the payload
to the terminal, and `sideband.allowControlCharacters` to override that
behavior.

However, some `pre-receive` hooks that are actively used in practice
want to color their messages and therefore rely on the fact that Git
passes them through to the terminal.

In contrast to other ANSI escape sequences, it is highly unlikely that
coloring sequences can be essential tools in attack vectors that mislead
Git users e.g. by hiding crucial information.

Therefore we can have both: Continue to allow ANSI coloring sequences to
be passed to the terminal, and neutralize all other ANSI escape
sequences.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:08 +01:00
Johannes Schindelin
268465a5f7 sideband: introduce an "escape hatch" to allow control characters
The preceding commit fixed the vulnerability whereas sideband messages
(that are under the control of the remote server) could contain ANSI
escape sequences that would be sent to the terminal verbatim.

However, this fix may not be desirable under all circumstances, e.g.
when remote servers deliberately add coloring to their messages to
increase their urgency.

To help with those use cases, give users a way to opt-out of the
protections: `sideband.allowControlCharacters`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:08 +01:00
Johannes Schindelin
873fe23b56 sideband: mask control characters
The output of `git clone` is a vital component for understanding what
has happened when things go wrong. However, these logs are partially
under the control of the remote server (via the "sideband", which
typically contains what the remote `git pack-objects` process sends to
`stderr`), and is currently not sanitized by Git.

This makes Git susceptible to ANSI escape sequence injection (see
CWE-150, https://cwe.mitre.org/data/definitions/150.html), which allows
attackers to corrupt terminal state, to hide information, and even to
insert characters into the input buffer (i.e. as if the user had typed
those characters).

To plug this vulnerability, disallow any control character in the
sideband, replacing them instead with the common `^<letter/symbol>`
(e.g. `^[` for `\x1b`, `^A` for `\x01`).

There is likely a need for more fine-grained controls instead of using a
"heavy hammer" like this, which will be introduced subsequently.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-02-02 18:10:08 +01:00
Johannes Schindelin
a7ac2046fa Start the merging-rebase to v2.53.0
This commit starts the rebase of 2fab893deb18888f140913717c53821b75657958 to a978e09acb5a3db0959fc757df17b27e8706d26b
2026-02-02 18:09:59 +01:00
Junio C Hamano
67ad42147a Git 2.53
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-01 18:15:01 -08:00
Junio C Hamano
6f328bc9e3 l10n-2.53.0-v1
-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE37vMEzKDqYvVxs51k24VDd1FMtUFAml+C8cACgkQk24VDd1F
 MtX/AA/+L3XJD3hcwz6BbCqZdIYSdj324KylNHHfsNZ0jw6DH5SwAR91/6VM4wzH
 7yqelAYydWwp265EkfGQNSxY8zPL5YCAd9/xYyNG3oZu7wbJwT13KovWgX2sXr43
 dWXFJIurXNBpiOeJi+82ghmaRS5SfPW1YFConUFj7zsFq3Bb4iXYt2KZ65FpiR5Z
 JJEkqEXi1a8YiuO/b0kTior4kuHyEyOVnzI7OrQihhAls3YQvf8L46zKcDqr/gPp
 6MoiNIFPWomyJl0stNRb9W5w3sr5UDgJ2aR/qj7MutA/2JN7mOqmCB6uGroMmxCU
 FV+gBqhj56di/+sQ0c446NLPUa3nSO4JP5TiUO8MUhP8BnEGopemngpyJLpWzhSr
 0tG5LK32RtMmszBM+XNV247oWL9IiePdhcy6FZr2JIRrVGBpN6RtkmlRKcdAxUIC
 7k+g4u1LzM9vVeLjm8brIMQ78TLY2tL/eOl91fl+5tTRvsJvC4tydIaqEb1k/L9/
 sCj5GMmVs0hxdXMXLtArlbzYvNl0cwkJnqehpQuFkowJmqjAnAV9gKUkId2iaRQh
 TGq9ukCSzwn1XpIsC1o477JoQm+hzCFOFXCESuj9+il4ndfZ+BQgsp7Omb12U0TY
 f4upg2lJJokcoqd0HJoXXD2dkayZlslVhwY7X03BlHRd3VRbiYk=
 =MkCD
 -----END PGP SIGNATURE-----

Merge tag 'l10n-2.53.0-v1' of https://github.com/git-l10n/git-po

l10n-2.53.0-v1

* tag 'l10n-2.53.0-v1' of https://github.com/git-l10n/git-po:
  l10n: zh_CN: standardize glossary terms
  l10n: zh_CN: updated translation for 2.53
  l10n: zh_CN: fix inconsistent use of standard vs. wide colons
  l10n: fr: v2.53
  l10n: zh_TW.po: update Git 2.53 translation
  l10n: tr: Update Turkish translations
  l10n: sv.po: Update Swedish translation
  l10n: po-id for 2.53
  l10n: ga.po: Fix git-po-helper warnings
  l10n: bg.po: Updated Bulgarian translation (6091t)
  l10n: ga.po: Update Irish translation for Git 2.53
2026-02-01 18:13:52 -08:00
Carlo Marcelo Arenas Belón
239b7f686c RelNotes: fully spell negation
Signed-off-by: Carlo Marcelo Arenas Belón <carenas@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-01 18:07:39 -08:00
Jiang Xin
532543fa46 Merge branch 'jx/zh_CN' of github.com:jiangxin/git
* 'jx/zh_CN' of github.com:jiangxin/git:
  l10n: zh_CN: standardize glossary terms
  l10n: zh_CN: updated translation for 2.53
  l10n: zh_CN: fix inconsistent use of standard vs. wide colons
2026-01-31 21:32:54 +08:00
Jiang Xin
5a83d800f3 Merge branch 'l10n/zh-TW/git-2-53' of github.com:l10n-tw/git-po
* 'l10n/zh-TW/git-2-53' of github.com:l10n-tw/git-po:
  l10n: zh_TW.po: update Git 2.53 translation
2026-01-31 21:20:06 +08:00
Jiang Xin
e996719801 Merge branch 'po-id' of github.com:bagasme/git-po
* 'po-id' of github.com:bagasme/git-po:
  l10n: po-id for 2.53
2026-01-31 21:15:38 +08:00
Jiang Xin
8ef65d7efd Merge branch 'l10n-ga-2.53' of github.com:aindriu80/git-po
* 'l10n-ga-2.53' of github.com:aindriu80/git-po:
  l10n: ga.po: Fix git-po-helper warnings
  l10n: ga.po: Update Irish translation for Git 2.53
2026-01-31 21:13:55 +08:00
Jiang Xin
b386b3aea7 Merge branch 'master' of github.com:alshopov/git-po
* 'master' of github.com:alshopov/git-po:
  l10n: bg.po: Updated Bulgarian translation (6091t)
2026-01-31 21:11:50 +08:00
Jiang Xin
af1a298e2c Merge branch 'fr_2.53' of github.com:jnavila/git
* 'fr_2.53' of github.com:jnavila/git:
  l10n: fr: v2.53
2026-01-31 21:08:43 +08:00
Jiang Xin
6f75c474d7 Merge branch 'tr-l10n' of github.com:bitigchi/git-po
* 'tr-l10n' of github.com:bitigchi/git-po:
  l10n: tr: Update Turkish translations
2026-01-31 21:06:38 +08:00
Jiang Xin
3eaaa7fea4 Merge branch 'master' of github.com:nafmo/git-l10n-sv
* 'master' of github.com:nafmo/git-l10n-sv:
  l10n: sv.po: Update Swedish translation
2026-01-31 21:03:10 +08:00
Jiang Xin
eb816ef79e l10n: zh_CN: standardize glossary terms
Add preferred Chinese terminology notes and align existing translations
to the updated glossary. AI-assisted review was used to check and
improve legacy translations.

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
2026-01-31 20:51:27 +08:00
Junio C Hamano
2258446484 RelNotes: correct "fast-import" option name
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-30 09:50:03 -08:00
Jiang Xin
3065daed59 l10n: zh_CN: updated translation for 2.53
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
2026-01-29 21:42:38 +08:00
Jiang Xin
eb3cfc6b2f l10n: zh_CN: fix inconsistent use of standard vs. wide colons
Replace mixed usage of standard (ASCII) colons ':' with full-width
(wide) colons ':' in Chinese translations to ensure typographic
consistency, as reported by CAESIUS-TIM [1].

Full-width punctuation is preferred in Chinese localization for better
readability and adherence to typesetting conventions.

[1]: https://github.com/git-l10n/git-po/issues/884

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
2026-01-29 21:42:38 +08:00
Jean-Noël Avila
72dd507505 l10n: fr: v2.53
Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
2026-01-28 19:43:46 +01:00
Yi-Jyun Pan
b47610d61d
l10n: zh_TW.po: update Git 2.53 translation
Co-authored-by: Lumynous <lumynou5.tw@gmail.com>
Signed-off-by: Yi-Jyun Pan <pan93412@gmail.com>
2026-01-28 22:51:42 +08:00
Johannes Schindelin
3832dd2481 Merge 'readme' into HEAD
Add a README.md for GitHub goodness.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:10 +01:00
Johannes Schindelin
8b56f08b72 Merge pull request #2837 from dscho/monitor-component-updates
Start monitoring updates of Git for Windows' component in the open
2026-01-28 14:30:10 +01:00
Johannes Schindelin
9b086470e9 Merge branch 'deprecate-core.useBuiltinFSMonitor'
Originally introduced as `core.useBuiltinFSMonitor` in Git for Windows
and developed, improved and stabilized there, the built-in FSMonitor
only made it into upstream Git (after unnecessarily long hemming and
hawing and throwing overly perfectionist style review sticks into the
spokes) as `core.fsmonitor = true`.

In Git for Windows, with this topic branch, we re-introduce the
now-obsolete config setting, with warnings suggesting to existing users
how to switch to the new config setting, with the intention to
ultimately drop the patch at some stage.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:10 +01:00
Johannes Schindelin
d5f1dfddd2 Merge branch 'phase-out-reset-stdin'
This topic branch re-adds the deprecated --stdin/-z options to `git
reset`. Those patches were overridden by a different set of options in
the upstream Git project before we could propose `--stdin`.

We offered this in MinGit to applications that wanted a safer way to
pass lots of pathspecs to Git, and these applications will need to be
adjusted.

Instead of `--stdin`, `--pathspec-from-file=-` should be used, and
instead of `-z`, `--pathspec-file-nul`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:10 +01:00
Johannes Schindelin
b77992d6a8 Merge branch 'un-revert-editor-save-and-reset'
A fix for calling `vim` in Windows Terminal caused a regression and was
reverted. We partially un-revert this, to get the fix again.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:10 +01:00
Johannes Schindelin
6fda530210 SECURITY.md: document Git for Windows' policies
This is the recommended way on GitHub to describe policies revolving around
security issues and about supported versions.

Helped-by: Sven Strickroth <email@cs-ware.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:09 +01:00
Johannes Schindelin
9e508167ec dependabot: help keeping GitHub Actions versions up to date
See https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot#enabling-dependabot-version-updates-for-actions for details.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:09 +01:00
Victoria Dye
aadd41abdf fsmonitor: reintroduce core.useBuiltinFSMonitor
Reintroduce the 'core.useBuiltinFSMonitor' config setting (originally added
in 0a756b2a25 (fsmonitor: config settings are repository-specific,
2021-03-05)) after its removal from the upstream version of FSMonitor.

Upstream, the 'core.useBuiltinFSMonitor' setting was rendered obsolete by
"overloading" the 'core.fsmonitor' setting to take a boolean value. However,
several applications (e.g., 'scalar') utilize the original config setting,
so it should be preserved for a deprecation period before complete removal:

* if 'core.fsmonitor' is a boolean, the user is correctly using the new
  config syntax; do not use 'core.useBuiltinFSMonitor'.
* if 'core.fsmonitor' is unspecified, use 'core.useBuiltinFSMonitor'.
* if 'core.fsmonitor' is a path, override and use the builtin FSMonitor if
  'core.useBuiltinFSMonitor' is 'true'; otherwise, use the FSMonitor hook
  indicated by the path.

Additionally, for this deprecation period, advise users to switch to using
'core.fsmonitor' to specify their use of the builtin FSMonitor.

Signed-off-by: Victoria Dye <vdye@github.com>
2026-01-28 14:30:09 +01:00
Johannes Schindelin
0239e4a571 Merge pull request #1170 from dscho/mingw-kill-process
Handle Ctrl+C in Git Bash nicely

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:09 +01:00
Philip Oakley
14a252e678 Modify the GitHub Pull Request template (to reflect Git for Windows)
Git for Windows accepts pull requests; Core Git does not. Therefore we
need to adjust the template (because it only matches core Git's
project management style, not ours).

Also: direct Git for Windows enhancements to their contributions page,
space out the text for easy reading, and clarify that the mailing list
is plain text, not HTML.

Signed-off-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:09 +01:00
Johannes Schindelin
58c26230eb Add a GitHub workflow to monitor component updates
Rather than using private IFTTT Applets that send mails to this
maintainer whenever a new version of a Git for Windows component was
released, let's use the power of GitHub workflows to make this process
publicly visible.

This workflow monitors the Atom/RSS feeds, and opens a ticket whenever a
new version was released.

Note: Bash sometimes releases multiple patched versions within a few
minutes of each other (i.e. 5.1p1 through 5.1p4, 5.0p15 and 5.0p16). The
MSYS2 runtime also has a similar system. We can address those patches as
a group, so we shouldn't get multiple issues about them.

Note further: We're not acting on newlib releases, OpenSSL alphas, Perl
release candidates or non-stable Perl releases. There's no need to open
issues about them.

Co-authored-by: Matthias Aßhauer <mha1993@live.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:09 +01:00
Johannes Schindelin
921085e742 Merge branch 'wsl-file-mode-bits'
This patch introduces support to set special NTFS attributes that are
interpreted by the Windows Subsystem for Linux as file mode bits, UID
and GID.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:09 +01:00
Brendan Forster
fa4ba97ec5 Add an issue template
With improvements by Clive Chan, Adric Norris, Ben Bodenmiller and
Philip Oakley.

Helped-by: Clive Chan <cc@clive.io>
Helped-by: Adric Norris <landstander668@gmail.com>
Helped-by: Ben Bodenmiller <bbodenmiller@hotmail.com>
Helped-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Brendan Forster <brendan@github.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:09 +01:00
Johannes Schindelin
cc6638dbfe Merge branch 'busybox-w32'
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:09 +01:00
Johannes Schindelin
992862351f README.md: Add a Windows-specific preamble
Includes touch-ups by 마누엘, Philip Oakley and 孙卓识.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:09 +01:00
Johannes Schindelin
75ab9302a4 Merge pull request #1897 from piscisaureus/symlink-attr
Specify symlink type in .gitattributes
2026-01-28 14:30:09 +01:00
Derrick Stolee
0a7316bf46 CONTRIBUTING.md: add guide for first-time contributors
Getting started contributing to Git can be difficult on a Windows
machine. CONTRIBUTING.md contains a guide to getting started, including
detailed steps for setting up build tools, running tests, and
submitting patches to upstream.

[includes an example by Pratik Karki how to submit v2, v3, v4, etc.]

Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
2026-01-28 14:30:09 +01:00
Johannes Schindelin
5ee11b692d mingw: try resetting the read-only bit if rename fails (#4527)
With this patch, Git for Windows works as intended on mounted APFS
volumes (where renaming read-only files would fail).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:09 +01:00
Johannes Schindelin
8721a8b3c0 Modify the Code of Conduct for Git for Windows
The Git project followed Git for Windows' lead and added their Code of
Conduct, based on the Contributor Covenant v1.4, later updated to v2.0.

We adapt it slightly to Git for Windows.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:09 +01:00
Johannes Schindelin
891ba58c15 Merge 'docker-volumes-are-no-symlinks'
This was pull request #1645 from ZCube/master

Support windows container.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:09 +01:00
Johannes Schindelin
2b232771ce Describe Git for Windows' architecture [no ci]
The Git for Windows project has grown quite complex over the years,
certainly much more complex than during the first years where the
`msysgit.git` repository was abusing Git for package management purposes
and the `git/git` fork was called `4msysgit.git`.

Let's describe the status quo in a thorough way.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:09 +01:00
Johannes Schindelin
2972e4e633 Merge branch 'msys2' 2026-01-28 14:30:09 +01:00
Johannes Schindelin
b961f120a3 Merge branch 'long-paths' 2026-01-28 14:30:09 +01:00
Johannes Schindelin
cff360f5ac Merge branch 'gitk-and-git-gui-patches'
These are Git for Windows' Git GUI and gitk patches. We will have to
decide at some point what to do about them, but that's a little lower
priority (as Git GUI seems to be unmaintained for the time being, and
the gitk maintainer keeps a very low profile on the Git mailing list,
too).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:09 +01:00
Johannes Schindelin
4ac142d372 reset: reinstate support for the deprecated --stdin option
The `--stdin` option was a well-established paradigm in other commands,
therefore we implemented it in `git reset` for use by Visual Studio.

Unfortunately, upstream Git decided that it is time to introduce
`--pathspec-from-file` instead.

To keep backwards-compatibility for some grace period, we therefore
reinstate the `--stdin` option on top of the `--pathspec-from-file`
option, but mark it firmly as deprecated.

Helped-by: Victoria Dye <vdye@github.com>
Helped-by: Matthew John Cheetham <mjcheetham@outlook.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
cb06418701 Partially un-revert "editor: save and reset terminal after calling EDITOR"
In e3f7e01b50be (Revert "editor: save and reset terminal after calling
EDITOR", 2021-11-22), we reverted the commit wholesale where the
terminal state would be saved and restored before/after calling an
editor.

The reverted commit was intended to fix a problem with Windows Terminal
where simply calling `vi` would cause problems afterwards.

To fix the problem addressed by the revert, but _still_ keep the problem
with Windows Terminal fixed, let's revert the revert, with a twist: we
restrict the save/restore _specifically_ to the case where `vi` (or
`vim`) is called, and do not do the same for any other editor.

This should still catch the majority of the cases, and will bridge the
time until the original patch is re-done in a way that addresses all
concerns.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
5c2a5a3549 mingw: really handle SIGINT
Previously, we did not install any handler for Ctrl+C, but now we really
want to because the MSYS2 runtime learned the trick to call the
ConsoleCtrlHandler when Ctrl+C was pressed.

With this, hitting Ctrl+C while `git log` is running will only terminate
the Git process, but not the pager. This finally matches the behavior on
Linux and on macOS.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
xungeng li
49c3f4b19b mingw: optionally enable wsl compability file mode bits
The Windows Subsystem for Linux (WSL) version 2 allows to use `chmod` on
NTFS volumes provided that they are mounted with metadata enabled (see
https://devblogs.microsoft.com/commandline/chmod-chown-wsl-improvements/
for details), for example:

	$ chmod 0755 /mnt/d/test/a.sh

In order to facilitate better collaboration between the Windows
version of Git and the WSL version of Git, we can make the Windows
version of Git also support reading and writing NTFS file modes
in a manner compatible with WSL.

Since this slightly slows down operations where lots of files are
created (such as an initial checkout), this feature is only enabled when
`core.WSLCompat` is set to true. Note that you also have to set
`core.fileMode=true` in repositories that have been initialized without
enabling WSL compatibility.

There are several ways to enable metadata loading for NTFS volumes
in WSL, one of which is to modify `/etc/wsl.conf` by adding:

```
[automount]
enabled = true
options = "metadata,umask=027,fmask=117"
```

And reboot WSL.

It can also be enabled temporarily by this incantation:

	$ sudo umount /mnt/c &&
	  sudo mount -t drvfs C: /mnt/c -o metadata,uid=1000,gid=1000,umask=22,fmask=111

It's important to note that this modification is compatible with, but
does not depend on WSL. The helper functions in this commit can operate
independently and functions normally on devices where WSL is not
installed or properly configured.

Signed-off-by: xungeng li <xungeng@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
4161847c82 t9200: skip tests when $PWD contains a colon
On Windows, the current working directory is pretty much guaranteed to
contain a colon. If we feed that path to CVS, it mistakes it for a
separator between host and port, though.

This has not been a problem so far because Git for Windows uses MSYS2's
Bash using a POSIX emulation layer that also pretends that the current
directory is a Unix path (at least as long as we're in a shell script).

However, that is rather limiting, as Git for Windows also explores other
ports of other Unix shells. One of those is BusyBox-w32's ash, which is
a native port (i.e. *not* using any POSIX emulation layer, and certainly
not emulating Unix paths).

So let's just detect if there is a colon in $PWD and punt in that case.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Bert Belder
c7ac5703c5 Win32: symlink: add test for symlink attribute
To verify that the symlink is resolved correctly, we use the fact that
`git.exe` is a native Win32 program, and that `git.exe config -f <path>`
therefore uses the native symlink resolution.

Signed-off-by: Bert Belder <bertbelder@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
948a2857fa mingw: kill child processes in a gentler way
The TerminateProcess() function does not actually leave the child
processes any chance to perform any cleanup operations. This is bad
insofar as Git itself expects its signal handlers to run.

A symptom is e.g. a left-behind .lock file that would not be left behind
if the same operation was run, say, on Linux.

To remedy this situation, we use an obscure trick: we inject a thread
into the process that needs to be killed and to let that thread run the
ExitProcess() function with the desired exit status. Thanks J Wyman for
describing this trick.

The advantage is that the ExitProcess() function lets the atexit
handlers run. While this is still different from what Git expects (i.e.
running a signal handler), in practice Git sets up signal handlers and
atexit handlers that call the same code to clean up after itself.

In case that the gentle method to terminate the process failed, we still
fall back to calling TerminateProcess(), but in that case we now also
make sure that processes spawned by the spawned process are terminated;
TerminateProcess() does not give the spawned process a chance to do so
itself.

Please note that this change only affects how Git for Windows tries to
terminate processes spawned by Git's own executables. Third-party
software that *calls* Git and wants to terminate it *still* need to make
sure to imitate this gentle method, otherwise this patch will not have
any effect.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
19fc9e77af t5813: allow for $PWD to be a Windows path
Git for Windows uses MSYS2's Bash to run the test suite, which comes
with benefits but also at a heavy price: on the plus side, MSYS2's
POSIX emulation layer allows us to continue pretending that we are on a
Unix system, e.g. use Unix paths instead of Windows ones, yet this is
bought at a rather noticeable performance penalty.

There *are* some more native ports of Unix shells out there, though,
most notably BusyBox-w32's ash. These native ports do not use any POSIX
emulation layer (or at most a *very* thin one, choosing to avoid
features such as fork() that are expensive to emulate on Windows), and
they use native Windows paths (usually with forward slashes instead of
backslashes, which is perfectly legal in almost all use cases).

And here comes the problem: with a $PWD looking like, say,
C:/git-sdk-64/usr/src/git/t/trash directory.t5813-proto-disable-ssh
Git's test scripts get quite a bit confused, as their assumptions have
been shattered. Not only does this path contain a colon (oh no!), it
also does not start with a slash.

This is a problem e.g. when constructing a URL as t5813 does it:
ssh://remote$PWD. Not only is it impossible to separate the "host" from
the path with a $PWD as above, even prefixing $PWD by a slash won't
work, as /C:/git-sdk-64/... is not a valid path.

As a workaround, detect when $PWD does not start with a slash on
Windows, and simply strip the drive prefix, using an obscure feature of
Windows paths: if an absolute Windows path starts with a slash, it is
implicitly prefixed by the drive prefix of the current directory. As we
are talking about the current directory here, anyway, that strategy
works.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
f1c208d52f t5605: special-case hardlink test for BusyBox-w32
When t5605 tries to verify that files are hardlinked (or that they are
not), it uses the `-links` option of the `find` utility.

BusyBox' implementation does not support that option, and BusyBox-w32's
lstat() does not even report the number of hard links correctly (for
performance reasons).

So let's just switch to a different method that actually works on
Windows.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
bffa16ecdb t5532: workaround for BusyBox on Windows
While it may seem super convenient to some old Unix hands to simpy
require Perl to be available when running the test suite, this is a
major hassle on Windows, where we want to verify that Perl is not,
actually, required in a NO_PERL build.

As a super ugly workaround, we "install" a script into /usr/bin/perl
reading like this:

	#!/bin/sh

	# We'd much rather avoid requiring Perl altogether when testing
	# an installed Git. Oh well, that's why we cannot have nice
	# things.
	exec c:/git-sdk-64/usr/bin/perl.exe "$@"

The problem with that is that BusyBox assumes that the #! line in a
script refers to an executable, not to a script. So when it encounters
the line #!/usr/bin/perl in t5532's proxy-get-cmd, it barfs.

Let's help this situation by simply executing the Perl script with the
"interpreter" specified explicitly.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
b29f110fed t5003: use binary file from t/lib-diff/
At some stage, t5003-archive-zip wants to add a file that is not ASCII.
To that end, it uses /bin/sh. But that file may actually not exist (it
is too easy to forget that not all the world is Unix/Linux...)! Besides,
we already have perfectly fine binary files intended for use solely by
the tests. So let's use one of them instead.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
61b0aea2ca test-lib: add BUSYBOX prerequisite
When running with BusyBox, we will want to avoid calling executables on
the PATH that are implemented in BusyBox itself.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
495bf8e201 tests (mingw): remove Bash-specific pwd option
The -W option is only understood by MSYS2 Bash's pwd command. We already
make sure to override `pwd` by `builtin pwd -W` for MINGW, so let's not
double the effort here.

This will also help when switching the shell to another one (such as
BusyBox' ash) whose pwd does *not* understand the -W option.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
6cd81171a3 mingw: only use Bash-ism builtin pwd -W when available
Traditionally, Git for Windows' SDK uses Bash as its default shell.
However, other Unix shells are available, too. Most notably, the Win32
port of BusyBox comes with `ash` whose `pwd` command already prints
Windows paths as Git for Windows wants them, while there is not even a
`builtin` command.

Therefore, let's be careful not to override `pwd` unless we know that
the `builtin` command is available.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
ab77ebf8c4 tests: use the correct path separator with BusyBox
BusyBox-w32 is a true Win32 application, i.e. it does not come with a
POSIX emulation layer.

That also means that it does *not* use the Unix convention of separating
the entries in the PATH variable using colons, but semicolons.

However, there are also BusyBox ports to Windows which use a POSIX
emulation layer such as Cygwin's or MSYS2's runtime, i.e. using colons
as PATH separators.

As a tell-tale, let's use the presence of semicolons in the PATH
variable: on Unix, it is highly unlikely that it contains semicolons,
and on Windows (without POSIX emulation), it is virtually guaranteed, as
everybody should have both $SYSTEMROOT and $SYSTEMROOT/system32 in their
PATH.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
50e21b0954 tests: only override sort & find if there are usable ones in /usr/bin/
The idea is to allow running the test suite on MinGit with BusyBox
installed in /mingw64/bin/sh.exe. In that case, we will want to exclude
sort & find (and other Unix utilities) from being bundled.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
7a10947b3d tests: move test PNGs into t/lib-diff/
We already have a directory where we store files intended for use by
multiple test scripts. The same directory is a better home for the
test-binary-*.png files than t/.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
83ce344e4a gitattributes: mark .png files as binary
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
713de6120d tests(mingw): if iconv is unavailable, use test-helper --iconv
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
5fff04da15 test-tool: learn to act as a drop-in replacement for iconv
It is convenient to assume that everybody who wants to build & test Git
has access to a working `iconv` executable (after all, we already pretty
much require libiconv).

However, that limits esoteric test scenarios such as Git for Windows',
where an end user installation has to ship with `iconv` for the sole
purpose of being testable. That payload serves no other purpose.

So let's just have a test helper (to be able to test Git, the test
helpers have to be available, after all) to act as `iconv` replacement.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
119a7bd28a mingw: when path_lookup() failed, try BusyBox
BusyBox comes with a ton of applets ("applet" being the identical
concept to Git's "builtins"). And similar to Git's builtins, the applets
can be called via `busybox <command>`, or the BusyBox executable can be
copied/hard-linked to the command name.

The similarities do not end here. Just as with Git's builtins, it is
problematic that BusyBox' hard-linked applets cannot easily be put into
a .zip file: .zip archives have no concept of hard-links and therefore
would store identical copies (and also extract identical copies,
"inflating" the archive unnecessarily).

To counteract that issue, MinGit already ships without hard-linked
copies of the builtins, and the plan is to do the same with BusyBox'
applets: simply ship busybox.exe as single executable, without
hard-linked applets.

To accommodate that, Git is being taught by this commit a very special
trick, exploiting the fact that it is possible to call an executable
with a command-line whose argv[0] is different from the executable's
name: when `sh` is to be spawned, and no `sh` is found in the PATH, but
busybox.exe is, use that executable (with unchanged argv).

Likewise, if any executable to be spawned is not on the PATH, but
busybox.exe is found, parse the output of `busybox.exe --help` to find
out what applets are included, and if the command matches an included
applet name, use busybox.exe to execute it.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
Johannes Schindelin
dd6f4f6e15 mingw: explicitly specify with which cmd to prefix the cmdline
The main idea of this patch is that even if we have to look up the
absolute path of the script, if only the basename was specified as
argv[0], then we should use that basename on the command line, too, not
the absolute path.

This patch will also help with the upcoming patch where we automatically
substitute "sh ..." by "busybox sh ..." if "sh" is not in the PATH but
"busybox" is: we will do that by substituting the actual executable, but
still keep prepending "sh" to the command line.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:08 +01:00
David Lomas
cee92a642d mingw: work around rename() failing on a read-only file
At least on _some_ APFS network shares, Git fails to rename the object
files because they are marked as read-only, because that has the effect
of setting the uchg flag on APFS, which then means the file can't be
renamed or deleted.

To work around that, when a rename failed, and the read-only flag is
set, try to turn it off and on again.

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

Signed-off-by: David Lomas <dl3@pale-eds.co.uk>
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
2026-01-28 14:30:07 +01:00
Johannes Schindelin
baea4cfe36 mingw: Windows Docker volumes are *not* symbolic links
... even if they may look like them.

As looking up the target of the "symbolic link" (just to see whether it
starts with `/ContainerMappedDirectories/`) is pretty expensive, we
do it when we can be *really* sure that there is a possibility that this
might be the case.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: JiSeop Moon <zcube@zcube.kr>
2026-01-28 14:30:07 +01:00
Bert Belder
12ea88bdfb mingw: allow to specify the symlink type in .gitattributes
On Windows, symbolic links have a type: a "file symlink" must point at
a file, and a "directory symlink" must point at a directory. If the
type of symlink does not match its target, it doesn't work.

Git does not record the type of symlink in the index or in a tree. On
checkout it'll guess the type, which only works if the target exists
at the time the symlink is created. This may often not be the case,
for example when the link points at a directory inside a submodule.

By specifying `symlink=file` or `symlink=dir` the user can specify what
type of symlink Git should create, so Git doesn't have to rely on
unreliable heuristics.

Signed-off-by: Bert Belder <bertbelder@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:07 +01:00
JiSeop Moon
5dcce1ae78 mingw: move the file_attr_to_st_mode() function definition
In preparation for making this function a bit more complicated (to allow
for special-casing the `ContainerMappedDirectories` in Windows
containers, which look like a symbolic link, but are not), let's move it
out of the header.

Signed-off-by: JiSeop Moon <zcube@zcube.kr>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:07 +01:00
Johannes Schindelin
0960f32862 Introduce helper to create symlinks that knows about index_state
On Windows, symbolic links actually have a type depending on the target:
it can be a file or a directory.

In certain circumstances, this poses problems, e.g. when a symbolic link
is supposed to point into a submodule that is not checked out, so there
is no way for Git to auto-detect the type.

To help with that, we will add support over the course of the next
commits to specify that symlink type via the Git attributes. This
requires an index_state, though, something that Git for Windows'
`symlink()` replacement cannot know about because the function signature
is defined by the POSIX standard and not ours to change.

So let's introduce a helper function to create symbolic links that
*does* know about the index_state.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:07 +01:00
JiSeop Moon
379ec9de1c mingw: when running in a Windows container, try to rename() harder
It is a known issue that a rename() can fail with an "Access denied"
error at times, when copying followed by deleting the original file
works. Let's just fall back to that behavior.

Signed-off-by: JiSeop Moon <zcube@zcube.kr>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:07 +01:00
Bert Belder
1a6bf77596 Win32: symlink: move phantom symlink creation to a separate function
Signed-off-by: Bert Belder <bertbelder@gmail.com>
2026-01-28 14:30:07 +01:00
JiSeop Moon
f24db036a8 mingw: introduce code to detect whether we're inside a Windows container
This will come in handy in the next commit.

Signed-off-by: JiSeop Moon <zcube@zcube.kr>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:07 +01:00
Johannes Schindelin
408161624f mingw (git_terminal_prompt): do fall back to CONIN$/CONOUT$ method
To support Git Bash running in a MinTTY, we use a dirty trick to access
the MSYS2 pseudo terminal: we execute a Bash snippet that accesses
/dev/tty.

The idea was to fall back to writing to/reading from CONOUT$/CONIN$ if
that Bash call failed because Bash was not found.

However, we should fall back even in other error conditions, because we
have not successfully read the user input. Let's make it so.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:04 +01:00
Ben Boeckel
6d5896bd35 clean: suggest using core.longPaths if paths are too long to remove
On Windows, git repositories may have extra files which need cleaned
(e.g., a build directory) that may be arbitrarily deep. Suggest using
`core.longPaths` if such situations are encountered.

Fixes: #2715
Signed-off-by: Ben Boeckel <mathstuf@gmail.com>
2026-01-28 14:30:04 +01:00
Karsten Blees
4b6c17c679 compat/terminal.c: only use the Windows console if bash 'read -r' fails
Accessing the Windows console through the special CONIN$ / CONOUT$ devices
doesn't work properly for non-ASCII usernames an passwords.

It also doesn't work for terminal emulators that hide the native console
window (such as mintty), and 'TERM=xterm*' is not necessarily a reliable
indicator for such terminals.

The new shell_prompt() function, on the other hand, works fine for both
MSys1 and MSys2, in native console windows as well as mintty, and properly
supports Unicode. It just needs bash on the path (for 'read -s', which is
bash-specific).

On Windows, try to use the shell to read from the terminal. If that fails
with ENOENT (i.e. bash was not found), use CONIN/OUT as fallback.

Note: To test this, create a UTF-8 credential file with non-ASCII chars,
e.g. in git-bash: 'echo url=http://täst.com > cred.txt'. Then in git-cmd,
'git credential fill <cred.txt' works (shell version), while calling git
without the git-wrapper (i.e. 'mingw64\bin\git credential fill <cred.txt')
mangles non-ASCII chars in both console output and input.

Signed-off-by: Karsten Blees <blees@dcon.de>
2026-01-28 14:30:04 +01:00
Jeff Hostetler
c25c3abc6f compat/fsmonitor/fsm-*-win32: support long paths
Update wchar_t buffers to use MAX_LONG_PATH instead of MAX_PATH and call
xutftowcs_long_path() in the Win32 backend source files.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-01-28 14:30:04 +01:00
Karsten Blees
7bb8f5a48c mingw: Support git_terminal_prompt with more terminals
The `git_terminal_prompt()` function expects the terminal window to be
attached to a Win32 Console. However, this is not the case with terminal
windows other than `cmd.exe`'s, e.g. with MSys2's own `mintty`.

Non-cmd terminals such as `mintty` still have to have a Win32 Console
to be proper console programs, but have to hide the Win32 Console to
be able to provide more flexibility (such as being resizeable not only
vertically but also horizontally). By writing to that Win32 Console,
`git_terminal_prompt()` manages only to send the prompt to nowhere and
to wait for input from a Console to which the user has no access.

This commit introduces a function specifically to support `mintty` -- or
other terminals that are compatible with MSys2's `/dev/tty` emulation. We
use the `TERM` environment variable as an indicator for that: if the value
starts with "xterm" (such as `mintty`'s "xterm_256color"), we prefer to
let `xterm_prompt()` handle the user interaction.

The most prominent user of `git_terminal_prompt()` is certainly
`git-remote-https.exe`. It is an interesting use case because both
`stdin` and `stdout` are redirected when Git calls said executable, yet
it still wants to access the terminal.

When running inside a `mintty`, the terminal is not accessible to the
`git-remote-https.exe` program, though, because it is a MinGW program
and the `mintty` terminal is not backed by a Win32 console.

To solve that problem, we simply call out to the shell -- which is an
*MSys2* program and can therefore access `/dev/tty`.

Helped-by: nalla <nalla@hamal.uberspace.de>
Signed-off-by: Karsten Blees <blees@dcon.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:04 +01:00
Johannes Schindelin
2b15f836a8 win32(long path support): leave drive-less absolute paths intact
When trying to ensure that long paths are handled correctly, we
first normalize absolute paths as we encounter them.

However, if the path is a so-called "drive-less" absolute path, i.e. if
it is relative to the current drive but _does_ start with a directory
separator, we would want the normalized path to be such a drive-less
absolute path, too.

Let's do that, being careful to still include the drive prefix when we
need to go through the `\\?\` dance (because there, the drive prefix is
absolutely required).

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

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:04 +01:00
Karsten Blees
0b0dc0f808 mingw: support long paths
Windows paths are typically limited to MAX_PATH = 260 characters, even
though the underlying NTFS file system supports paths up to 32,767 chars.
This limitation is also evident in Windows Explorer, cmd.exe and many
other applications (including IDEs).

Particularly annoying is that most Windows APIs return bogus error codes
if a relative path only barely exceeds MAX_PATH in conjunction with the
current directory, e.g. ERROR_PATH_NOT_FOUND / ENOENT instead of the
infinitely more helpful ERROR_FILENAME_EXCED_RANGE / ENAMETOOLONG.

Many Windows wide char APIs support longer than MAX_PATH paths through the
file namespace prefix ('\\?\' or '\\?\UNC\') followed by an absolute path.
Notable exceptions include functions dealing with executables and the
current directory (CreateProcess, LoadLibrary, Get/SetCurrentDirectory) as
well as the entire shell API (ShellExecute, SHGetSpecialFolderPath...).

Introduce a handle_long_path function to check the length of a specified
path properly (and fail with ENAMETOOLONG), and to optionally expand long
paths using the '\\?\' file namespace prefix. Short paths will not be
modified, so we don't need to worry about device names (NUL, CON, AUX).

Contrary to MSDN docs, the GetFullPathNameW function doesn't seem to be
limited to MAX_PATH (at least not on Win7), so we can use it to do the
heavy lifting of the conversion (translate '/' to '\', eliminate '.' and
'..', and make an absolute path).

Add long path error checking to xutftowcs_path for APIs with hard MAX_PATH
limit.

Add a new MAX_LONG_PATH constant and xutftowcs_long_path function for APIs
that support long paths.

While improved error checking is always active, long paths support must be
explicitly enabled via 'core.longpaths' option. This is to prevent end
users from shooting themselves in the foot by checking out files that Windows
Explorer, cmd/bash or their favorite IDE cannot handle.

Test suite:
Test the case is when the full pathname length of a dir is close
to 260 (MAX_PATH).
Bug report and an original reproducer by Andrey Rogozhnikov:
https://github.com/msysgit/git/pull/122#issuecomment-43604199

[jes: adjusted test number to avoid conflicts, added support for
chdir(), etc]

Thanks-to: Martin W. Kirst <maki@bitkings.de>
Thanks-to: Doug Kelly <dougk.ff7@gmail.com>
Original-test-by: Andrey Rogozhnikov <rogozhnikov.andrey@gmail.com>
Signed-off-by: Karsten Blees <blees@dcon.de>
Signed-off-by: Stepan Kasal <kasal@ucw.cz>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Josh Soref <jsoref@gmail.com>
2026-01-28 14:30:04 +01:00
Doug Kelly
519b619b85 pack-objects (mingw): demonstrate a segmentation fault with large deltas
There is a problem in the way 9ac3f0e5b3e4 (pack-objects: fix
performance issues on packing large deltas, 2018-07-22) initializes that
mutex in the `packing_data` struct. The problem manifests in a
segmentation fault on Windows, when a mutex (AKA critical section) is
accessed without being initialized. (With pthreads, you apparently do
not really have to initialize them?)

This was reported in https://github.com/git-for-windows/git/issues/1839.

Signed-off-by: Doug Kelly <dougk.ff7@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:04 +01:00
Johannes Schindelin
ff04e9b21b Merge branch 'dont-clean-junctions-fscache'
We already avoid traversing NTFS junction points in `git clean -dfx`.
With this topic branch, we do that when the FSCache is enabled, too.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:04 +01:00
Johannes Schindelin
09c1ab4905 Merge remote-tracking branch 'benpeart/fscache-per-thread-gfw'
This brings substantial wins in performance because the FSCache is now
per-thread, being merged to the primary thread only at the end, so we do
not have to lock (except while merging).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:04 +01:00
Johannes Schindelin
691bc35e47 clean: make use of FSCache
The `git clean` command needs to enumerate plenty of files and
directories, and can therefore benefit from the FSCache.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:03 +01:00
Johannes Schindelin
34aae90f59 Merge pull request #1909 from benpeart/free-fscache-after-status-gfw
status: disable and free fscache at the end of the status command
2026-01-28 14:30:03 +01:00
Ben Peart
4aa340bad7 fscache: teach fscache to use NtQueryDirectoryFile
Using FindFirstFileExW() requires the OS to allocate a 64K buffer for each
directory and then free it when we call FindClose().  Update fscache to call
the underlying kernel API NtQueryDirectoryFile so that we can do the buffer
management ourselves.  That allows us to allocate a single buffer for the
lifetime of the cache and reuse it for each directory.

This change improves performance of 'git status' by 18% in a repo with ~200K
files and 30k folders.

Documentation for NtQueryDirectoryFile can be found at:

https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntifs/nf-ntifs-ntquerydirectoryfile
https://docs.microsoft.com/en-us/windows/desktop/FileIO/file-attribute-constants
https://docs.microsoft.com/en-us/windows/desktop/fileio/reparse-point-tags

To determine if the specified directory is a symbolic link, inspect the
FileAttributes member to see if the FILE_ATTRIBUTE_REPARSE_POINT flag is
set. If so, EaSize will contain the reparse tag (this is a so far
undocumented feature, but confirmed by the NTFS developers). To
determine if the reparse point is a symbolic link (and not some other
form of reparse point), test whether the tag value equals the value
IO_REPARSE_TAG_SYMLINK.

The NtQueryDirectoryFile() call works best (and on Windows 8.1 and
earlier, it works *only*) with buffer sizes up to 64kB. Which is 32k
wide characters, so let's use that as our buffer size.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:03 +01:00
Johannes Schindelin
a08c6ea409 fscache: implement an FSCache-aware is_mount_point()
When FSCache is active, we can cache the reparse tag and use it directly
to determine whether a path refers to an NTFS junction, without any
additional, costly I/O.

Note: this change only makes a difference with the next commit, which
will make use of the FSCache in `git clean` (contingent on
`core.fscache` set, of course).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:03 +01:00
Johannes Schindelin
9ec49aad75 Merge branch 'fscache' 2026-01-28 14:30:03 +01:00
Ben Peart
a919310c6d status: disable and free fscache at the end of the status command
At the end of the status command, disable and free the fscache so that we
don't leak the memory and so that we can dump the fscache statistics.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
2026-01-28 14:30:03 +01:00
Ben Peart
260041ff50 fscache: make fscache_enable() thread safe
The recent change to make fscache thread specific relied on fscache_enable()
being called first from the primary thread before being called in parallel
from worker threads.  Make that more robust and protect it with a critical
section to avoid any issues.

Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Ben Peart <benpeart@microsoft.com>
2026-01-28 14:30:03 +01:00
Johannes Schindelin
91ce9a8e3c fscache: remember the reparse tag for each entry
We will use this in the next commit to implement an FSCache-aware
version of is_mount_point().

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:03 +01:00
Derrick Stolee
16a1f1870a unpack-trees: enable fscache for sparse-checkout
When updating the skip-worktree bits in the index to align with new
values in a sparse-checkout file, Git scans the entire working
directory with lstat() calls. In a sparse-checkout, many of these
lstat() calls are for paths that do not exist.

Enable the fscache feature during this scan. Since enable_fscache()
calls nest, the disable_fscache() method decrements a counter and
would only clear the cache if that counter reaches zero.

In a local test of a repo with ~2.2 million paths, updating the index
with git read-tree -m -u HEAD with a sparse-checkout file containing
only /.gitattributes improved from 2-3 minutes to ~6 seconds.

Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:03 +01:00
Ben Peart
7588ad517b fscache: teach fscache to use mempool
Now that the fscache is single threaded, take advantage of the mem_pool as
the allocator to significantly reduce the cost of allocations and frees.

With the reduced cost of free, in future patches, we can start freeing the
fscache at the end of commands instead of just leaking it.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:03 +01:00
Ben Peart
ed9e62ed1a fscache: add fscache hit statistics
Track fscache hits and misses for lstat and opendir requests.  Reporting of
statistics is done when the cache is disabled for the last time and freed
and is only reported if GIT_TRACE_FSCACHE is set.

Sample output is:

11:33:11.836428 compat/win32/fscache.c:433 fscache: lstat 3775, opendir 263, total requests/misses 4052/269

Signed-off-by: Ben Peart <benpeart@microsoft.com>
2026-01-28 14:30:03 +01:00
Ben Peart
7ba4643052 fscache: update fscache to be thread specific instead of global
The threading model for fscache has been to have a single, global cache.
This puts requirements on it to be thread safe so that callers like
preload-index can call it from multiple threads.  This was implemented
with a single mutex and completion events which introduces contention
between the calling threads.

Simplify the threading model by making fscache thread specific.  This allows
us to remove the global mutex and synchronization events entirely and instead
associate a fscache with every thread that requests one. This works well with
the current multi-threading which divides the cache entries into blocks with
a separate thread processing each block.

At the end of each worker thread, if there is a fscache on the primary
thread, merge the cached results from the worker into the primary thread
cache. This enables us to reuse the cache later especially when scanning for
untracked files.

In testing, this reduced the time spent in preload_index() by about 25% and
also reduced the CPU utilization significantly.  On a repo with ~200K files,
it reduced overall status times by ~12%.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
2026-01-28 14:30:03 +01:00
Ben Peart
8f3d874d8b fscache: add GIT_TEST_FSCACHE support
Add support to fscache to enable running the entire test suite with the
fscache enabled.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
2026-01-28 14:30:03 +01:00
Ben Peart
86df8be1de fscache: fscache takes an initial size
Update enable_fscache() to take an optional initial size parameter which is
used to initialize the hashmap so that it can avoid having to rehash as
additional entries are added.

Add a separate disable_fscache() macro to make the code clearer and easier
to read.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:03 +01:00
Ben Peart
10641751c3 fscache: use FindFirstFileExW to avoid retrieving the short name
Use FindFirstFileExW with FindExInfoBasic to avoid forcing NTFS to look up
the short name.  Also switch to a larger (64K vs 4K) buffer using
FIND_FIRST_EX_LARGE_FETCH to minimize round trips to the kernel.

In a repo with ~200K files, this drops warm cache status times from 3.19
seconds to 2.67 seconds for a 16% savings.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
2026-01-28 14:30:03 +01:00
Ben Peart
3dd272a340 mem_pool: add GIT_TRACE_MEMPOOL support
Add tracing around initializing and discarding mempools. In discard report
on the amount of memory unused in the current block to help tune setting
the initial_size.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
2026-01-28 14:30:03 +01:00
Ben Peart
9c26251e35 Enable the filesystem cache (fscache) in refresh_index().
On file systems that support it, this can dramatically speed up operations
like add, commit, describe, rebase, reset, rm that would otherwise have to
lstat() every file to "re-match" the stat information in the index to that
of the file system.

On a synthetic repo with 1M files, "git reset" dropped from 52.02 seconds to
14.42 seconds for a savings of 72%.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
2026-01-28 14:30:03 +01:00
Takuto Ikuta
38e3b0b60f checkout.c: enable fscache for checkout again
This is retry of #1419.

I added flush_fscache macro to flush cached stats after disk writing
with tests for regression reported in #1438 and #1442.

git checkout checks each file path in sorted order, so cache flushing does not
make performance worse unless we have large number of modified files in
a directory containing many files.

Using chromium repository, I tested `git checkout .` performance when I
delete 10 files in different directories.
With this patch:
TotalSeconds: 4.307272
TotalSeconds: 4.4863595
TotalSeconds: 4.2975562
Avg: 4.36372923333333

Without this patch:
TotalSeconds: 20.9705431
TotalSeconds: 22.4867685
TotalSeconds: 18.8968292
Avg: 20.7847136

I confirmed this patch passed all tests in t/ with core_fscache=1.

Signed-off-by: Takuto Ikuta <tikuta@chromium.org>
2026-01-28 14:30:03 +01:00
Johannes Schindelin
9e0e180692 ci(macos): skip the git p4 tests (#5954)
Historically, the macOS jobs have always been among the longest-running
ones, and recently the `git p4` tests became another liability: They
started to fail much more often (maybe as of the switch away from the
`macos-13` pool?), requiring re-runs of the jobs that already were
responsible for long CI build times.

Of the 35 test scripts that exercise `git p4`, 32 are actually run on
macOS (3 are skipped for reasons like case-sensitivee filesystem), and
they take an accumulated runtime of over half an hour.

Furthermore, the `git p4` command is not really affected by Git for
Windows' patches, at least not as far as macOS is concerned, therefore
it is not only causing developer friction to have these long-running,
frequently failing tests, it is also quite wasteful: There has not been
a single instance so far where any `git p4` test failure in Git for
Windows had demonstrated an actionable bug.

So let's just disable those tests in the CI runs, at least on macOS.
2026-01-28 14:30:02 +01:00
Johannes Schindelin
ad28b5ceac Merge branch 'git-gui-askyesno'
These changes are necessary to support better Git for Windows' new
auto-update feature.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:02 +01:00
Takuto Ikuta
147e66371c fetch-pack.c: enable fscache for stats under .git/objects
When I do git fetch, git call file stats under .git/objects for each
refs. This takes time when there are many refs.

By enabling fscache, git takes file stats by directory traversing and that
improved the speed of fetch-pack for repository having large number of
refs.

In my windows workstation, this improves the time of `git fetch` for
chromium repository like below. I took stats 3 times.

* With this patch
TotalSeconds: 9.9825165
TotalSeconds: 9.1862075
TotalSeconds: 10.1956256
Avg: 9.78811653333333

* Without this patch
TotalSeconds: 15.8406702
TotalSeconds: 15.6248053
TotalSeconds: 15.2085938
Avg: 15.5580231

Signed-off-by: Takuto Ikuta <tikuta@chromium.org>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:02 +01:00
Johannes Schindelin
4367c0b069 git-svn: mark it as unsupported by the Git for Windows project (#5923)
There have been too many challenges supporting `git svn`, including lack
of participation in developing/maintaining the required stack.

See https://github.com/git-for-windows/git/issues/5405 for full details.
2026-01-28 14:30:02 +01:00
Johannes Schindelin
76c3bf3653 ci(macos): skip the git p4 tests
Historically, the macOS jobs have always been among the longest-running
ones, and recently the `git p4` tests became another liability: They
started to fail much more often (maybe as of the switch away from the
`macos-13` pool?), requiring re-runs of the jobs that already were
responsible for long CI build times.

Of the 35 test scripts that exercise `git p4`, 32 are actually run on
macOS (3 are skipped for reasons like case-sensitivee filesystem), and
they take an accumulated runtime of over half an hour.

Furthermore, the `git p4` command is not really affected by Git for
Windows' patches, at least not as far as macOS is concerned, therefore
it is not only causing developer friction to have these long-running,
frequently failing tests, it is also quite wasteful: There has not been
a single instance so far where any `git p4` test failure in Git for
Windows had demonstrated an actionable bug.

While upstream Git is confident to have addressed the flakiness of the
`git p4` tests via ffff0bb0dac1 (Use Perforce arm64 binary on macOS CI
jobs, 2025-11-16) (which got slipped in at the 11th hour into the
v2.52.0 release, fast-tracked without ever hitting `seen` even after
-rc2 was released), I am not quite so confident, and besides, the
runtime penalty of running those tests in Git for Windows' CI runs is
still a worrisome burden.

So let's just disable those tests in the CI runs, at least on macOS.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:02 +01:00
Johannes Schindelin
31ddaed68f git-gui--askyesno (mingw): use Git for Windows' icon, if available
For additional GUI goodness.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:02 +01:00
Jeff Hostetler
d74b0b0038 dir.c: regression fix for add_excludes with fscache
Fix regression described in:
https://github.com/git-for-windows/git/issues/1392

which was introduced in:
b2353379bb

Problem Symptoms
================
When the user has a .gitignore file that is a symlink, the fscache
optimization introduced above caused the stat-data from the symlink,
rather that of the target file, to be returned.  Later when the ignore
file was read, the buffer length did not match the stat.st_size field
and we called die("cannot use <path> as an exclude file")

Optimization Rationale
======================
The above optimization calls lstat() before open() primarily to ask
fscache if the file exists.  It gets the current stat-data as a side
effect essentially for free (since we already have it in memory).
If the file does not exist, it does not need to call open().  And
since very few directories have .gitignore files, we can greatly
reduce time spent in the filesystem.

Discussion of Fix
=================
The above optimization calls lstat() rather than stat() because the
fscache only intercepts lstat() calls.  Calls to stat() stay directed
to the mingw_stat() completly bypassing fscache.  Furthermore, calls
to mingw_stat() always call {open, fstat, close} so that symlinks are
properly dereferenced, which adds *additional* open/close calls on top
of what the original code in dir.c is doing.

Since the problem only manifests for symlinks, we add code to overwrite
the stat-data when the path is a symlink.  This preserves the effect of
the performance gains provided by the fscache in the normal case.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-01-28 14:30:02 +01:00
Johannes Schindelin
33b49c5e1a Merge branch 'ready-for-upstream'
This is the branch thicket of patches in Git for Windows that are
considered ready for upstream. To keep them in a ready-to-submit shape,
they are kept as close to the beginning of the branch thicket as
possible.
2026-01-28 14:30:02 +01:00
Johannes Schindelin
a01bd81ccb git-svn: mark it as unsupported by the Git for Windows project
There have been too many challenges supporting `git svn`, including lack
of participation in developing/maintaining the required stack.

See https://github.com/git-for-windows/git/issues/5405 for full details.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:02 +01:00
Johannes Schindelin
0bad704151 git-gui--askyesno: fix funny text wrapping
The text wrapping seems to be aligned to the right side of the Yes
button, leaving an awful lot of empty space.

Let's try to counter this by using pixel units.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:02 +01:00
Jeff Hostetler
dd81725b2c fscache: make fscache_enabled() public
Make fscache_enabled() function public rather than static.
Remove unneeded fscache_is_enabled() function.
Change is_fscache_enabled() macro to call fscache_enabled().

is_fscache_enabled() now takes a pathname so that the answer
is more precise and mean "is fscache enabled for this pathname",
since fscache only stores repo-relative paths and not absolute
paths, we can avoid attempting lookups for absolute paths.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-01-28 14:30:02 +01:00
Jeff Hostetler
89d3cb27fd dir.c: make add_excludes aware of fscache during status
Teach read_directory_recursive() and add_excludes() to
be aware of optional fscache and avoid trying to open()
and fstat() non-existant ".gitignore" files in every
directory in the worktree.

The current code in add_excludes() calls open() and then
fstat() for a ".gitignore" file in each directory present
in the worktree.  Change that when fscache is enabled to
call lstat() first and if present, call open().

This seems backwards because both lstat needs to do more
work than fstat.  But when fscache is enabled, fscache will
already know if the .gitignore file exists and can completely
avoid the IO calls.  This works because of the lstat diversion
to mingw_lstat when fscache is enabled.

This reduced status times on a 350K file enlistment of the
Windows repo on a NVMe SSD by 0.25 seconds.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-01-28 14:30:02 +01:00
Jeff Hostetler
89545a17e8 add: use preload-index and fscache for performance
Teach "add" to use preload-index and fscache features
to improve performance on very large repositories.

During an "add", a call is made to run_diff_files()
which calls check_remove() for each index-entry.  This
calls lstat().  On Windows, the fscache code intercepts
the lstat() calls and builds a private cache using the
FindFirst/FindNext routines, which are much faster.

Somewhat independent of this, is the preload-index code
which distributes some of the start-up costs across
multiple threads.

We need to keep the call to read_cache() before parsing the
pathspecs (and hence cannot use the pathspecs to limit any preload)
because parse_pathspec() is using the index to determine whether a
pathspec is, in fact, in a submodule. If we would not read the index
first, parse_pathspec() would not error out on a path that is inside
a submodule, and t7400-submodule-basic.sh would fail with

	not ok 47 - do not add files from a submodule

We still want the nice preload performance boost, though, so we simply
call read_cache_preload(&pathspecs) after parsing the pathspecs.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:02 +01:00
Johannes Schindelin
bba3243fb6 fscache: add a test for the dir-not-found optimization
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:02 +01:00
Jeff Hostetler
4650e13008 fscache: remember not-found directories
Teach FSCACHE to remember "not found" directories.

This is a performance optimization.

FSCACHE is a performance optimization available for Windows.  It
intercepts Posix-style lstat() calls into an in-memory directory
using FindFirst/FindNext.  It improves performance on Windows by
catching the first lstat() call in a directory, using FindFirst/
FindNext to read the list of files (and attribute data) for the
entire directory into the cache, and short-cut subsequent lstat()
calls in the same directory.  This gives a major performance
boost on Windows.

However, it does not remember "not found" directories.  When STATUS
runs and there are missing directories, the lstat() interception
fails to find the parent directory and simply return ENOENT for the
file -- it does not remember that the FindFirst on the directory
failed. Thus subsequent lstat() calls in the same directory, each
re-attempt the FindFirst.  This completely defeats any performance
gains.

This can be seen by doing a sparse-checkout on a large repo and
then doing a read-tree to reset the skip-worktree bits and then
running status.

This change reduced status times for my very large repo by 60%.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:02 +01:00
Jeff Hostetler
d3105b49d9 fscache: add key for GIT_TRACE_FSCACHE
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:02 +01:00
Karsten Blees
fb4c6a5135 fscache: load directories only once
If multiple threads access a directory that is not yet in the cache, the
directory will be loaded by each thread. Only one of the results is added
to the cache, all others are leaked. This wastes performance and memory.

On cache miss, add a future object to the cache to indicate that the
directory is currently being loaded. Subsequent threads register themselves
with the future object and wait. When the first thread has loaded the
directory, it replaces the future object with the result and notifies
waiting threads.

Signed-off-by: Karsten Blees <blees@dcon.de>
2026-01-28 14:30:02 +01:00
Karsten Blees
bf9f0e72e0 mingw: add a cache below mingw's lstat and dirent implementations
Checking the work tree status is quite slow on Windows, due to slow
`lstat()` emulation (git calls `lstat()` once for each file in the
index). Windows operating system APIs seem to be much better at scanning
the status of entire directories than checking single files.

Add an `lstat()` implementation that uses a cache for lstat data. Cache
misses read the entire parent directory and add it to the cache.
Subsequent `lstat()` calls for the same directory are served directly
from the cache.

Also implement `opendir()`/`readdir()`/`closedir()` so that they create
and use directory listings in the cache.

The cache doesn't track file system changes and doesn't plug into any
modifying file APIs, so it has to be explicitly enabled for git functions
that don't modify the working copy.

Note: in an earlier version of this patch, the cache was always active and
tracked file system changes via ReadDirectoryChangesW. However, this was
much more complex and had negative impact on the performance of modifying
git commands such as 'git checkout'.

Signed-off-by: Karsten Blees <blees@dcon.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:02 +01:00
Karsten Blees
5ded7b7efc mingw: add infrastructure for read-only file system level caches
Add a macro to mark code sections that only read from the file system,
along with a config option and documentation.

This facilitates implementation of relatively simple file system level
caches without the need to synchronize with the file system.

Enable read-only sections for 'git status' and preload_index.

Signed-off-by: Karsten Blees <blees@dcon.de>
2026-01-28 14:30:02 +01:00
Karsten Blees
cb36770f67 Win32: make the lstat implementation pluggable
Emulating the POSIX lstat API on Windows via GetFileAttributes[Ex] is quite
slow. Windows operating system APIs seem to be much better at scanning the
status of entire directories than checking single files. A caching
implementation may improve performance by bulk-reading entire directories
or reusing data obtained via opendir / readdir.

Make the lstat implementation pluggable so that it can be switched at
runtime, e.g. based on a config option.

Signed-off-by: Karsten Blees <blees@dcon.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:02 +01:00
Karsten Blees
c65ad577c8 mingw: make the dirent implementation pluggable
Emulating the POSIX `dirent` API on Windows via
`FindFirstFile()`/`FindNextFile()` is pretty staightforward, however,
most of the information provided in the `WIN32_FIND_DATA` structure is
thrown away in the process. A more sophisticated implementation may
cache this data, e.g. for later reuse in calls to `lstat()`.

Make the `dirent` implementation pluggable so that it can be switched at
runtime, e.g. based on a config option.

Define a base DIR structure with pointers to `readdir()`/`closedir()`
that match the `opendir()` implementation (similar to vtable pointers in
Object-Oriented Programming). Define `readdir()`/`closedir()` so that
they call the function pointers in the `DIR` structure. This allows to
choose the `opendir()` implementation on a call-by-call basis.

Make the fixed-size `dirent.d_name` buffer a flex array, as `d_name` may
be implementation specific (e.g. a caching implementation may allocate a
`struct dirent` with _just_ the size needed to hold the `d_name` in
question).

Signed-off-by: Karsten Blees <blees@dcon.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:02 +01:00
Karsten Blees
73c6e63635 Win32: dirent.c: Move opendir down
Move opendir down in preparation for the next patch.

Signed-off-by: Karsten Blees <blees@dcon.de>
2026-01-28 14:30:02 +01:00
Karsten Blees
91dcc05d47 Win32: make FILETIME conversion functions public
We will use them in the upcoming "FSCache" patches (to accelerate
sequential lstat() calls).

Signed-off-by: Karsten Blees <blees@dcon.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:02 +01:00
Johannes Schindelin
f53e6dee8c t/t5571-prep-push-hook.sh: Add test with writing to stderr (#6063)
Git v2.53.0-rc0 included f406b895529 (Merge branch
'ar/run-command-hook', 2026-01-06), which caused a regression on
Windows. While this merge was reverted for independent reasons in
a3d1f391d35 (Revert "Merge branch 'ar/run-command-hook'", 2026-01-15),
it seems worthwhile to ensure that writing to standard error from a
`pre-push` hook remains unbroken.

The symptom, when running this regression test case against
v2.53.0-rc0.windows.1 is that the `git push` fails, with this message
printed to standard error:

.git/hooks/pre-push: line 2: /dev/stderr: No such file or
direct[61/1940]
   error: failed to push some refs to 'repo1'

When that hook runs, `/dev/stderr` is a symlink to `/proc/self/fd/2`, as
always, but `ls -l /proc/self/fd/` shows this in the failing run

  total 0
  lrwxrwxrwx 1 me 4096 0 Jan 27 14:34 0 -> pipe:[0]
  lrwxrwxrwx 1 me 4096 0 Jan 27 14:34 1 -> pipe:[0]
  lrwxrwxrwx 1 me 4096 0 Jan 27 14:34 2 -> pipe:[0]

instead of the expected contents (which are shown when running this
against v2.53.0-rc1.windows.1):

  total 0
  lrwxrwxrwx 1 me 4096 0 Jan 27 14:53 0 -> 'pipe:[0]'
  lrwxrwxrwx 1 me 4096 0 Jan 27 14:53 1 -> /dev/cons1
lrwxrwxrwx 1 me 4096 0 Jan 27 14:53 2 -> '/path/to/git/t/trash
directory.t5571-pre-push-hook/actual'

This suggests that the underlying reason might be that `stdout` has an
exclusive handle to that pipe, and opening `stderr` (which points to the
same pipe) fails because of that exclusively-opened `stdout` handle.

This closes https://github.com/git-for-windows/git/issues/6053.
2026-01-28 14:30:01 +01:00
Johannes Schindelin
65299eec03 Merge branch 'check-whitespace-only-downstream'
To avoid `check-whitespace` failures when rebasing Git for Windows onto
new Git versions, let's limit that job's scope to downstream commits.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:01 +01:00
Johannes Schindelin
7af34d51cf Merge branch 'reftable-vs-custom-allocators'
Currently not _strictly_ necessary, but still good to have.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:01 +01:00
Johannes Schindelin
60e32e7f07 credential-cache: handle ECONNREFUSED gracefully (#5329)
I should probably add some tests for this.
2026-01-28 14:30:01 +01:00
Johannes Schindelin
f3c163f4a4 Add experimental 'git survey' builtin (#5174)
This introduces `git survey` to Git for Windows ahead of upstream for
the express purpose of getting the path-based analysis in the hands of
more folks.

The inspiration of this builtin is
[`git-sizer`](https://github.com/github/git-sizer), but since that
command relies on `git cat-file --batch` to get the contents of objects,
it has limits to how much information it can provide.

This is mostly a rewrite of the `git survey` builtin that was introduced
into the `microsoft/git` fork in microsoft/git#667. That version had a
lot more bells and whistles, including an analysis much closer to what
`git-sizer` provides.

The biggest difference in this version is that this one is focused on
using the path-walk API in order to visit batches of objects based on a
common path. This allows identifying, for instance, the path that is
contributing the most to the on-disk size across all versions at that
path.

For example, here are the top ten paths contributing to my local Git
repository (which includes `microsoft/git` and `gitster/git`):

```
TOP FILES BY DISK SIZE
============================================================================
                                    Path | Count | Disk Size | Inflated Size
-----------------------------------------+-------+-----------+--------------
                       whats-cooking.txt |  1373 |  11637459 |      37226854
             t/helper/test-gvfs-protocol |     2 |   6847105 |      17233072
                      git-rebase--helper |     1 |   6027849 |      15269664
                          compat/mingw.c |  6111 |   5194453 |     463466970
             t/helper/test-parse-options |     1 |   3420385 |       8807968
                  t/helper/test-pkt-line |     1 |   3408661 |       8778960
      t/helper/test-dump-untracked-cache |     1 |   3408645 |       8780816
            t/helper/test-dump-fsmonitor |     1 |   3406639 |       8776656
                                po/vi.po |   104 |   1376337 |      51441603
                                po/de.po |   210 |   1360112 |      71198603
```

This kind of analysis has been helpful in identifying the reasons for
growth in a few internal monorepos. Those findings motivated the changes
in #5157 and #5171.

With this early version in Git for Windows, we can expand the reach of
the experimental tool in advance of it being contributed to the upstream
project.

Unfortunately, this will mean that in the next `microsoft/git` rebase,
Jeff Hostetler's version will need to be pulled out since there are
enough conflicts. These conflicts include how tables are stored and
generated, as the version in this PR is slightly more general to allow
for different kinds of data.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:01 +01:00
Derrick Stolee
da40b4aa28 Add path walk API and its use in 'git pack-objects' (#5171)
This is a follow up to #5157 as well as motivated by the RFC in
gitgitgadget/git#1786.

We have ways of walking all objects, but it is focused on visiting a
single commit and then expanding the new trees and blobs reachable from
that commit that have not been visited yet. This means that objects
arrive without any locality based on their path.

Add a new "path walk API" that focuses on walking objects in batches
according to their type and path. This will walk all annotated tags, all
commits, all root trees, and then start a depth-first search among all
paths in the repo to collect trees and blobs in batches.

The most important application for this is being fast-tracked to Git for
Windows: `git pack-objects --path-walk`. This application of the path
walk API discovers the objects to pack via this batched walk, and
automatically groups objects that appear at a common path so they can be
checked for delta comparisons.

This use completely avoids any name-hash collisions (even the collisions
that sometimes occur with the new `--full-name-hash` option) and can be
much faster to compute since the first pass of delta calculations does
not waste time on objects that are unlikely to be diffable.

Some statistics are available in the commit messages.
2026-01-28 14:30:01 +01:00
Johannes Schindelin
10b1259e34 pack-objects: create new name-hash algorithm (#5157)
This is an updated version of gitgitgadget/git#1785, intended for early
consumption into Git for Windows.

The idea here is to add a new `--full-name-hash` option to `git
pack-objects` and `git repack`. This adjusts the name-hash value used
for finding delta bases in such a way that uses the full path name with
a lower likelihood of collisions than the default name-hash algorithm.
In many repositories with name-hash collisions and many versions of
those paths, this can significantly reduce the size of a full repack. It
can also help in certain cases of `git push`, but only if the pack is
already artificially inflated by name-hash collisions; cases that find
"sibling" deltas as better choices become worse with `--full-name-hash`.

Thus, this option is currently recommended for full repacks of large
repos, and on client machines without reachability bitmaps.

Some care is taken to ignore this option when using bitmaps, either
writing bitmaps or using a bitmap walk during reads. The bitmap file
format contains name-hash values, but no way to indicate which function
is used, so compatibility is a concern for bitmaps. Future work could
explore this idea.

After this PR is merged, then the more-involved `--path-walk` option may
be considered.
2026-01-28 14:30:01 +01:00
Johannes Schindelin
25929d0197 Merge branch 'run-command-be-helpful-when-Git-LFS-fails-on-Windows-7'
Since Git LFS v3.5.x implicitly dropped Windows 7 support, we now want
users to be advised _what_ is going wrong on that Windows version. This
topic branch goes out of its way to provide users with such guidance.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:01 +01:00
Johannes Schindelin
6cb30d8fb2 Merge branch 'Fallback-to-AppData-if-XDG-CONFIG-HOME-is-unset'
This topic branch adds support for a more Windows-native user-wide
config file than `XDG_CONFIG_HOME` (or `~/.config/`) will ever be.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:00 +01:00
Johannes Schindelin
d483502583 Merge branch 'Fix-i686-build-with-GCC-v14'
This fixes a long-time compile warning turned error by GCC v14.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:00 +01:00
Johannes Schindelin
7a1e55406a Merge branch 'run-t5601-and-t7406-with-symlinks-on-windows-10'
This topic branch contains a patch that made it into Git for Windows
v2.45.1 but not into Git v2.45.1 (because the latter does not come with
symlink support on Windows).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:00 +01:00
Johannes Schindelin
53e182a8b1 common-main.c: fflush stdout buffer when exit (#4901) 2026-01-28 14:30:00 +01:00
Johannes Schindelin
a214fc94b6 win32: use native ANSI sequence processing, if possible (#4700)
Windows 10 version 1511 (also known as Anniversary Update), according to
https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
introduced native support for ANSI sequence processing. This allows
using colors from the entire 24-bit color range.

All we need to do is test whether the console's "virtual processing
support" can be enabled. If it can, we do not even need to start the
`console_thread` to handle ANSI sequences.

Incidentally, this addresses
https://github.com/git-for-windows/git/issues/3712.
2026-01-28 14:30:00 +01:00
Johannes Schindelin
9962298e2d Additional error checks for issuing the windows.appendAtomically warning (#4528)
Another (hopefully clean) PR for showing the error warning about atomic
append on windows after failure on APFS, which returns EBADF not EINVAL.

Signed-off-by: David Lomas <dl3@pale-eds.co.uk>
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
2026-01-28 14:30:00 +01:00
Johannes Schindelin
118aa29327 Merge branch 'nano-server'
This patch adds a GitHub workflow (to be triggered manually) to allow
for conveniently verifying that Git and Scalar still work as intended in
Windows Nano Server (a relatively small container base image that is
frequently used where a "small Windows" is needed, e.g. in automation
;-))

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:30:00 +01:00
Johannes Schindelin
687ad9030e Lazy load libcurl, allowing for an SSL/TLS backend-specific libcurl (#4410)
As per
https://github.com/git-for-windows/git/issues/4350#issuecomment-1485041503,
the major block for upgrading Git for Windows' OpenSSL from v1.1 to v3
is the tricky part where such an upgrade would break `git fetch`/`git
clone` and `git push` because the libcurl depends on the OpenSSL DLL,
and the major version bump will _change_ the file name of said DLL.

To overcome that, the plan is to build libcurl flavors for each
supported SSL/TLS backend, aligning with the way MSYS2 builds libcurl,
then switch Git for Windows' SDK to the Secure Channel-flavored libcurl,
and teach Git to look for the specific flavor of libcurl corresponding
to the `http.sslBackend` setting (if that was configured).

Here is the PR to teach Git that trick.
2026-01-28 14:30:00 +01:00
Johannes Schindelin
43a5b95a7d ARM64: Embed manifest properly (#4718)
Teach our ARM64 based builds to embed the manifest file correctly.

This fixes #4707
2026-01-28 14:30:00 +01:00
Johannes Schindelin
cc7bb716b1 Merge pull request #2974 from derrickstolee/maintenance-and-headless
Include Windows-specific maintenance and headless-git
2026-01-28 14:30:00 +01:00
Johannes Schindelin
c7751e1661 Merge pull request #2506 from dscho/issue-2283
Allow running Git directly from `C:\Program Files\Git\mingw64\bin\git.exe`
2026-01-28 14:30:00 +01:00
Matthias Aßhauer
97118b0101 git.rc: include winuser.h
winuser.h contains the definition of RT_MANIFEST that our LLVM based
toolchain needs to understand that we want to embed
compat/win32/git.manifest as an application manifest. It currently just
embeds it as additional data that Windows doesn't understand.

This also helps our GCC based toolchain understand that we only want one
copy embedded. It currently embeds one working assembly manifest and one
nearly identical, but useless copy as additional data.

This also teaches our Visual Studio based buildsystems to pick up the
manifest file from git.rc. This means we don't have to explicitly specify
it in contrib/buildsystems/Generators/Vcxproj.pm anymore. Slightly
counter-intuitively this also means we have to explicitly tell Cmake
not to embed a default manifest.

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

Signed-off-by: Matthias Aßhauer <mha1993@live.de>
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
2026-01-28 14:29:58 +01:00
Yuyi Wang
2910ae0743 cmake: install headless-git.
headless-git is a git executable without opening a console window. It is
useful when other GUI executables want to call git. We should install it
together with git on Windows.

Signed-off-by: Yuyi Wang <Strawberry_Str@hotmail.com>
2026-01-28 14:29:58 +01:00
Johannes Schindelin
9a0a9c1ded mingw: ignore HOMEDRIVE/HOMEPATH if it points to Windows' system directory
Internally, Git expects the environment variable `HOME` to be set, and
to point to the current user's home directory.

This environment variable is not set by default on Windows, and
therefore Git tries its best to construct one if it finds `HOME` unset.

There are actually two different approaches Git tries: first, it looks
at `HOMEDRIVE`/`HOMEPATH` because this is widely used in corporate
environments with roaming profiles, and a user generally wants their
global Git settings to be in a roaming profile.

Only when `HOMEDRIVE`/`HOMEPATH` is either unset or does not point to a
valid location, Git will fall back to using `USERPROFILE` instead.

However, starting with Windows Vista, for secondary logons and services,
the environment variables `HOMEDRIVE`/`HOMEPATH` point to Windows'
system directory (usually `C:\Windows\system32`).

That is undesirable, and that location is usually write-protected anyway.

So let's verify that the `HOMEDRIVE`/`HOMEPATH` combo does not point to
Windows' system directory before using it, falling back to `USERPROFILE`
if it does.

This fixes git-for-windows#2709

Initial-Path-by: Ivan Pozdeev <vano@mail.mipt.ru>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:29:58 +01:00
Jeff Hostetler
a127f482d5 clink.pl: move default linker options for MSVC=1 builds
Move the default `-ENTRY` and `-SUBSYSTEM` arguments for
MSVC=1 builds from `config.mak.uname` into `clink.pl`.
These args are constant for console-mode executables.

Add support to `clink.pl` for generating a Win32 GUI application
using the `-mwindows` argument (to match how GCC does it).  This
changes the `-ENTRY` and `-SUBSYSTEM` arguments accordingly.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-01-28 14:29:58 +01:00
Jeff Hostetler
4a2e42ab88 clink.pl: ignore no-stack-protector arg on MSVC=1 builds
Ignore the `-fno-stack-protector` compiler argument when building
with MSVC.  This will be used in a later commit that needs to build
a Win32 GUI app.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-01-28 14:29:58 +01:00
Jeff Hostetler
4d1cc403e0 config.mak.uname: add git.rc to MSVC builds
Teach MSVC=1 builds to depend on the `git.rc` file so that
the resulting executables have Windows-style resources and
version number information within them.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-01-28 14:29:58 +01:00
Jeff Hostetler
26af83426c vcbuild: add support for compiling Windows resource files
Create a wrapper for the Windows Resource Compiler (RC.EXE)
for use by the MSVC=1 builds. This is similar to the CL.EXE
and LIB.EXE wrappers used for the MSVC=1 builds.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-01-28 14:29:58 +01:00
Jeff Hostetler
eb66711b2c Makefile: clean up .ilk files when MSVC=1
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-01-28 14:29:58 +01:00
Jeff Hostetler
b37402aaf8 clink.pl: fix libexpatd.lib link error when using MSVC
When building with `make MSVC=1 DEBUG=1`, link to `libexpatd.lib`
rather than `libexpat.lib`.

It appears that the `vcpkg` package for "libexpat" has changed and now
creates `libexpatd.lib` for debug mode builds.  Previously, both debug
and release builds created a ".lib" with the same basename.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2026-01-28 14:29:58 +01:00
Johannes Schindelin
e6ec40e4af Merge branch 'dscho-avoid-d-f-conflict-in-vs-master'
Merge this early to resolve merge conflicts early.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:29:58 +01:00
Johannes Schindelin
8e2d9a9098 mingw: allow git.exe to be used instead of the "Git wrapper"
Git for Windows wants to add `git.exe` to the users' `PATH`, without
cluttering the latter with unnecessary executables such as `wish.exe`.
To that end, it invented the concept of its "Git wrapper", i.e. a tiny
executable located in `C:\Program Files\Git\cmd\git.exe` (originally a
CMD script) whose sole purpose is to set up a couple of environment
variables and then spawn the _actual_ `git.exe` (which nowadays lives in
`C:\Program Files\Git\mingw64\bin\git.exe` for 64-bit, and the obvious
equivalent for 32-bit installations).

Currently, the following environment variables are set unless already
initialized:

- `MSYSTEM`, to make sure that the MSYS2 Bash and the MSYS2 Perl
  interpreter behave as expected, and

- `PLINK_PROTOCOL`, to force PuTTY's `plink.exe` to use the SSH
  protocol instead of Telnet,

- `PATH`, to make sure that the `bin` folder in the user's home
  directory, as well as the `/mingw64/bin` and the `/usr/bin`
  directories are included. The trick here is that the `/mingw64/bin/`
  and `/usr/bin/` directories are relative to the top-level installation
  directory of Git for Windows (which the included Bash interprets as
  `/`, i.e. as the MSYS pseudo root directory).

Using the absence of `MSYSTEM` as a tell-tale, we can detect in
`git.exe` whether these environment variables have been initialized
properly. Therefore we can call `C:\Program Files\Git\mingw64\bin\git`
in-place after this change, without having to call Git through the Git
wrapper.

Obviously, above-mentioned directories must be _prepended_ to the `PATH`
variable, otherwise we risk picking up executables from unrelated Git
installations. We do that by constructing the new `PATH` value from
scratch, appending `$HOME/bin` (if `HOME` is set), then the MSYS2 system
directories, and then appending the original `PATH`.

Side note: this modification of the `PATH` variable is independent of
the modification necessary to reach the executables and scripts in
`/mingw64/libexec/git-core/`, i.e. the `GIT_EXEC_PATH`. That
modification is still performed by Git, elsewhere, long after making the
changes described above.

While we _still_ cannot simply hard-link `mingw64\bin\git.exe` to `cmd`
(because the former depends on a couple of `.dll` files that are only in
`mingw64\bin`, i.e. calling `...\cmd\git.exe` would fail to load due to
missing dependencies), at least we can now avoid that extra process of
running the Git wrapper (which then has to wait for the spawned
`git.exe` to finish) by calling `...\mingw64\bin\git.exe` directly, via
its absolute path.

Testing this is in Git's test suite tricky: we set up a "new" MSYS
pseudo-root and copy the `git.exe` file into the appropriate location,
then verify that `MSYSTEM` is set properly, and also that the `PATH` is
modified so that scripts can be found in `$HOME/bin`, `/mingw64/bin/`
and `/usr/bin/`.

This addresses https://github.com/git-for-windows/git/issues/2283

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:29:53 +01:00
Johannes Schindelin
b53fe0e7ed mingw: ensure valid CTYPE
A change between versions 2.4.1 and 2.6.0 of the MSYS2 runtime modified
how Cygwin's runtime (and hence Git for Windows' MSYS2 runtime
derivative) handles locales: d16a56306d (Consolidate wctomb/mbtowc calls
for POSIX-1.2008, 2016-07-20).

An unintended side-effect is that "cold-calling" into the POSIX
emulation will start with a locale based on the current code page,
something that Git for Windows is very ill-prepared for, as it expects
to be able to pass a command-line containing non-ASCII characters to the
shell without having those characters munged.

One symptom of this behavior: when `git clone` or `git fetch` shell out
to call `git-upload-pack` with a path that contains non-ASCII
characters, the shell tried to interpret the entire command-line
(including command-line parameters) as executable path, which obviously
must fail.

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

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 14:27:37 +01:00
Thomas Braun
541d54bc01 t/t5571-prep-push-hook.sh: Add test with writing to stderr
The 2.53.0.rc0.windows release candidate had a regression where
writing to stderr from a pre-push hook would error out.

The regression was fixed in 2.53.0.rc1.windows and the test here ensures
that this stays fixed.

Signed-off-by: Thomas Braun <thomas.braun@virtuell-zuhause.de>
2026-01-28 09:48:09 +01:00
Johannes Schindelin
23b1b383ec Add full mingw-w64-git (i.e. regular MSYS2 ecosystem) support (#5971)
Every once in a while, there are bug reports in Git for Windows' bug
tracker that describe an issue running [inside MSYS2
proper](https://gitforwindows.org/install-inside-msys2-proper), totally
ignoring the big, honking warning on top of [the
page](https://gitforwindows.org/install-inside-msys2-proper) that spells
out clearly that this is an unsupported use case.

At the same time, we cannot easily deflect and say "just use MSYS2
directly" (and leave the "and stop pestering us" out). We cannot do that
because there is only an _MSYS_ `git` package in MSYS2 (i.e. a Git that
uses the quite slow POSIX emulation layer provided by the MSYS2
runtime), but no `mingw-w64-git` package (which would be equivalent in
speed to Git for Windows).

In https://github.com/msys2/MINGW-packages/pull/26470, I am preparing to
change that. As part of that PR, I noticed and fixed a couple of issues
_in `git-for-windows/git` that prevented full support for
`mingw-w64-git` in MSYS2, such as problems with CLANG64 and UCRT64.

While at it, I simplified the entire setup to trust MSYS2's
`MINGW_PREFIX` & related environment variables instead of hard-coding
values like the installation prefix and what `MSYSTEM` to fall back on
if it is unset.
2026-01-28 07:39:02 +01:00
Johannes Schindelin
7a2d2d422c Skip linking the "dashed" git-<command>s for built-ins (#4252)
It is merely a historical wart that, say, `git-commit` exists in the
`libexec/git-core/` directory, a tribute to the original idea to let Git
be essentially a bunch of Unix shell scripts revolving around very few
"plumbing" (AKA low-level) commands.

Git has evolved a lot from there. These days, most of Git's
functionality is contained within the `git` executable, in the form of
"built-in" commands.

To accommodate for scripts that use the "dashed" form of Git commands,
even today, Git provides hard-links that make the `git` executable
available as, say, `git-commit`, just in case that an old script has not
been updated to invoke `git commit`.

Those hard-links do not come cheap: they take about half a minute for
every build of Git on Windows, they are mistaken for taking up huge
amounts of space by some Windows Explorer versions that do not
understand hard-links, and therefore many a "bug" report had to be
addressed.

The "dashed form" has been officially deprecated in Git version 1.5.4,
which was released on February 2nd, 2008, i.e. a very long time ago.
This deprecation was never finalized by skipping these hard-links, but
we can start the process now, in Git for Windows.

This addresses the concern raised in
https://github.com/git-for-windows/git/pull/4185#discussion_r1051661894
2026-01-28 07:39:02 +01:00
Johannes Schindelin
6217166e74 Fix global repository field not being cleared (#4083)
It is checked for w.r.t. global repository struct down in the callstack
in compatibility layer for MinGW before being assigned in the function
that `free()`'d it.
2026-01-28 07:39:01 +01:00
Johannes Schindelin
5db2326416 Fix Windows version resources (#4092)
Add `FileVersion`, which is a required string ([Microsoft
documentation](https://learn.microsoft.com/en-us/windows/win32/menurc/versioninfo-resource))
in the `StringFileInfo` block.
As not all required strings were present in the block, none were being
included.
Fixes #4090

After including the `FileVersion` string, all other defined strings are
now being included on executables.

File version information for `git.exe` has changed from:
```
PS C:\Program Files\Git\bin> [System.Diagnostics.FileVersionInfo]::GetVersionInfo("C:\Data\git-sdk-64\usr\src\git\git.exe") | Select-Object *

FileVersionRaw     : 2.38.1.1
ProductVersionRaw  : 2.38.1.1
Comments           :
CompanyName        :
FileBuildPart      : 1
FileDescription    :
FileMajorPart      : 2
FileMinorPart      : 38
FileName           : C:\Data\git-sdk-64\usr\src\git\git.exe
FilePrivatePart    : 1
FileVersion        :
InternalName       :
IsDebug            : False
IsPatched          : False
IsPrivateBuild     : False
IsPreRelease       : False
IsSpecialBuild     : False
Language           : English (United States)
LegalCopyright     :
LegalTrademarks    :
OriginalFilename   :
PrivateBuild       :
ProductBuildPart   : 1
ProductMajorPart   : 2
ProductMinorPart   : 38
ProductName        :
ProductPrivatePart : 1
ProductVersion     :
SpecialBuild       :
```

To the following:
```
PS C:\Program Files\Git\bin> [System.Diagnostics.FileVersionInfo]::GetVersionInfo("C:\Data\git-sdk-64\usr\src\git\git.exe") | Select-Object *

FileVersionRaw     : 2.38.1.1
ProductVersionRaw  : 2.38.1.1
Comments           :
CompanyName        : The Git Development Community
FileBuildPart      : 1
FileDescription    : Git for Windows
FileMajorPart      : 2
FileMinorPart      : 38
FileName           : C:\Data\git-sdk-64\usr\src\git\git.exe
FilePrivatePart    : 1
FileVersion        : 2.38.1.windows.1.10.g6ed65a6fab
InternalName       : git
IsDebug            : False
IsPatched          : False
IsPrivateBuild     : False
IsPreRelease       : False
IsSpecialBuild     : False
Language           : English (United States)
LegalCopyright     :
LegalTrademarks    :
OriginalFilename   : git.exe
PrivateBuild       :
ProductBuildPart   : 1
ProductMajorPart   : 2
ProductMinorPart   : 38
ProductName        : Git
ProductPrivatePart : 1
ProductVersion     : 2.38.1.windows.1.10.g6ed65a6fab
SpecialBuild       :
```

I wasn't really expecting `GIT_VERSION` to contain the Git commit, I was
hoping for just `2.38.1` or `2.38.1.1`, at least for the `FileVersion`
string.

Anybody know if it's possible to concatenate the `MAJOR`, `MINOR`,
`MICRO`, and `PATCHLEVEL` fields with dots, or if there's another
variable that can be used (with or without `PATCHLEVEL`)?
Alternatively, use the complete `GIT_VERSION` for both `FileVersion` and
`ProductVersion`.
2026-01-28 07:39:01 +01:00
Johannes Schindelin
7fd7a49082 Merge pull request #3942 from rimrul/mingw-tsaware
MinGW: link as terminal server aware
2026-01-28 07:39:01 +01:00
Johannes Schindelin
28e5687b2b Merge branch 'fsync-object-files-always'
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:39:01 +01:00
Johannes Schindelin
b9e732d4a9 Merge branch 'optionally-dont-append-atomically-on-windows'
Fix append failure issue under remote directories #2753

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:39:01 +01:00
Johannes Schindelin
bd97b7accc Merge pull request #3875 from 1480c1/wine/detect_msys_tty
winansi: check result before using Name for pty
2026-01-28 07:39:01 +01:00
Johannes Schindelin
6a8807ad5c Merge pull request #3751 from rkitover/native-term
mingw: set $env:TERM=xterm-256color for newer OSes
2026-01-28 07:39:01 +01:00
Derrick Stolee
9a70cad330 Merge pull request #3791: Various fixes around safe.directory
The first three commits are rebased versions of those in gitgitgadget/git#1215. These allow the following:

1. Fix `git config --global foo.bar <path>` from allowing the `<path>`. As a bonus, users with a config value starting with `/` will not get a warning about "old-style" paths needing a "`%(prefix)/`".

2. When in WSL, the path starts with `/` so it needs to be interpolated properly. Update the warning to include `%(prefix)/` to get the right value for WSL users. (This is specifically for using Git for Windows from Git Bash, but in a WSL directory.)

3. When using WSL, the ownership check fails and reports an error message. This is noisy, and happens even if the user has marked the path with `safe.directory`. Remove that error message.
2026-01-28 07:39:01 +01:00
Johannes Schindelin
b6b0d41dd7 Merge pull request #3533 from PhilipOakley/hashliteral_t
Begin `unsigned long`->`size_t` conversion to support large files on Windows
2026-01-28 07:39:01 +01:00
Johannes Schindelin
c8703368a5 Merge pull request #3306 from PhilipOakley/vs-sln
Make Git for Windows start builds in modern Visual Studio
2026-01-28 07:39:00 +01:00
Johannes Schindelin
98234fcc22 Merge pull request #3349 from vdye/feature/ci-subtree-tests
Add `contrib/subtree` test execution to CI builds
2026-01-28 07:39:00 +01:00
Johannes Schindelin
70cc441491 Merge pull request #3293 from pascalmuller/http-support-automatically-sending-client-certificate
http: Add support for enabling automatic sending of SSL client certificate
2026-01-28 07:39:00 +01:00
Johannes Schindelin
d486ed7f80 Merge pull request #3220 from dscho/there-is-no-vs/master-anymore
Let the documentation reflect that there is no vs/master anymore
2026-01-28 07:39:00 +01:00
Johannes Schindelin
5eeb594d29 Merge pull request #3165 from dscho/increase-allowed-length-of-interpreter-path
mingw: allow for longer paths in `parse_interpreter()`
2026-01-28 07:39:00 +01:00
Johannes Schindelin
a13ee5cc4b Merge pull request #3327 from dennisameling/fix-host-cpu
cmake(): allow setting HOST_CPU for cross-compilation
2026-01-28 07:39:00 +01:00
Johannes Schindelin
85d16b1646 Merge pull request #2915 from dennisameling/windows-arm64-support
Windows arm64 support
2026-01-28 07:39:00 +01:00
Johannes Schindelin
238ea8760f Merge pull request #2351 from PhilipOakley/vcpkg-tip
Vcpkg Install: detect lack of working Git, and note possible vcpkg time outs
2026-01-28 07:39:00 +01:00
Johannes Schindelin
0b1660c8e7 Merge 'git-gui/js/intent-to-add'
This merges the current version of the patch that tries to address Git
GUI's problems with intent-to-add files.

This patch will likely be improved substantially before it is merged
into Git GUI's main branch, but we want to have _something_ resembling a
fix already in Git for Windows v2.29.0.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:59 +01:00
Johannes Schindelin
d1be88d2bf Merge pull request #2655 from jglathe/jg/t0014_trace_extra_info
t/t0014: fix: eliminate additional lines from trace
2026-01-28 07:38:59 +01:00
Johannes Schindelin
daee3f4a30 Merge pull request #2714 from lbonanomi/crlf-scissors
Rationalize line endings for scissors-cleanup
2026-01-28 07:38:59 +01:00
Johannes Schindelin
3eb5d18aa1 Merge 'add-p-many-files'
This topic branch allows `add -p` and `add -i` with a large number of
files. It is kind of a hack that was never really meant to be
upstreamed. Let's see if we can do better in the built-in `add -p`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:59 +01:00
Johannes Schindelin
d048f44aa3 Merge pull request #2618 from dscho/avoid-d/f-conflict-in-vs/master
ci: avoid d/f conflict in vs/master
2026-01-28 07:38:59 +01:00
Johannes Schindelin
fdaf080621 Merge pull request #2535 from dscho/schannel-revoke-best-effort
Introduce and use the new "best effort" strategy for Secure Channel revoke checking
2026-01-28 07:38:59 +01:00
Johannes Schindelin
f3a7f9ca9d Merge pull request #2504 from dscho/access-repo-via-junction
Handle `git add <file>` where <file> traverses an NTFS junction
2026-01-28 07:38:59 +01:00
Johannes Schindelin
8a4340d467 Merge pull request #2501 from jeffhostetler/clink-debug-curl
clink.pl: fix MSVC compile script to handle libcurl-d.lib
2026-01-28 07:38:59 +01:00
Johannes Schindelin
e1a6400f8d check-whitespace: avoid alerts about upstream commits
Every once in a while, whitespace errors are introduced in Git for
Windows' rebases to newer Git versions, simply by virtue of integrating
upstream commits that do not follow upstream Git's own whitespace rule.
In Git v2.50.0-rc0, for example, 03f2915541a4 (xdiff: disable
cleanup_records heuristic with --minimal, 2025-04-29) introduced a
trailing space.

Arguably, non-actionable alerts are worse than no alerts at all, so
let's suppress those alerts that we cannot do anything about, anyway.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:58 +01:00
Johannes Schindelin
746fc5e0ce reftable: do make sure to use custom allocators
The reftable library goes out of its way to use its own set of allocator
functions that can be configured using `reftable_set_alloc()`. However,
Git does not configure this.

That is not typically a problem, except when Git uses a custom allocator
via some definitions in `git-compat-util.h`, as is the case in Git for
Windows (which switched away from the long-unmaintained nedmalloc to
mimalloc).

Then, it is quite possible that Git assigns a `strbuf` (allocated via
the custom allocator) to, say, the `refname` field of a
`reftable_log_record` in `write_transaction_table()`, and later on asks
the reftable library function `reftable_log_record_release()` to release
it, but that function was compiled without using `git-compat-util.h` and
hence calls regular `free()` (i.e. _not_ the custom allocator's own
function).

This has been a problem for a long time and it was a matter of some sort
of "luck" that 1) reftables are not commonly used on Windows, and 2)
mimalloc can often ignore gracefully when it is asked to release memory
that it has not allocated.

However, a recent update to `seen` brought this problem to the
forefront, letting t1460 fail in Git for Windows, with symptoms much in
the same way as the problem I had to address in d02c37c3e6ba
(t-reftable-basics: allow for `malloc` to be `#define`d, 2025-01-08)
where exit code 127 was also produced in lieu of
`STATUS_HEAP_CORRUPTION` (C0000374) because exit codes are only 7 bits
wide.

It was not possible to figure out what change in particular caused these
new failures within a reasonable time frame, as there are too many
changes in `seen` that conflict with Git for Windows' patches, I had to
stop the investigation after spending four hours on it fruitlessly.

To verify that this patch fixes the issue, I avoided using mimalloc and
temporarily patched in a "custom allocator" that would more reliably
point out problems, like this:

  diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
  index 68f38291f84c..9421d630b9f5 100644
  --- a/refs/reftable-backend.c
  +++ b/refs/reftable-backend.c
  @@ -353,6 +353,69 @@ static int reftable_be_fsync(int fd)
   	return fsync_component(FSYNC_COMPONENT_REFERENCE, fd);
   }

  +#define DEBUG_REFTABLE_ALLOC
  +#ifdef DEBUG_REFTABLE_ALLOC
  +#include "khash.h"
  +
  +static inline khint_t __ac_X31_hash_ptr(void *ptr)
  +{
  +	union {
  +		void *ptr;
  +		char s[sizeof(void *)];
  +	} u;
  +	size_t i;
  +	khint_t h;
  +
  +	u.ptr = ptr;
  +	h = (khint_t)*u.s;
  +	for (i = 0; i < sizeof(void *); i++)
  +		h = (h << 5) - h + (khint_t)u.s[i];
  +	return h;
  +}
  +
  +#define kh_ptr_hash_func(key) __ac_X31_hash_ptr(key)
  +#define kh_ptr_hash_equal(a, b) ((a) == (b))
  +
  +KHASH_INIT(ptr, void *, int, 0, kh_ptr_hash_func, kh_ptr_hash_equal)
  +
  +static kh_ptr_t *my_malloced;
  +
  +static void *my_malloc(size_t sz)
  +{
  +	int dummy;
  +	void *ptr = malloc(sz);
  +	if (ptr)
  +		kh_put_ptr(my_malloced, ptr, &dummy);
  +	return ptr;
  +}
  +
  +static void *my_realloc(void *ptr, size_t sz)
  +{
  +	int dummy;
  +	if (ptr) {
  +		khiter_t pos = kh_get_ptr(my_malloced, ptr);
  +		if (pos >= kh_end(my_malloced))
  +			die("Was not my_malloc()ed: %p", ptr);
  +		kh_del_ptr(my_malloced, pos);
  +	}
  +	ptr = realloc(ptr, sz);
  +	if (ptr)
  +		kh_put_ptr(my_malloced, ptr, &dummy);
  +	return ptr;
  +}
  +
  +static void my_free(void *ptr)
  +{
  +	if (ptr) {
  +		khiter_t pos = kh_get_ptr(my_malloced, ptr);
  +		if (pos >= kh_end(my_malloced))
  +			die("Was not my_malloc()ed: %p", ptr);
  +		kh_del_ptr(my_malloced, pos);
  +	}
  +	free(ptr);
  +}
  +#endif
  +
   static struct ref_store *reftable_be_init(struct repository *repo,
   					  const char *gitdir,
   					  unsigned int store_flags)
  @@ -362,6 +425,11 @@ static struct ref_store *reftable_be_init(struct repository *repo,
   	int is_worktree;
   	mode_t mask;

  +#ifdef DEBUG_REFTABLE_ALLOC
  +	my_malloced = kh_init_ptr();
  +	reftable_set_alloc(my_malloc, my_realloc, my_free);
  +#endif
  +
   	mask = umask(0);
   	umask(mask);

I briefly considered contributing this "custom allocator" patch, too,
but it is unwieldy (for example, it would not work at all when compiling
with mimalloc support) and it would only waste space (or even time, if a
compile flag was introduced and exercised as part of the CI builds).
Given that it is highly unlikely that Git will lose the new
`reftable_set_alloc()` call by mistake, I rejected that idea as simply
too wasteful.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:58 +01:00
Johannes Schindelin
c2454dd6b2 Merge pull request #2488 from bmueller84/master
mingw: fix fatal error working on mapped network drives on Windows
2026-01-28 07:38:58 +01:00
Johannes Schindelin
67cb9f60c0 Merge pull request #2375 from assarbad/reintroduce-sideband-config
Config option to disable side-band-64k for transport
2026-01-28 07:38:58 +01:00
Johannes Schindelin
886675521b Update mimalloc to v2.2.7 (#6048)
After releasing v2.2.6, they followed up really quickly with a v2.2.7,
which indicates some urgency in taking this update. The diff of this PR
is pretty informative, too.

This closes https://github.com/git-for-windows/git/issues/6046
2026-01-28 07:38:58 +01:00
Johannes Schindelin
f922e6d3d4 Merge branch 'msys2-python'
In MSYS2, we have two Python interpreters at our disposal, so we can
include the Python stuff in the build.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:58 +01:00
Johannes Schindelin
ea9d3c5dde Merge branch 'dont-clean-junctions'
This topic branch teaches `git clean` to respect NTFS junctions and Unix
bind mounts: it will now stop at those boundaries.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:58 +01:00
Johannes Schindelin
6dec875a3d Merge branch 'drive-prefix'
This topic branch allows us to specify absolute paths without the drive
prefix e.g. when cloning.

Example:

	C:\Users\me> git clone https://github.com/git/git \upstream-git

This will clone into a new directory C:\upstream-git, in line with how
Windows interprets absolute paths.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:58 +01:00
Johannes Schindelin
169bba6894 Merge 'remote-hg-prerequisites' into HEAD
These fixes were necessary for Sverre Rabbelier's remote-hg to work,
but for some magic reason they are not necessary for the current
remote-hg. Makes you wonder how that one gets away with it.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:58 +01:00
Matthias Aßhauer
fdc5dd88d8 credential-cache: handle ECONNREFUSED gracefully
In 245670c (credential-cache: check for windows specific errors, 2021-09-14)
we concluded that on Windows we would always encounter ENETDOWN where we
would expect ECONNREFUSED on POSIX systems, when connecting to unix sockets.
As reported in [1], we do encounter ECONNREFUSED on Windows if the
socket file doesn't exist, but the containing directory does and ENETDOWN if
neither exists. We should handle this case like we do on non-windows systems.

[1] https://github.com/git-for-windows/git/pull/4762#issuecomment-2545498245

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

Helped-by: M Hickford <mirth.hickford@gmail.com>
Signed-off-by: Matthias Aßhauer <mha1993@live.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:57 +01:00
Johannes Schindelin
e04c2735ea survey: clearly note the experimental nature in the output
While this command is definitely something we _want_, chances are that
upstreaming this will require substantial changes.

We still want to be able to experiment with this before that, to focus
on what we need out of this command: To assist with diagnosing issues
with large repositories, as well as to help monitoring the growth and
the associated painpoints of such repositories.

To that end, we are about to integrate this command into
`microsoft/git`, to get the tool into the hands of users who need it
most, with the idea to iterate in close collaboration between these
users and the developers familar with Git's internals.

However, we will definitely want to avoid letting anybody have the
impression that this command, its exact inner workings, as well as its
output format, are anywhere close to stable. To make that fact utterly
clear (and thereby protect the freedom to iterate and innovate freely
before upstreaming the command), let's mark its output as experimental
in all-caps, as the first thing we do.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:57 +01:00
Matthias Aßhauer
3ce045cd66 t0301: actually test credential-cache on Windows
Commit 2406bf5 (Win32: detect unix socket support at runtime,
2024-04-03) introduced a runtime detection for whether the operating
system supports unix sockets for Windows, but a mistake snuck into the
tests. When building and testing Git without NO_UNIX_SOCKETS we
currently skip t0301-credential-cache on Windows if unix sockets are
supported and run the tests if they aren't.

Flip that logic to actually work the way it was intended.

Signed-off-by: Matthias Aßhauer <mha1993@live.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:57 +01:00
Derrick Stolee
07beb8f5f5 survey: add --top=<N> option and config
The 'git survey' builtin provides several detail tables, such as "top
files by on-disk size". The size of these tables defaults to 10,
currently.

Allow the user to specify this number via a new --top=<N> option or the
new survey.top config key.

Signed-off-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:57 +01:00
Matthias Aßhauer
79c8bcc695 compat/mingw: drop outdated comment
This comment has been true for the longest time; The combination of the
two preceding commits made it incorrect, so let's drop that comment.

Signed-off-by: Matthias Aßhauer <mha1993@live.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:57 +01:00
Derrick Stolee
338e9b9360 survey: add report of "largest" paths
Since we are already walking our reachable objects using the path-walk API,
let's now collect lists of the paths that contribute most to different
metrics. Specifically, we care about

 * Number of versions.
 * Total size on disk.
 * Total inflated size (no delta or zlib compression).

This information can be critical to discovering which parts of the
repository are causing the most growth, especially on-disk size. Different
packing strategies might help compress data more efficiently, but the toal
inflated size is a representation of the raw size of all snapshots of those
paths. Even when stored efficiently on disk, that size represents how much
information must be processed to complete a command such as 'git blame'.

The exact disk size seems to be not quite robust enough for testing, as
could be seen by the `linux-musl-meson` job consistently failing, possibly
because of zlib-ng deflates differently: t8100.4(git survey
(default)) was failing with a symptom like this:

   TOTAL OBJECT SIZES BY TYPE
   ===============================================
   Object Type | Count | Disk Size | Inflated Size
   ------------+-------+-----------+--------------
  -    Commits |    10 |      1523 |          2153
  +    Commits |    10 |      1528 |          2153
         Trees |    10 |       495 |          1706
         Blobs |    10 |       191 |           101
  -       Tags |     4 |       510 |           528
  +       Tags |     4 |       547 |           528

This means: the disk size is unlikely something we can verify robustly.
Since zlib-ng seems to increase the disk size of the tags from 528 to
547, we cannot even assume that the disk size is always smaller than the
inflated size. We will most likely want to either skip verifying the
disk size altogether, or go for some kind of fuzzy matching, say, by
replacing `s/ 1[45][0-9][0-9] / ~1.5k /` and `s/ [45][0-9][0-9] / ~½k /`
or something like that.

Signed-off-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:57 +01:00
Matthias Aßhauer
6358efd8b2 compat/mingw: handle WSA errors in strerror
We map WSAGetLastError() errors to errno errors in winsock_error_to_errno(),
but the MSVC strerror() implementation only produces "Unknown error" for
most of them. Produce some more meaningful error messages in these
cases.

Our builds for ARM64 link against the newer UCRT strerror() that does know
these errors, so we won't change the strerror() used there.

The wording of the messages is copied from glibc strerror() messages.

Reported-by: M Hickford <mirth.hickford@gmail.com>
Signed-off-by: Matthias Aßhauer <mha1993@live.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:57 +01:00
Derrick Stolee
3dcc8daf86 survey: add ability to track prioritized lists
In future changes, we will make use of these methods. The intention is to
keep track of the top contributors according to some metric. We don't want
to store all of the entries and do a sort at the end, so track a
constant-size table and remove rows that get pushed out depending on the
chosen sorting algorithm.

Co-authored-by: Jeff Hostetler <git@jeffhostetler.com>
Signed-off-by; Jeff Hostetler <git@jeffhostetler.com>
Signed-off-by: Derrick Stolee <stolee@gmail.com>
2026-01-28 07:38:57 +01:00
Johannes Schindelin
c797e5aa3a mingw: make sure errno is set correctly when socket operations fail
The winsock2 library provides functions that work on different data
types than file descriptors, therefore we wrap them.

But that is not the only difference: they also do not set `errno` but
expect the callers to enquire about errors via `WSAGetLastError()`.

Let's translate that into appropriate `errno` values whenever the socket
operations fail so that Git's code base does not have to change its
expectations.

This closes https://github.com/git-for-windows/git/issues/2404

Helped-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:57 +01:00
Derrick Stolee
7879885db3 survey: show progress during object walk
Signed-off-by: Derrick Stolee <stolee@gmail.com>
2026-01-28 07:38:57 +01:00
Derrick Stolee
03f77f8e97 survey: summarize total sizes by object type
Now that we have explored objects by count, we can expand that a bit more to
summarize the data for the on-disk and inflated size of those objects. This
information is helpful for diagnosing both why disk space (and perhaps
clone or fetch times) is growing but also why certain operations are slow
because the inflated size of the abstract objects that must be processed is
so large.

Note: zlib-ng is slightly more efficient even at those small sizes. Even
between zlib versions, there are slight differences in compression. To
accommodate for that in the tests, not the exact numbers but some rough
approximations are validated (the test should validate `git survey`,
after all, not zlib).

Signed-off-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:57 +01:00
Derrick Stolee
1743754fef survey: add object count summary
At the moment, nothing is obvious about the reason for the use of the
path-walk API, but this will become more prevelant in future iterations. For
now, use the path-walk API to sum up the counts of each kind of object.

For example, this is the reachable object summary output for my local repo:

REACHABLE OBJECT SUMMARY
========================
Object Type |  Count
------------+-------
       Tags |   1343
    Commits | 179344
      Trees | 314350
      Blobs | 184030

Signed-off-by: Derrick Stolee <stolee@gmail.com>
2026-01-28 07:38:57 +01:00
Derrick Stolee
949cf92170 survey: start pretty printing data in table form
When 'git survey' provides information to the user, this will be presented
in one of two formats: plaintext and JSON. The JSON implementation will be
delayed until the functionality is complete for the plaintext format.

The most important parts of the plaintext format are headers specifying the
different sections of the report and tables providing concreted data.

Create a custom table data structure that allows specifying a list of
strings for the row values. When printing the table, check each column for
the maximum width so we can create a table of the correct size from the
start.

The table structure is designed to be flexible to the different kinds of
output that will be implemented in future changes.

Signed-off-by: Derrick Stolee <stolee@gmail.com>
2026-01-28 07:38:57 +01:00
Jeff Hostetler
ac99a8f352 survey: add command line opts to select references
By default we will scan all references in "refs/heads/", "refs/tags/"
and "refs/remotes/".

Add command line opts let the use ask for all refs or a subset of them
and to include a detached HEAD.

Signed-off-by: Jeff Hostetler <git@jeffhostetler.com>
Signed-off-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
2026-01-28 07:38:57 +01:00
Jeff Hostetler
c99f45051c survey: stub in new experimental 'git-survey' command
Start work on a new 'git survey' command to scan the repository
for monorepo performance and scaling problems.  The goal is to
measure the various known "dimensions of scale" and serve as a
foundation for adding additional measurements as we learn more
about Git monorepo scaling problems.

The initial goal is to complement the scanning and analysis performed
by the GO-based 'git-sizer' (https://github.com/github/git-sizer) tool.
It is hoped that by creating a builtin command, we may be able to take
advantage of internal Git data structures and code that is not
accessible from GO to gain further insight into potential scaling
problems.

Co-authored-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Jeff Hostetler <git@jeffhostetler.com>
Signed-off-by: Derrick Stolee <stolee@gmail.com>
2026-01-28 07:38:57 +01:00
Johannes Schindelin
7238dd9bc1 ci: work around a problem with HTTP/2 vs libcurl v8.10.0
As reported in https://lore.kernel.org/git/ZuPKvYP9ZZ2mhb4m@pks.im/,
libcurl v8.10.0 had a regression that was picked up by Git's t5559.30
"large fetch-pack requests can be sent using chunked encoding".

This bug was fixed in libcurl v8.10.1.

Sadly, the macos-13 runner image was updated in the brief window between
these two libcurl versions, breaking each and every CI build, as
reported at https://github.com/git-for-windows/git/issues/5159.

This would usually not matter, we would just ignore the failing CI
builds until the macos-13 runner image is rebuilt in a couple of days,
and then the CI builds would succeed again.

However.

As has become the custom, a surprise Git version was released, and now
that Git for Windows wants to follow suit, since Git for Windows has
this custom of trying to never release a version with a failing CI
build, we _must_ work around it.

This patch implements this work-around, basically for the sake of Git
for Windows v2.46.2's CI build.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:56 +01:00
Derrick Stolee
ad2b49eaab revision: create mark_trees_uninteresting_dense()
The sparse tree walk algorithm was created in d5d2e93577e (revision:
implement sparse algorithm, 2019-01-16) and involves using the
mark_trees_uninteresting_sparse() method. This method takes a repository
and an oidset of tree IDs, some of which have the UNINTERESTING flag and
some of which do not.

Create a method that has an equivalent set of preconditions but uses a
"dense" walk (recursively visits all reachable trees, as long as they
have not previously been marked UNINTERESTING). This is an important
difference from mark_tree_uninteresting(), which short-circuits if the
given tree has the UNINTERESTING flag.

A use of this method will be added in a later change, with a condition
set whether the sparse or dense approach should be used.

Signed-off-by: Derrick Stolee <stolee@gmail.com>
2026-01-28 07:38:56 +01:00
Johannes Schindelin
70b9ce9fe1 run-command: be helpful with Git LFS fails on Windows 7
Git LFS is now built with Go 1.21 which no longer supports Windows 7.
However, Git for Windows still wants to support Windows 7.

Ideally, Git LFS would re-introduce Windows 7 support until Git for
Windows drops support for Windows 7, but that's not going to happen:
https://github.com/git-for-windows/git/issues/4996#issuecomment-2176152565

The next best thing we can do is to let the users know what is
happening, and how to get out of their fix, at least.

This is not quite as easy as it would first seem because programs
compiled with Go 1.21 or newer will simply throw an exception and fail
with an Access Violation on Windows 7.

The only way I found to address this is to replicate the logic from Go's
very own `version` command (which can determine the Go version with
which a given executable was built) to detect the situation, and in that
case offer a helpful error message.

This addresses https://github.com/git-for-windows/git/issues/4996.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:56 +01:00
Ariel Lourenco
3e9b12fd0d Fallback to AppData if XDG_CONFIG_HOME is unset
In order to be a better Windows citizenship, Git should
save its configuration files on AppData folder. This can
enables git configuration files be replicated between machines
using the same Microsoft account logon which would reduce the
friction of setting up Git on new systems. Therefore, if
%APPDATA%\Git\config exists, we use it; otherwise
$HOME/.config/git/config is used.

Signed-off-by: Ariel Lourenco <ariellourenco@users.noreply.github.com>
2026-01-28 07:38:56 +01:00
Johannes Schindelin
e4e770cf10 win32: ensure that localtime_r() is declared even in i686 builds
The `__MINGW64__` constant is defined, surprise, surprise, only when
building for a 64-bit CPU architecture.

Therefore using it as a guard to define `_POSIX_C_SOURCE` (so that
`localtime_r()` is declared, among other functions) is not enough, we
also need to check `__MINGW32__`.

Technically, the latter constant is defined even for 64-bit builds. But
let's make things a bit easier to understand by testing for both
constants.

Making it so fixes this compile warning (turned error in GCC v14.1):

  archive-zip.c: In function 'dos_time':
  archive-zip.c:612:9: error: implicit declaration of function 'localtime_r';
  did you mean 'localtime_s'? [-Wimplicit-function-declaration]
    612 |         localtime_r(&time, &tm);
        |         ^~~~~~~~~~~
        |         localtime_s

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:56 +01:00
Johannes Schindelin
025e9a85c9 t5601/t7406(mingw): do run tests with symlink support
A long time ago, we decided to run tests in Git for Windows' SDK with
the default `winsymlinks` mode: copying instead of linking. This is
still the default mode of MSYS2 to this day.

However, this is not how most users run Git for Windows: As the majority
of Git for Windows' users seem to be on Windows 10 and newer, likely
having enabled Developer Mode (which allows creating symbolic links
without administrator privileges), they will run with symlink support
enabled.

This is the reason why it is crucial to get the fixes for CVE-2024-? to
the users, and also why it is crucial to ensure that the test suite
exercises the related test cases. This commit ensures the latter.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:56 +01:00
MinarKotonoha
9da49cabc1 common-main.c: fflush stdout buffer upon exit
By default, the buffer type of Windows' `stdout` is unbuffered (_IONBF),
and there is no need to manually fflush `stdout`.

But some programs, such as the Windows Filtering Platform driver
provided by the security software, may change the buffer type of
`stdout` to full buffering. This nees `fflush(stdout)` to be called
manually, otherwise there will be no output to `stdout`.

Signed-off-by: MinarKotonoha <chengzhuo5@qq.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:56 +01:00
Johannes Schindelin
650a165ef9 win32: use native ANSI sequence processing, if possible
Windows 10 version 1511 (also known as Anniversary Update), according to
https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
introduced native support for ANSI sequence processing. This allows
using colors from the entire 24-bit color range.

All we need to do is test whether the console's "virtual processing
support" can be enabled. If it can, we do not even need to start the
`console_thread` to handle ANSI sequences.

Or, almost all we need to do: When `console_thread()` does its work, it
uses the Unicode-aware `write_console()` function to write to the Win32
Console, which supports Git for Windows' implicit convention that all
text that is written is encoded in UTF-8. The same is not necessarily
true if native ANSI sequence processing is used, as the output is then
subject to the current code page. Let's ensure that the code page is set
to `CP_UTF8` as long as Git writes to it.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:56 +01:00
David Lomas
0a76992d62 mingw: suggest windows.appendAtomically in more cases
When running Git for Windows on a remote APFS filesystem, it would
appear that the `mingw_open_append()`/`write()` combination would fail
almost exactly like on some CIFS-mounted shares as had been reported in
https://github.com/git-for-windows/git/issues/2753, albeit with a
different `errno` value.

Let's handle that `errno` value just the same, by suggesting to set
`windows.appendAtomically=false`.

Signed-off-by: David Lomas <dl3@pale-eds.co.uk>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:56 +01:00
Johannes Schindelin
11ef03e827 Add a GitHub workflow to verify that Git/Scalar work in Nano Server
In Git for Windows v2.39.0, we fixed a regression where `git.exe` would
no longer work in Windows Nano Server (frequently used in Docker
containers).

This GitHub workflow can be used to verify manually that the Git/Scalar
executables work in Nano Server.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:56 +01:00
Johannes Schindelin
9e5b795a9a mingw: do load libcurl dynamically by default
This will help with Git for Windows' maintenance going forward: It
allows Git for Windows to switch its primary libcurl to a variant
without the OpenSSL backend, while still loading an alternate when
setting `http.sslBackend = openssl`.

This is necessary to avoid maintenance headaches with upgrading OpenSSL:
its major version name is encoded in the shared library's file name and
hence major version updates (temporarily) break libraries that are
linked against the OpenSSL library.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:56 +01:00
Johannes Schindelin
dd918bd51d http: when loading libcurl lazily, allow for multiple SSL backends
The previous commits introduced a compile-time option to load libcurl
lazily, but it uses the hard-coded name "libcurl-4.dll" (or equivalent
on platforms other than Windows).

To allow for installing multiple libcurl flavors side by side, where
each supports one specific SSL/TLS backend, let's first look whether
`libcurl-<backend>-4.dll` exists, and only use `libcurl-4.dll` as a fall
back.

That will allow us to ship with a libcurl by default that only supports
the Secure Channel backend for the `https://` protocol. This libcurl
won't suffer from any dependency problem when upgrading OpenSSL to a new
major version (which will change the DLL name, and hence break every
program and library that depends on it).

This is crucial because Git for Windows relies on libcurl to keep
working when building and deploying a new OpenSSL package because that
library is used by `git fetch` and `git clone`.

Note that this feature is by no means specific to Windows. On Ubuntu,
for example, a `git` built using `LAZY_LOAD_LIBCURL` will use
`libcurl.so.4` for `http.sslbackend=openssl` and `libcurl-gnutls.so.4`
for `http.sslbackend=gnutls`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:56 +01:00
Johannes Schindelin
5ef2a8d03f http: support lazy-loading libcurl also on Windows
This implements the Windows-specific support code, because everything is
slightly different on Windows, even loading shared libraries.

Note: I specifically do _not_ use the code from
`compat/win32/lazyload.h` here because that code is optimized for
loading individual functions from various system DLLs, while we
specifically want to load _many_ functions from _one_ DLL here, and
distinctly not a system DLL (we expect libcurl to be located outside
`C:\Windows\system32`, something `INIT_PROC_ADDR` refuses to work with).
Also, the `curl_easy_getinfo()`/`curl_easy_setopt()` functions are
declared as vararg functions, which `lazyload.h` cannot handle. Finally,
we are about to optionally override the exact file name that is to be
loaded, which is a goal contrary to `lazyload.h`'s design.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:55 +01:00
Johannes Schindelin
7af555c5b9 http: optionally load libcurl lazily
This compile-time option allows to ask Git to load libcurl dynamically
at runtime.

Together with a follow-up patch that optionally overrides the file name
depending on the `http.sslBackend` setting, this kicks open the door for
installing multiple libcurl flavors side by side, and load the one
corresponding to the (runtime-)configured SSL/TLS backend.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:38:55 +01:00
Johannes Schindelin
e23ad91110 max_tree_depth: lower it for clang builds in general on Windows
In 436a42215e5 (max_tree_depth: lower it for clangarm64 on Windows,
2025-04-23), I provided a work-around for a nasty issue with clangarm
builds, where the stack is exhausted before the maximal tree depth is
reached, and the resulting error cannot easily be handled by Git
(because it would require Windows-specific handling).

Turns out that this is not at all limited to ARM64. In my tests with
CLANG64 in MSYS2 on the GitHub Actions runners, the test t6700.4 failed
in the exact same way. What's worse: The limit needs to be quite a bit
lower for x86_64 than for aarch64. In aforementioned tests, the breaking
point was 1232: With 1231 it still worked as expected, with 1232 it
would fail with the `STATUS_STACK_OVERFLOW` incorrectly mapped to exit
code 127. For comparison, in my tests on GitHub Actions' Windows/ARM64
runners, the breaking point was 1439 instead.

Therefore the condition needs to be adapted once more, to accommodate
(with some safety margin) both aarch64 and x86_64 in clang-based builds
on Windows, to let that test pass.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:36:18 +01:00
Johannes Schindelin
55d1066492 windows: skip linking git-<command> for built-ins
It is merely a historical wart that, say, `git-commit` exists in the
`libexec/git-core/` directory, a tribute to the original idea to let Git
be essentially a bunch of Unix shell scripts revolving around very few
"plumbing" (AKA low-level) commands.

Git has evolved a lot from there. These days, most of Git's
functionality is contained within the `git` executable, in the form of
"built-in" commands.

To accommodate for scripts that use the "dashed" form of Git commands,
even today, Git provides hard-links that make the `git` executable
available as, say, `git-commit`, just in case that an old script has not
been updated to invoke `git commit`.

Those hard-links do not come cheap: they take about half a minute for
every build of Git on Windows, they are mistaken for taking up huge
amounts of space by some Windows Explorer versions that do not
understand hard-links, and therefore many a "bug" report had to be
addressed.

The "dashed form" has been officially deprecated in Git version 1.5.4,
which was released on February 2nd, 2008, i.e. a very long time ago.
This deprecation was never finalized by skipping these hard-links, but
we can start the process now, in Git for Windows.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:18:37 +01:00
Johannes Schindelin
d1f0a5ba34 mingw: always define ETC_* for MSYS2 environments
Special-casing even more configurations simply does not make sense.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:18:37 +01:00
Johannes Schindelin
71c1841f0e mingw: rely on MSYS2's metadata instead of hard-coding it
MSYS2 defines some helpful environment variables, e.g. `MSYSTEM`. There
is code in Git for Windows to ensure that that `MSYSTEM` variable is
set, hard-coding a default.

However, the existing solution jumps through hoops to reconstruct the
proper default, and is even incomplete doing so, as we found out when we
extended it to support CLANGARM64.

This is absolutely unnecessary because there is already a perfectly
valid `MSYSTEM` value we can use at build time. This is even true when
building the MINGW32 variant on a MINGW64 system because `makepkg-mingw`
will override the `MSYSTEM` value as per the `MINGW_ARCH` array.

The same is equally true for the `/mingw64`, `/mingw32` and
`/clangarm64` prefix: those values are already available via the
`MINGW_PREFIX` environment variable, and we just need to pass that
setting through.

Only when `MINGW_PREFIX` is not set (as is the case in Git for Windows'
minimal SDK, where only `MSYSTEM` is guaranteed to be set correctly), we
use as fall-back the top-level directory whose name is the down-cased
value of the `MSYSTEM` variable.

Incidentally, this also broadens the support to all the configurations
supported by the MSYS2 project, i.e. clang64 & ucrt64, too.

Note: This keeps the same, hard-coded MSYSTEM platform support for CMake
as before, but drops it for Meson (because it is unclear how Meson could
do this in a more flexible manner).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:18:37 +01:00
Johannes Schindelin
75886a3bc8 mingw: only enable the MSYS2-specific stuff when compiling in MSYS2
The tell-tale is the presence of the `MSYSTEM` value while compiling, of
course. In that case, we want to ensure that `MSYSTEM` is set when
running `git.exe`, and also enable the magic MSYS2 tty detection.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:18:37 +01:00
Johannes Schindelin
3471074861 mingw: set the prefix and HOST_CPU as per MSYS2's settings
MSYS2 already defines a couple of helpful environment variables, and we
can use those to infer the installation location as well as the CPU. No
need for hard-coding ;-)

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:18:37 +01:00
Johannes Schindelin
fb3404d94a mingw: avoid over-specifying --pic-executable
In bf2d5d8239e (Don't let ld strip relocations, 2016-01-16) (picked from
https://github.com/git-for-windows/git/pull/612/commits/6a237925bf10),
Git for Windows introduced the `-Wl,-pic-executable` flag, specifying
the exact entry point via `-e`. This required discerning between i686
and x86_64 code because the former required the symbol to be prefixed
with an underscore, the latter did not.

As per https://sourceware.org/bugzilla/show_bug.cgi?id=10865, the
specified symbols are already the default, though.

So let's drop the overly-specific definition.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:18:37 +01:00
Johannes Schindelin
fcae0f80eb mingw: only use -Wl,--large-address-aware for 32-bit builds
That option only matters there, and is in fact only really understood in
those builds; UCRT64 versions of GCC, for example, do not know what to
do with that option.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:18:37 +01:00
Johannes Schindelin
6855ef0b35 mingw: drop the -D_USE_32BIT_TIME_T option
This option was added in fa93bb20d72 (MinGW: Fix stat definitions to
work with MinGW runtime version 4.0, 2013-09-11), i.e. a _long_ time
ago. So long, in fact, that it still targeted MinGW. But we switched to
mingw-w64 in 2015, which seems not to share the problem, and therefore
does not require a fix.

Even worse: This flag is incompatible with UCRT64, which we are about to
support by way of upstreaming `mingw-w64-git` to the MSYS2 project, see
https://github.com/msys2/MINGW-packages/pull/26470 for details.

So let's send that option into its well-deserved retirement.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:18:37 +01:00
Johannes Schindelin
dd3b541d21 mingw: stop hard-coding CC = gcc
This is no longer true in general, not with supporting Clang out of the
box.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:18:37 +01:00
Andrey Zabavnikov
906ddd07a9 status: fix for old-style submodules with commondir
In f9b7573f6b00 (repository: free fields before overwriting them,
2017-09-05), Git was taught to release memory before overwriting it, but
357a03ebe9e0 (repository.c: move env-related setup code back to
environment.c, 2018-03-03) changed the code so that it would not
_always_ be overwritten.

As a consequence, the `commondir` attribute would point to
already-free()d memory.

This seems not to cause problems in core Git, but there are add-on
patches in Git for Windows where the `commondir` attribute is
subsequently used and causing invalid memory accesses e.g. in setups
containing old-style submodules (i.e. the ones with a `.git` directory
within theirs worktrees) that have `commondir` configured.

This fixes https://github.com/git-for-windows/git/pull/4083.

Signed-off-by: Andrey Zabavnikov <zabavnikov@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:18:36 +01:00
Kiel Hurley
4337ef00a1 Fix Windows version resources
Add FileVersion, which is a required field
As not all required fields were present, none were being included
Fixes #4090

Signed-off-by: Kiel Hurley <kielhurley@gmail.com>
2026-01-28 07:18:36 +01:00
Matthias Aßhauer
4f2721c778 MinGW: link as terminal server aware
Whith Windows 2000, Microsoft introduced a flag to the PE header to mark executables as
"terminal server aware". Windows terminal servers provide a redirected Windows directory and
redirected registry hives when launching legacy applications without this flag set. Since we
do not use any INI files in the Windows directory and don't write to the registry, we don't
need  this additional preparation. Telling the OS that we don't need this should provide
slightly improved startup times in terminal server environments.

When building for supported Windows Versions with MSVC the /TSAWARE linker flag is
automatically set, but MinGW requires us to set the --tsaware flag manually.

This partially addresses https://github.com/git-for-windows/git/issues/3935.

Signed-off-by: Matthias Aßhauer <mha1993@live.de>
2026-01-28 07:18:36 +01:00
Johannes Schindelin
6a8a5a9221 mingw: change core.fsyncObjectFiles = 1 by default
From the documentation of said setting:

	This boolean will enable fsync() when writing object files.

	This is a total waste of time and effort on a filesystem that
	orders data writes properly, but can be useful for filesystems
	that do not use journalling (traditional UNIX filesystems) or
	that only journal metadata and not file contents (OS X’s HFS+,
	or Linux ext3 with "data=writeback").

The most common file system on Windows (NTFS) does not guarantee that
order, therefore a sudden loss of power (or any other event causing an
unclean shutdown) would cause corrupt files (i.e. files filled with
NULs). Therefore we need to change the default.

Note that the documentation makes it sound as if this causes really bad
performance. In reality, writing loose objects is something that is done
only rarely, and only a handful of files at a time.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:18:09 +01:00
孙卓识
10f0986c63 Add config option windows.appendAtomically
Atomic append on windows is only supported on local disk files, and it may
cause errors in other situations, e.g. network file system. If that is the
case, this config option should be used to turn atomic append off.

Co-Authored-By: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: 孙卓识 <sunzhuoshi@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:35 +01:00
Christopher Degawa
53be802501 winansi: check result and Buffer before using Name
NtQueryObject under Wine can return a success but fill out no name.
In those situations, Wine will set Buffer to NULL, and set result to
the sizeof(OBJECT_NAME_INFORMATION).

Running a command such as

echo "$(git.exe --version 2>/dev/null)"

will crash due to a NULL pointer dereference when the code attempts to
null terminate the buffer, although, weirdly, removing the subshell or
redirecting stdout to a file will not trigger the crash.

Code has been added to also check Buffer and Length to ensure the check
is as robust as possible due to the current behavior being fragile at
best, and could potentially change in the future

This code is based on the behavior of NtQueryObject under wine and
reactos.

Signed-off-by: Christopher Degawa <ccom@randomderp.com>
2026-01-28 07:16:35 +01:00
Rafael Kitover
cb452cf758 mingw: $env:TERM="xterm-256color" for newer OSes
For Windows builds >= 15063 set $env:TERM to "xterm-256color" instead of
"cygwin" because they have a more capable console system that supports
this. Also set $env:COLORTERM="truecolor" if unset.

$env:TERM is initialized so that ANSI colors in color.c work, see
29a3963484 (Win32: patch Windows environment on startup, 2012-01-15).

See git-for-windows/git#3629 regarding problems caused by always setting
$env:TERM="cygwin".

This is the same heuristic used by the Cygwin runtime.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:35 +01:00
Derrick Stolee
d8f746f542 compat/mingw.c: do not warn when failing to get owner
In the case of Git for Windows (say, in a Git Bash window) running in a
Windows Subsystem for Linux (WSL) directory, the GetNamedSecurityInfoW()
call in is_path_owned_By_current_side() returns an error code other than
ERROR_SUCCESS. This is consistent behavior across this boundary.

In these cases, the owner would always be different because the WSL
owner is a different entity than the Windows user.

The change here is to suppress the error message that looks like this:

  error: failed to get owner for '//wsl.localhost/...' (1)

Before this change, this warning happens for every Git command,
regardless of whether the directory is marked with safe.directory.

Signed-off-by: Derrick Stolee <derrickstolee@github.com>
2026-01-28 07:16:35 +01:00
Philip Oakley
9ea106018c hash-object: add a >4GB/LLP64 test case using filtered input
To verify that the `clean` side of the `clean`/`smudge` filter code is
correct with regards to LLP64 (read: to ensure that `size_t` is used
instead of `unsigned long`), here is a test case using a trivial filter,
specifically _not_ writing anything to the object store to limit the
scope of the test case.

As in previous commits, the `big` file from previous test cases is
reused if available, to save setup time, otherwise re-generated.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:35 +01:00
Derrick Stolee
dbcd712371 setup: properly use "%(prefix)/" when in WSL
Signed-off-by: Derrick Stolee <derrickstolee@github.com>
2026-01-28 07:16:35 +01:00
Philip Oakley
770dec44be hash-object: add another >4GB/LLP64 test case
To complement the `--stdin` and `--literally` test cases that verify
that we can hash files larger than 4GB on 64-bit platforms using the
LLP64 data model, here is a test case that exercises `hash-object`
_without_ any options.

Just as before, we use the `big` file from the previous test case if it
exists to save on setup time, otherwise generate it.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:35 +01:00
Philip Oakley
28101c6ae0 hash-object --stdin: verify that it works with >4GB/LLP64
Just like the `hash-object --literally` code path, the `--stdin` code
path also needs to use `size_t` instead of `unsigned long` to represent
memory sizes, otherwise it would cause problems on platforms using the
LLP64 data model (such as Windows).

To limit the scope of the test case, the object is explicitly not
written to the object store, nor are any filters applied.

The `big` file from the previous test case is reused to save setup time;
To avoid relying on that side effect, it is generated if it does not
exist (e.g. when running via `sh t1007-*.sh --long --run=1,41`).

Signed-off-by: Philip Oakley <philipoakley@iee.email>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:35 +01:00
Philip Oakley
23246b4397 CMake: show Win32 and Generator_platform build-option values
Ensure key CMake option values are part of the CMake output to
facilitate user support when tool updates impact the wider CMake
actions, particularly ongoing 'improvements' in Visual Studio.

These CMake displays perform the same function as the build-options.txt
provided in the main Git for Windows. CMake is already chatty.
The setting of CMAKE_EXPORT_COMPILE_COMMANDS is also reported.

Include the environment's CMAKE_EXPORT_COMPILE_COMMANDS value which
may have been propogated to CMake's internal value.

Testing the CMAKE_EXPORT_COMPILE_COMMANDS processing can be difficult
in the Visual Studio environment, as it may be cached in many places.
The 'environment' may include the OS, the user shell, CMake's
own environment, along with the Visual Studio presets and caches.

See previous commit for arefacts that need removing for a clean test.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
2026-01-28 07:16:34 +01:00
Victoria Dye
757a2c9bd5 ci: run contrib/subtree tests in CI builds
Because `git subtree` (unlike most other `contrib` modules) is included as
part of the standard release of Git for Windows, its stability should be
verified as consistently as it is for the rest of git. By including the
`git subtree` tests in the CI workflow, these tests are as much of a gate to
merging and indicator of stability as the standard test suite.

Signed-off-by: Victoria Dye <vdye@github.com>
2026-01-28 07:16:34 +01:00
Pascal Muller
6d4c9d6bcc http: optionally send SSL client certificate
This adds support for a new http.sslAutoClientCert config value.

In cURL 7.77 or later the schannel backend does not automatically send
client certificates from the Windows Certificate Store anymore.

This config value is only used if http.sslBackend is set to "schannel",
and can be used to opt in to the old behavior and force cURL to send
client certificates.

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

Signed-off-by: Pascal Muller <pascalmuller@gmail.com>
2026-01-28 07:16:34 +01:00
Johannes Schindelin
92b17b15d0 compat/vcbuild: document preferred way to build in Visual Studio
We used to have that `make vcxproj` hack, but a hack it is. In the
meantime, we have a much cleaner solution: using CMake, either
explicitly, or even more conveniently via Visual Studio's built-in CMake
support (simply open Git's top-level directory via File>Open>Folder...).

Let's let the `README` reflect this.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:34 +01:00
Johannes Schindelin
f154867f25 mingw: allow for longer paths in parse_interpreter()
As reported in https://github.com/newren/git-filter-repo/pull/225, it
looks like 99 bytes is not really sufficient to represent e.g. the full
path to Python when installed via Windows Store (and this path is used
in the hasb bang line when installing scripts via `pip`).

Let's increase it to what is probably the maximum sensible path size:
MAX_PATH. This makes `parse_interpreter()` in line with what
`lookup_prog()` handles.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Vilius Šumskas <vilius@sumskas.eu>
2026-01-28 07:16:34 +01:00
Dennis Ameling
702dc2683b cmake(): allow setting HOST_CPU for cross-compilation
Git's regular Makefile mentions that HOST_CPU should be defined when cross-compiling Git: 37796bca76/Makefile (L438-L439)

This is then used to set the GIT_HOST_CPU variable when compiling Git: 37796bca76/Makefile (L1337-L1341)

Then, when the user runs `git version --build-options`, it returns that value: 37796bca76/help.c (L658)

This commit adds the same functionality to the CMake configuration. Users can now set -DHOST_CPU= to set the target architecture.

Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
2026-01-28 07:16:34 +01:00
Dennis Ameling
18aa03feff Add schannel to curl installation
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
2026-01-28 07:16:34 +01:00
Philip Oakley
d5fab9ba0c hash algorithms: use size_t for section lengths
Continue walking the code path for the >4GB `hash-object --literally`
test to the hash algorithm step for LLP64 systems.

This patch lets the SHA1DC code use `size_t`, making it compatible with
LLP64 data models (as used e.g. by Windows).

The interested reader of this patch will note that we adjust the
signature of the `git_SHA1DCUpdate()` function without updating _any_
call site. This certainly puzzled at least one reviewer already, so here
is an explanation:

This function is never called directly, but always via the macro
`platform_SHA1_Update`, which is usually called via the macro
`git_SHA1_Update`. However, we never call `git_SHA1_Update()` directly
in `struct git_hash_algo`. Instead, we call `git_hash_sha1_update()`,
which is defined thusly:

    static void git_hash_sha1_update(git_hash_ctx *ctx,
                                     const void *data, size_t len)
    {
        git_SHA1_Update(&ctx->sha1, data, len);
    }

i.e. it contains an implicit downcast from `size_t` to `unsigned long`
(before this here patch). With this patch, there is no downcast anymore.

With this patch, finally, the t1007-hash-object.sh "files over 4GB hash
literally" test case is fixed.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:34 +01:00
Philip Oakley
24849e3602 CMakeLists: add default "x64-windows" arch for Visual Studio
In Git-for-Windows, work on using ARM64 has progressed. The
commit 2d94b77b27 (cmake: allow building for Windows/ARM64, 2020-12-04)
failed to notice that /compat/vcbuild/vcpkg_install.bat will default to
using the "x64-windows" architecture for the vcpkg installation if not set,
but CMake is not told of this default. Commit 635b6d99b3 (vcbuild: install
ARM64 dependencies when building ARM64 binaries, 2020-01-31) later updated
vcpkg_install.bat to accept an arch (%1) parameter, but retained the default.

This default is neccessary for the use case where the project directory is
opened directly in Visual Studio, which will find and build a CMakeLists.txt
file without any parameters, thus expecting use of the default setting.

Also Visual studio will generate internal .sln solution and .vcxproj project
files needed for some extension tools. Inform users of the additional
.sln/.vcxproj generation.

** How to test:
 rm -rf '.vs' # remove old visual studio settings
 rm -rf 'compat/vcbuild/vcpkg' # remove any vcpkg downloads
 rm -rf 'contrib/buildsystems/out' # remove builds & CMake artifacts
 with a fresh Visual Studio Community Edition, File>>Open>>(git *folder*)
   to load the project (which will take some time!).
 check for successful compilation.
The implicit .sln (etc.) are in the hidden .vs directory created by
Visual Studio.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
2026-01-28 07:16:34 +01:00
Victoria Dye
6057555be5 subtree: update contrib/subtree test target
The intention of this change is to align with how the top-level git
`Makefile` defines its own test target (which also internally calls
`$(MAKE) -C t/ all`). This change also ensures the consistency of
`make -C contrib/subtree test` with other testing in CI executions
(which rely on `$DEFAULT_TEST_TARGET` being defined as `prove`).

Signed-off-by: Victoria Dye <vdye@github.com>
2026-01-28 07:16:34 +01:00
Dennis Ameling
8bea01b12e ci(vs-build) also build Windows/ARM64 artifacts
There are no Windows/ARM64 agents in GitHub Actions yet, therefore we
just skip adjusting the `vs-test` job for now.

Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:34 +01:00
Philip Oakley
da87446dce object-file.c: use size_t for header lengths
Continue walking the code path for the >4GB `hash-object --literally`
test. The `hash_object_file_literally()` function internally uses both
`hash_object_file()` and `write_object_file_prepare()`. Both function
signatures use `unsigned long` rather than `size_t` for the mem buffer
sizes. Use `size_t` instead, for LLP64 compatibility.

While at it, convert those function's object's header buffer length to
`size_t` for consistency. The value is already upcast to `uintmax_t` for
print format compatibility.

Note: The hash-object test still does not pass. A subsequent commit
continues to walk the call tree's lower level hash functions to identify
further fixes.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:34 +01:00
Philip Oakley
ee8cdf0cd7 .gitignore: add Visual Studio CMakeSetting.json file
The CMakeSettings.json file is tool generated. Developers may track it
should they provide additional settings.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
2026-01-28 07:16:34 +01:00
Dennis Ameling
7262616276 cmake: allow building for Windows/ARM64
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:34 +01:00
Philip Oakley
1c0fe1a018 hash-object: demonstrate a >4GB/LLP64 problem
On LLP64 systems, such as Windows, the size of `long`, `int`, etc. is
only 32 bits (for backward compatibility). Git's use of `unsigned long`
for file memory sizes in many places, rather than size_t, limits the
handling of large files on LLP64 systems (commonly given as `>4GB`).

Provide a minimum test for handling a >4GB file. The `hash-object`
command, with the  `--literally` and without `-w` option avoids
writing the object, either loose or packed. This avoids the code paths
hitting the `bigFileThreshold` config test code, the zlib code, and the
pack code.

Subsequent patches will walk the test's call chain, converting types to
`size_t` (which is larger in LLP64 data models) where appropriate.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:34 +01:00
Philip Oakley
88a65bf26e CMake: default Visual Studio generator has changed
Correct some wording and inform users regarding the Visual Studio
changes (from V16.6) to the default generator.

Subsequent commits ensure that Git for Windows can be directly
opened in modern Visual Studio without needing special configuration
of the CMakeLists settings.

It appeares that internally Visual Studio creates it's own version of the
.sln file (etc.) for extension tools that expect them.

The large number of references below document the shifting of Visual Studio
default and CMake setting options.

refs: https://docs.microsoft.com/en-us/search/?scope=C%2B%2B&view=msvc-150&terms=Ninja

1. https://docs.microsoft.com/en-us/cpp/linux/cmake-linux-configure?view=msvc-160
(note the linux bit)
 "In Visual Studio 2019 version 16.6 or later ***, Ninja is the default
generator for configurations targeting a remote system or WSL. For more
information, see this post on the C++ Team Blog
[https://devblogs.microsoft.com/cppblog/linux-development-with-visual-studio-first-class-support-for-gdbserver-improved-build-times-with-ninja-and-updates-to-the-connection-manager/].

For more information about these settings, see CMakeSettings.json reference
[https://docs.microsoft.com/en-us/cpp/build/cmakesettings-reference?view=msvc-160]."

2. https://docs.microsoft.com/en-us/cpp/build/cmake-presets-vs?view=msvc-160
"CMake supports two files that allow users to specify common configure,
build, and test options and share them with others: CMakePresets.json
and CMakeUserPresets.json."

" Both files are supported in Visual Studio 2019 version 16.10 or later.
***"
3. https://devblogs.microsoft.com/cppblog/linux-development-with-visual-studio-first-class-support-for-gdbserver-improved-build-times-with-ninja-and-updates-to-the-connection-manager/
" Ninja has been the default generator (underlying build system) for
CMake configurations targeting Windows for some time***, but in Visual
Studio 2019 version 16.6 Preview 3*** we added support for Ninja on Linux."

4. https://docs.microsoft.com/en-us/cpp/build/cmakesettings-reference?view=msvc-160
" `generator`: specifies CMake generator to use for this configuration.
May be one of:

    Visual Studio 2019 only:
        Visual Studio 16 2019
        Visual Studio 16 2019 Win64
        Visual Studio 16 2019 ARM

    Visual Studio 2017 and later:
        Visual Studio 15 2017
        Visual Studio 15 2017 Win64
        Visual Studio 15 2017 ARM
        Visual Studio 14 2015
        Visual Studio 14 2015 Win64
        Visual Studio 14 2015 ARM
        Unix Makefiles
        Ninja

Because Ninja is designed for fast build speeds instead of flexibility
and function, it is set as the default. However, some CMake projects may
be unable to correctly build using Ninja. If this occurs, you can
instruct CMake to generate Visual Studio projects instead.

To specify a Visual Studio generator in Visual Studio 2017, open the
settings editor from the main menu by choosing CMake | Change CMake
Settings. Delete "Ninja" and type "V". This activates IntelliSense,
which enables you to choose the generator you want."

"To specify a Visual Studio generator in Visual Studio 2019, right-click
on the CMakeLists.txt file in Solution Explorer and choose CMake
Settings for project > Show Advanced Settings > CMake Generator.

When the active configuration specifies a Visual Studio generator, by
default MSBuild.exe is invoked with` -m -v:minimal` arguments."

5. https://docs.microsoft.com/en-us/cpp/build/cmake-presets-vs?view=msvc-160#enable-cmakepresetsjson-integration-in-visual-studio-2019
"Enable CMakePresets.json integration in Visual Studio 2019

CMakePresets.json integration isn't enabled by default in Visual Studio
2019. You can enable it for all CMake projects in Tools > Options >
CMake > General: (tick a box)" ... see more.

6. https://docs.microsoft.com/en-us/cpp/build/cmakesettings-reference?view=msvc-140
(whichever v140 is..)
"CMake projects are supported in Visual Studio 2017 and later."

7. https://docs.microsoft.com/en-us/cpp/overview/what-s-new-for-cpp-2017?view=msvc-150
"Support added for the CMake Ninja generator."

8. https://docs.microsoft.com/en-us/cpp/overview/what-s-new-for-cpp-2017?view=msvc-150#cmake-support-via-open-folder
"CMake support via Open Folder
Visual Studio 2017 introduces support for using CMake projects without
converting to MSBuild project files (.vcxproj). For more information,
see CMake projects in Visual
Studio[https://docs.microsoft.com/en-us/cpp/build/cmake-projects-in-visual-studio?view=msvc-150].
Opening CMake projects with Open Folder automatically configures the
environment for C++ editing, building, and debugging." ... +more!

9. https://docs.microsoft.com/en-us/cpp/build/cmake-presets-vs?view=msvc-160#supported-cmake-and-cmakepresetsjson-versions
"Visual Studio reads and evaluates CMakePresets.json and
CMakeUserPresets.json itself and doesn't invoke CMake directly with the
--preset option. So, CMake version 3.20 or later isn't strictly required
when you're building with CMakePresets.json inside Visual Studio. We
recommend using CMake version 3.14 or later."

10. https://docs.microsoft.com/en-us/cpp/build/cmake-presets-vs?view=msvc-160#enable-cmakepresetsjson-integration-in-visual-studio-2019
"If you don't want to enable CMakePresets.json integration for all CMake
projects, you can enable CMakePresets.json integration for a single
CMake project by adding a CMakePresets.json file to the root of the open
folder. You must close and reopen the folder in Visual Studio to
activate the integration.

11. https://docs.microsoft.com/en-us/cpp/build/cmake-presets-vs?view=msvc-160#default-configure-presets
***(doesn't actually say which version..)
"Default Configure Presets
If no CMakePresets.json or CMakeUserPresets.json file exists, or if
CMakePresets.json or CMakeUserPresets.json is invalid, Visual Studio
will fall back*** on the following default Configure Presets:

Windows example
JSON
{
  "name": "windows-default",
  "displayName": "Windows x64 Debug",
  "description": "Sets Ninja generator, compilers, x64 architecture,
build and install directory, debug build type",
  "generator": "Ninja",
  "binaryDir": "${sourceDir}/out/build/${presetName}",
  "architecture": {
    "value": "x64",
    "strategy": "external"
  },
  "cacheVariables": {
    "CMAKE_BUILD_TYPE": "Debug",
    "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}"
  },
  "vendor": {
    "microsoft.com/VisualStudioSettings/CMake/1.0": {
      "hostOS": [ "Windows" ]
    }
  }
},
"

Signed-off-by: Philip Oakley <philipoakley@iee.email>
2026-01-28 07:16:34 +01:00
Ian Bearman
c3c19beffc vcbuild: add an option to install individual 'features'
In this context, a "feature" is a dependency combined with its own
dependencies.

Signed-off-by: Ian Bearman <ianb@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:34 +01:00
Johannes Schindelin
db0e354abb t5505/t5516: fix white-space around redirectors
The convention in Git project's shell scripts is to have white-space
_before_, but not _after_ the `>` (or `<`).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:33 +01:00
Philip Oakley
ea8a6b7eda vcpkg_install: add comment regarding slow network connections
The vcpkg downloads may not succeed. Warn careful readers of the time out.

A simple retry will usually resolve the issue.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:33 +01:00
Johannes Schindelin
63e838f859 git-gui: accommodate for intent-to-add files
As of Git v2.28.0, the diff for files staged via `git add -N` marks them
as new files. Git GUI was ill-prepared for that, and this patch teaches
Git GUI about them.

Please note that this will not even fix things with v2.28.0, as the
`rp/apply-cached-with-i-t-a` patches are required on Git's side, too.

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

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Pratyush Yadav <me@yadavpratyush.com>
2026-01-28 07:16:33 +01:00
Jens Glathe
26563b25de t0014: fix indentation
For some reason, this test case was indented with 4 spaces instead of 1
horizontal tab. The other test cases in the same test script are fine.

Signed-off-by: Jens Glathe <jens.glathe@oldschoolsolutions.biz>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:33 +01:00
Luke Bonanomi
d00df93e0a commit: accept "scissors" with CR/LF line endings
This change enhances `git commit --cleanup=scissors` by detecting
scissors lines ending in either LF (UNIX-style) or CR/LF (DOS-style).

Regression tests are included to specifically test for trailing
comments after a CR/LF-terminated scissors line.

Signed-off-by: Luke Bonanomi <lbonanomi@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:33 +01:00
Johannes Schindelin
0924bbd7b1 t3701: verify that we can add *lots* of files interactively
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:33 +01:00
Johannes Schindelin
69135d81fd http: use new "best effort" strategy for Secure Channel revoke checking
The native Windows HTTPS backend is based on Secure Channel which lets
the caller decide how to handle revocation checking problems caused by
missing information in the certificate or offline CRL distribution
points.

Unfortunately, cURL chose to handle these problems differently than
OpenSSL by default: while OpenSSL happily ignores those problems
(essentially saying "¯\_(ツ)_/¯"), the Secure Channel backend will error
out instead.

As a remedy, the "no revoke" mode was introduced, which turns off
revocation checking altogether. This is a bit heavy-handed. We support
this via the `http.schannelCheckRevoke` setting.

In https://github.com/curl/curl/pull/4981, we contributed an opt-in
"best effort" strategy that emulates what OpenSSL seems to do.

In Git for Windows, we actually want this to be the default. This patch
makes it so, introducing it as a new value for the
`http.schannelCheckRevoke" setting, which now becmes a tristate: it
accepts the values "false", "true" or "best-effort" (defaulting to the
last one).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:33 +01:00
Johannes Schindelin
065aaec646 mingw: implement a platform-specific strbuf_realpath()
There is a Win32 API function to resolve symbolic links, and we can use
that instead of resolving them manually. Even better, this function also
resolves NTFS junction points (which are somewhat similar to bind
mounts).

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

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:33 +01:00
Ian Bearman
e94d8273ab vcbuild: install ARM64 dependencies when building ARM64 binaries
Co-authored-by: Dennis Ameling <dennis@dennisameling.com>
Signed-off-by: Ian Bearman <ianb@microsoft.com>
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:33 +01:00
Johannes Schindelin
14dc73634a t5505/t5516: allow running without .git/branches/ in the templates
When we commit the template directory as part of `make vcxproj`, the
`branches/` directory is not actually commited, as it is empty.

Two tests were not prepared for that situation.

This developer tried to get rid of the support for `.git/branches/` a
long time ago, but that effort did not bear fruit, so the best we can do
is work around in these here tests.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:33 +01:00
Philip Oakley
71dccee643 vcpkg_install: detect lack of Git
The vcpkg_install batch file depends on the availability of a
working Git on the CMD path. This may not be present if the user
has selected the 'bash only' option during Git-for-Windows install.

Detect and tell the user about their lack of a working Git in the CMD
window.

Fixes #2348.
A separate PR https://github.com/git-for-windows/build-extra/pull/258
now highlights the recommended path setting during install.

Signed-off-by: Philip Oakley <philipoakley@iee.email>
2026-01-28 07:16:33 +01:00
Johannes Schindelin
ddf039e5ff strbuf_realpath(): use platform-dependent API if available
Some platforms (e.g. Windows) provide API functions to resolve paths
much quicker. Let's offer a way to short-cut `strbuf_realpath()` on
those platforms.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:33 +01:00
Jeff Hostetler
963231342a clink.pl: fix MSVC compile script to handle libcurl-d.lib
Update clink.pl to link with either libcurl.lib or libcurl-d.lib
depending on whether DEBUG=1 is set.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:32 +01:00
Bjoern Mueller
2c41f19e89 mingw: fix fatal error working on mapped network drives on Windows
In 1e64d18 (mingw: do resolve symlinks in `getcwd()`) a problem was
introduced that causes git for Windows to stop working with certain
mapped network drives (in particular, drives that are mapped to
locations with long path names). Error message was "fatal: Unable to
read current working directory: No such file or directory". Present
change fixes this issue as discussed in
https://github.com/git-for-windows/git/issues/2480

Signed-off-by: Bjoern Mueller <bjoernm@gmx.de>
2026-01-28 07:16:32 +01:00
Thomas Braun
6f6e8f4245 transport: optionally disable side-band-64k
Since commit 0c499ea60fda (send-pack: demultiplex a sideband stream with
status data, 2010-02-05) the send-pack builtin uses the side-band-64k
capability if advertised by the server.

Unfortunately this breaks pushing over the dump git protocol if used
over a network connection.

The detailed reasons for this breakage are (by courtesy of Jeff Preshing,
quoted from https://groups.google.com/d/msg/msysgit/at8D7J-h7mw/eaLujILGUWoJ):

	MinGW wraps Windows sockets in CRT file descriptors in order to
	mimic the functionality of POSIX sockets. This causes msvcrt.dll
	to treat sockets as Installable File System (IFS) handles,
	calling ReadFile, WriteFile, DuplicateHandle and CloseHandle on
	them. This approach works well in simple cases on recent
	versions of Windows, but does not support all usage patterns. In
	particular, using this approach, any attempt to read & write
	concurrently on the same socket (from one or more processes)
	will deadlock in a scenario where the read waits for a response
	from the server which is only invoked after the write. This is
	what send_pack currently attempts to do in the use_sideband
	codepath.

The new config option `sendpack.sideband` allows to override the
side-band-64k capability of the server, and thus makes the dumb git
protocol work.

Other transportation methods like ssh and http/https still benefit from
the sideband channel, therefore the default value of `sendpack.sideband`
is still true.

Signed-off-by: Thomas Braun <thomas.braun@byte-physics.de>
Signed-off-by: Oliver Schneider <oliver@assarbad.net>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:32 +01:00
Johannes Schindelin
9c43955fed mingw: use mimalloc
Thorough benchmarking with repacking a subset of linux.git (the commit
history reachable from 93a6fefe2f ([PATCH] fix the SYSCTL=n compilation,
2007-02-28), to be precise) suggest that this allocator is on par, in
multi-threaded situations maybe even better than nedmalloc:

`git repack -adfq` with mimalloc, 8 threads:

31.166991900 27.576763800 28.712311000 27.373859000 27.163141900

`git repack -adfq` with nedmalloc, 8 threads:

31.915032900 27.149883100 28.244933700 27.240188800 28.580849500

In a different test using GitHub Actions build agents (probably
single-threaded, a core-strength of nedmalloc)):

`git repack -q -d -l -A --unpack-unreachable=2.weeks.ago` with mimalloc:

943.426 978.500 939.709 959.811 954.605

`git repack -q -d -l -A --unpack-unreachable=2.weeks.ago` with nedmalloc:

995.383 952.179 943.253 963.043 980.468

While these measurements were not executed with complete scientific
rigor, as no hardware was set aside specifically for these benchmarks,
it shows that mimalloc and nedmalloc perform almost the same, nedmalloc
with a bit higher variance and also slightly higher average (further
testing suggests that nedmalloc performs worse in multi-threaded
situations than in single-threaded ones).

In short: mimalloc seems to be slightly better suited for our purposes
than nedmalloc.

Seeing that mimalloc is developed actively, while nedmalloc ceased to
see any updates in eight years, let's use mimalloc on Windows instead.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:32 +01:00
Johannes Schindelin
5d6daeebfb mingw: include the Python parts in the build
While Git for Windows does not _ship_ Python (in order to save on
bandwidth), MSYS2 provides very fine Python interpreters that users can
easily take advantage of, by using Git for Windows within its SDK.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:32 +01:00
Johannes Schindelin
ee43a66a84 clean: remove mount points when possible
Windows' equivalent to "bind mounts", NTFS junction points, can be
unlinked without affecting the mount target. This is clearly what users
expect to happen when they call `git clean -dfx` in a worktree that
contains NTFS junction points: the junction should be removed, and the
target directory of said junction should be left alone (unless it is
inside the worktree).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:32 +01:00
Johannes Schindelin
299cf47051 mingw: demonstrate a git add issue with NTFS junctions
NTFS junctions are somewhat similar in spirit to Unix bind mounts: they
point to a different directory and are resolved by the filesystem
driver. As such, they appear to `lstat()` as if they are directories,
not as if they are symbolic links.

_Any_ user can create junctions, while symbolic links can only be
created by non-administrators in Developer Mode on Windows 10. Hence
NTFS junctions are much more common "in the wild" than NTFS symbolic
links.

It was reported in https://github.com/git-for-windows/git/issues/2481
that adding files via an absolute path that traverses an NTFS junction:
since 1e64d18 (mingw: do resolve symlinks in `getcwd()`), we resolve not
only symbolic links but also NTFS junctions when determining the
absolute path of the current directory. The same is not true for `git
add <file>`, where symbolic links are resolved in `<file>`, but not NTFS
junctions.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:32 +01:00
Johannes Schindelin
7e3722cc82 mimalloc: offer a build-time option to enable it
By defining `USE_MIMALLOC`, Git can now be compiled with that
nicely-fast and small allocator.

Note that we have to disable a couple `DEVELOPER` options to build
mimalloc's source code, as it makes heavy use of declarations after
statements, among other things that disagree with Git's conventions.

We even have to silence some GCC warnings in non-DEVELOPER mode. For
example, the `-Wno-array-bounds` flag is needed because in `-O2` builds,
trying to call `NtCurrentTeb()` (which `_mi_thread_id()` does on
Windows) causes the bogus warning about a system header, likely related
to https://sourceforge.net/p/mingw-w64/mailman/message/37674519/ and to
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578:

C:/git-sdk-64-minimal/mingw64/include/psdk_inc/intrin-impl.h:838:1:
        error: array subscript 0 is outside array bounds of 'long long unsigned int[0]' [-Werror=array-bounds]
  838 | __buildreadseg(__readgsqword, unsigned __int64, "gs", "q")
      | ^~~~~~~~~~~~~~

Also: The `mimalloc` library uses C11-style atomics, therefore we must
require that standard when compiling with GCC if we want to use
`mimalloc` (instead of requiring "only" C99). This is what we do in the
CMake definition already, therefore this commit does not need to touch
`contrib/buildsystems/`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:32 +01:00
Johannes Schindelin
2f285aea9f mimalloc: adjust for building inside Git
We want to compile mimalloc's source code as part of Git, rather than
requiring the code to be built as an external library: mimalloc uses a
CMake-based build, which is not necessarily easy to integrate into the
flavors of Git for Windows (which will be the main benefitting port).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Matthias Aßhauer <mha1993@live.de>
2026-01-28 07:16:32 +01:00
Johannes Schindelin
e7cdf876a9 Import the source code of mimalloc v2.2.7
Update to newer mimalloc versions like this:

  update_mimalloc ()
  {
      test $# = 1 || {
          echo "Need a mimalloc version" 1>&2;
          return 1
      };
      for oneline in 'mimalloc: adjust for building inside Git' 'Import the source code of mimalloc';
      do
          git revert -n HEAD^{/^"$oneline"} && git checkout HEAD -- Makefile && git commit -sm "Temporarily revert \"$oneline\"" -m 'In preparation for upgrading to a newer mimalloc version.' || return 1;
      done;
      for file in $(git show --format='%n' --name-only --diff-filter=A HEAD^{/^"Import the source code of mimalloc "}) compat/mimalloc/arena-abandon.c compat/mimalloc/free.c compat/mimalloc/libc.c compat/mimalloc/prim/prim.c compat/mimalloc/mimalloc-stats.h;
      do
          file2=${file#compat/mimalloc/};
          case "$file2" in
              segment-cache.c)
                  : no longer needed;
                  continue
              ;;
              bitmap.h | *.c)
                  file2=src/$file2
              ;;
              *.h)
                  file2=include/$file2
              ;;
          esac;
          mkdir -p "${file%/*}" && git -C /usr/src/mimalloc/ show "$1":$file2 > "$file" && git add "$file" || {
              echo "Failed: $file2 -> $file" 1>&2;
              return 1
          };
      done;
      conv_sed='sed -n "/^ *eval/d;/      /p"' && git commit -sm "Import the source code of mimalloc $1" -m "Update to newer mimalloc versions like this:" -m "$(set | sed -n '/^update_mimalloc *() *$/,/^}/{s/^./  &/;p}')" -m '  update_mimalloc $MIMALLOC_VERSION' -m 'For convenience, you can set `MIMALLOC_VERSION` and then run:' -m '  eval "$(git show -s <this-commit> | '"$conv_sed"')"' || return 1;
      git cherry-pick HEAD^{/^'mimalloc: adjust for building inside Git'} || return 1
  }

  update_mimalloc $MIMALLOC_VERSION

For convenience, you can set `MIMALLOC_VERSION` and then run:

  eval "$(git show -s <this-commit> | sed -n "/^ *eval/d;/      /p")"

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:32 +01:00
Johannes Schindelin
0f84586a47 git-compat-util: avoid redeclaring _DEFAULT_SOURCE
We are about to vendor in `mimalloc`'s source code which we will want to
include `compat/posix.h` after defining that constant.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:32 +01:00
Johannes Schindelin
2f738e48d2 win32/pthread: avoid name clashes with winpthread
When asking the mingw-w64 variant of GCC to compile C11 code, it seems
to link implicitly to libwinpthread, which does implement a pthread
emulation (that is more complete than Git's).

In preparation for vendoring in mimalloc (which requires C11 support),
let's keep preferring Git's own pthread emulation.

To avoid linker errors where it thinks that the `pthread_self` and the
`pthread_create` symbols are defined twice, let's give our version a
`win32_` prefix, just like we already do for `pthread_join()`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:32 +01:00
Johannes Schindelin
39792672e5 Merge branch 'fixes-from-the-git-mailing-list'
These fixes have been sent to the Git mailing list but have not been
picked up by the Git project yet.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:31 +01:00
Johannes Schindelin
f5f40f3b12 mingw: prevent regressions with "drive-less" absolute paths
On Windows, there are several categories of absolute paths. One such
category starts with a backslash and is implicitly relative to the drive
associated with the current working directory. Example:

	c:
	git clone https://github.com/git-for-windows/git \G4W

should clone into C:\G4W.

Back in 2017, Juan Carlos Arevalo Baeza reported a bug in Git's handling
of those absolute paths was identified, and fixed. Let's make sure that
it stays fixed.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:31 +01:00
Johannes Schindelin
f0d37931c6 Always auto-gc after calling a fast-import transport
After importing anything with fast-import, we should always let the
garbage collector do its job, since the objects are written to disk
inefficiently.

This brings down an initial import of http://selenic.com/hg from about
230 megabytes to about 14.

In the future, we may want to make this configurable on a per-remote
basis, or maybe teach fast-import about it in the first place.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:31 +01:00
Johannes Schindelin
579319b620 clean: do not traverse mount points
It seems to be not exactly rare on Windows to install NTFS junction
points (the equivalent of "bind mounts" on Linux/Unix) in worktrees,
e.g. to map some development tools into a subdirectory.

In such a scenario, it is pretty horrible if `git clean -dfx` traverses
into the mapped directory and starts to "clean up".

Let's just not do that. Let's make sure before we traverse into a
directory that it is not a mount point (or junction).

This addresses https://github.com/git-for-windows/git/issues/607

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:31 +01:00
Johannes Schindelin
133f5d9087 Merge branch 'disallow-control-characters-in-sideband-channel'
This addresses:

- CVE-2024-52005:

	Insufficient neutralization of ANSI escape sequences in sideband
	payload can be used to mislead Git users into believing that
	certain remote-generated messages actually originate from Git.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
2026-01-28 07:16:31 +01:00
Jeff King
154c3b8f2c grep: prevent ^$ false match at end of file
In some implementations, `regexec_buf()` assumes that it is fed lines;
Without `REG_NOTEOL` it thinks the end of the buffer is the end of a
line. Which makes sense, but trips up this case because we are not
feeding lines, but rather a whole buffer. So the final newline is not
the start of an empty line, but the true end of the buffer.

This causes an interesting bug:

  $ echo content >file.txt
  $ git grep --no-index -n '^$' file.txt
  file.txt:2:

This bug is fixed by making the end of the buffer consistently the end
of the final line.

The patch was applied from
https://lore.kernel.org/git/20250113062601.GD767856@coredump.intra.peff.net/

Reported-by: Olly Betts <olly@survex.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:31 +01:00
Sverre Rabbelier
baaf71713b remote-helper: check helper status after import/export
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
2026-01-28 07:16:31 +01:00
Johannes Schindelin
2cd5611bd9 unix-socket: avoid leak when initialization fails
When a Unix socket is initialized, the current directory's path is
stored so that the cleanup code can `chdir()` back to where it was
before exit.

If the path that needs to be stored exceeds the default size of the
`sun_path` attribute of `struct sockaddr_un` (which is defined as a
108-sized byte array on Linux), a larger buffer needs to be allocated so
that it can hold the path, and it is the responsibility of the
`unix_sockaddr_cleanup()` function to release that allocated memory.

In Git's CI, this stack allocation is not necessary because the code is
checked out to `/home/runner/work/git/git`. Concatenate the path
`t/trash directory.t0301-credential-cache/.cache/git/credential/socket`
and a terminating NUL, and you end up with 96 bytes, 12 shy of the
default `sun_path` size.

However, I use worktrees with slightly longer paths:
`/home/me/projects/git/yes/i/nest/worktrees/to/organize/them/` is more
in line with what I have. When I recently tried to locally reproduce a
failure of the `linux-leaks` CI job, this t0301 test failed (where it
had not failed in CI).

The reason: When `credential-cache` tries to reach its daemon initially
by calling `unix_sockaddr_init()`, it is expected that the daemon cannot
be reached (the idea is to spin up the daemon in that case and try
again). However, when this first call to `unix_sockaddr_init()` fails,
the code returns early from the `unix_stream_connect()` function
_without_ giving the cleanup code a chance to run, skipping the
deallocation of above-mentioned path.

The fix is easy: do not return early but instead go directly to the
cleanup code.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:31 +01:00
Johannes Schindelin
ed536c9232 sideband: do allow ANSI color sequences by default
The preceding two commits introduced special handling of the sideband
channel to neutralize ANSI escape sequences before sending the payload
to the terminal, and `sideband.allowControlCharacters` to override that
behavior.

However, some `pre-receive` hooks that are actively used in practice
want to color their messages and therefore rely on the fact that Git
passes them through to the terminal.

In contrast to other ANSI escape sequences, it is highly unlikely that
coloring sequences can be essential tools in attack vectors that mislead
Git users e.g. by hiding crucial information.

Therefore we can have both: Continue to allow ANSI coloring sequences to
be passed to the terminal, and neutralize all other ANSI escape
sequences.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:31 +01:00
Sverre Rabbelier
ae83d576a7 transport-helper: add trailing --
[PT: ensure we add an additional element to the argv array]

Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:31 +01:00
Johannes Schindelin
69ad7769d9 sideband: introduce an "escape hatch" to allow control characters
The preceding commit fixed the vulnerability whereas sideband messages
(that are under the control of the remote server) could contain ANSI
escape sequences that would be sent to the terminal verbatim.

However, this fix may not be desirable under all circumstances, e.g.
when remote servers deliberately add coloring to their messages to
increase their urgency.

To help with those use cases, give users a way to opt-out of the
protections: `sideband.allowControlCharacters`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:31 +01:00
Sverre Rabbelier
61ca56afb7 t9350: point out that refs are not updated correctly
This happens only when the corresponding commits are not exported in
the current fast-export run. This can happen either when the relevant
commit is already marked, or when the commit is explicitly marked
as UNINTERESTING with a negative ref by another argument.

This breaks fast-export basec remote helpers.

Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
2026-01-28 07:16:31 +01:00
Johannes Schindelin
72f5de3454 sideband: mask control characters
The output of `git clone` is a vital component for understanding what
has happened when things go wrong. However, these logs are partially
under the control of the remote server (via the "sideband", which
typically contains what the remote `git pack-objects` process sends to
`stderr`), and is currently not sanitized by Git.

This makes Git susceptible to ANSI escape sequence injection (see
CWE-150, https://cwe.mitre.org/data/definitions/150.html), which allows
attackers to corrupt terminal state, to hide information, and even to
insert characters into the input buffer (i.e. as if the user had typed
those characters).

To plug this vulnerability, disallow any control character in the
sideband, replacing them instead with the common `^<letter/symbol>`
(e.g. `^[` for `\x1b`, `^A` for `\x01`).

There is likely a need for more fine-grained controls instead of using a
"heavy hammer" like this, which will be introduced subsequently.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-01-28 07:16:31 +01:00
Johannes Schindelin
2fab893deb Start the merging-rebase to v2.53.0-rc2
This commit starts the rebase of 3de3111a1bb8cba985f39033b1bde92840198da5 to 20f0c2a0fbb01b94d417a0d633a47bfbdd080841
2026-01-28 07:16:27 +01:00
Junio C Hamano
ea717645d1 RelNotes: a few spelling fixes
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-27 12:12:06 -08:00
Emir SARI
d63adbbbd5
l10n: tr: Update Turkish translations
Signed-off-by: Emir SARI <emir_sari@icloud.com>
2026-01-27 23:00:13 +03:00
Peter Krefting
cba7353aed l10n: sv.po: Update Swedish translation
Also fix typos reported by Tuomas Ahola.

Helped-by: Tuomas Ahola <taahol@utu.fi>.
Signed-off-by: Peter Krefting <peter@softwolves.pp.se>
2026-01-27 19:33:55 +01:00
Johannes Schindelin
e23c0db6dd
t/t5571-prep-push-hook.sh: Add test with writing to stderr (#6063)
Git v2.53.0-rc0 included f406b895529 (Merge branch
'ar/run-command-hook', 2026-01-06), which caused a regression on
Windows. While this merge was reverted for independent reasons in
a3d1f391d35 (Revert "Merge branch 'ar/run-command-hook'", 2026-01-15),
it seems worthwhile to ensure that writing to standard error from a
`pre-push` hook remains unbroken.

The symptom, when running this regression test case against
v2.53.0-rc0.windows.1 is that the `git push` fails, with this message
printed to standard error:

.git/hooks/pre-push: line 2: /dev/stderr: No such file or
direct[61/1940]
   error: failed to push some refs to 'repo1'

When that hook runs, `/dev/stderr` is a symlink to `/proc/self/fd/2`, as
always, but `ls -l /proc/self/fd/` shows this in the failing run

  total 0
  lrwxrwxrwx 1 me 4096 0 Jan 27 14:34 0 -> pipe:[0]
  lrwxrwxrwx 1 me 4096 0 Jan 27 14:34 1 -> pipe:[0]
  lrwxrwxrwx 1 me 4096 0 Jan 27 14:34 2 -> pipe:[0]

instead of the expected contents (which are shown when running this
against v2.53.0-rc1.windows.1):

  total 0
  lrwxrwxrwx 1 me 4096 0 Jan 27 14:53 0 -> 'pipe:[0]'
  lrwxrwxrwx 1 me 4096 0 Jan 27 14:53 1 -> /dev/cons1
lrwxrwxrwx 1 me 4096 0 Jan 27 14:53 2 -> '/path/to/git/t/trash
directory.t5571-pre-push-hook/actual'

This suggests that the underlying reason might be that `stdout` has an
exclusive handle to that pipe, and opening `stderr` (which points to the
same pipe) fails because of that exclusively-opened `stdout` handle.

This closes https://github.com/git-for-windows/git/issues/6053.
2026-01-27 15:13:22 +00:00
Junio C Hamano
ab380cb80b Git 2.53-rc2
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-26 22:26:31 -08:00
Bagas Sanjaya
6ef4d11472 l10n: po-id for 2.53
Update following components:

  * branch.c
  * builtin/blame.c
  * builtin/config.c
  * builtin/fast-export.c
  * builtin/fast-import.c
  * builtin/fetch.c
  * builtin/gc.c
  * builtin/index-pack.c
  * builtin/pack-objects.c
  * builtin/patch-id.c
  * builtin/replay.c
  * builtin/repo.c
  * bundle-uri.c
  * command-list.c
  * object-file.c
  * refs/reftable-backend.c
  * repack-promisor.c
  * strbuf.c

Signed-off-by: Bagas Sanjaya <bagasdotme@gmail.com>
2026-01-27 10:05:58 +07:00
Thomas Braun
c9aea168b5 t/t5571-prep-push-hook.sh: Add test with writing to stderr
The 2.53.0.rc0.windows release candidate had a regression where
writing to stderr from a pre-push hook would error out.

The regression was fixed in 2.53.0.rc1.windows and the test here ensures
that this stays fixed.

Signed-off-by: Thomas Braun <thomas.braun@virtuell-zuhause.de>
2026-01-26 23:06:53 +01:00
Aindriú Mac Giolla Eoin
d534a373e7
l10n: ga.po: Fix git-po-helper warnings
Signed-off-by: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>
2026-01-26 10:39:45 +00:00
Junio C Hamano
ab689ea7f9 Revert "Merge branch 'cs/rebased-subtree-split'"
This reverts commit 79e3055baba32e2952e6e8994cdcd4fc145ba7f0, reversing
changes made to 9813aace1e52765e01e688672cdcdcbe25336ec7.

Regresison report

    https://lore.kernel.org/git/755578cb-07e0-4b40-aa90-aacf4d45ccaa@heusel.eu/
2026-01-25 22:37:35 -08:00
Junio C Hamano
6959eee16e Merge branch 'master' of https://github.com/j6t/git-gui
* 'master' of https://github.com/j6t/git-gui:
  git-gui: mark *.po files at any directory level as UTF-8
  git-gui i18n: Update Bulgarian translation (558t)
  git-gui i18n: Update Bulgarian translation (557t)
2026-01-25 09:08:06 -08:00
Alexander Shopov
06045e3984 l10n: bg.po: Updated Bulgarian translation (6091t)
Signed-off-by: Alexander Shopov <ash@kambanaria.org>
2026-01-25 16:43:40 +01:00
Johannes Sixt
1a729ccb93 git-gui: mark *.po files at any directory level as UTF-8
When a commit is viewed in Gitk that changes a file in po/glossary, the
patch text shows mojibake instead of correctly decoded UTF-8 text.
Gitk retrieves the encoding attribute to decide how to treat the bytes
that make up the patch text. There is an attribute definition that all
files are US-ASCII, and a later attribute definition overrides this.
But the override, which specifies UTF-8, applies only to *.po files in
directory po/ and does not apply to subdirectories.

Widen the pattern to apply to all directory levels.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
2026-01-25 10:53:08 +01:00
Johannes Sixt
4b700c24e8 Merge branch 'master' of github.com:alshopov/git-gui
* 'master' of github.com:alshopov/git-gui:
  git-gui i18n: Update Bulgarian translation (558t)
2026-01-25 10:32:21 +01:00
Alexander Shopov
539e6337b8 git-gui i18n: Update Bulgarian translation (558t)
- Translate new string (558t)
- Add graves for disambiguation
- Improve glossary translation (96t) and synchonize with git

Signed-off-by: Alexander Shopov <ash@kambanaria.org>
2026-01-24 21:47:12 +01:00
Johannes Sixt
453fd8d14c Merge branch 'master' of github.com:alshopov/git-gui
* 'master' of github.com:alshopov/git-gui:
  git-gui i18n: Update Bulgarian translation (557t)

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
2026-01-24 09:25:29 +01:00
Junio C Hamano
ea24e2c554 A bit more before -rc2
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-23 13:34:37 -08:00
Junio C Hamano
a85b5220e1 Merge branch 'dk/replay-doc-omit-irrelevant-rev-list-options'
Documentation clean-up.

* dk/replay-doc-omit-irrelevant-rev-list-options:
  lint-gitlink: preemptively ignore all /ifn?def|endif/ macros
  replay: drop rev-list formatting options from manual
2026-01-23 13:34:37 -08:00
Junio C Hamano
26f50ef98f Merge branch 'js/symlink-windows'
Upstream symbolic link support on Windows from Git-for-Windows.

* js/symlink-windows:
  mingw: special-case index entries for symlinks with buggy size
  mingw: emulate `stat()` a little more faithfully
  mingw: try to create symlinks without elevated permissions
  mingw: add support for symlinks to directories
  mingw: implement basic `symlink()` functionality (file symlinks only)
  mingw: implement `readlink()`
  mingw: allow `mingw_chdir()` to change to symlink-resolved directories
  mingw: support renaming symlinks
  mingw: handle symlinks to directories in `mingw_unlink()`
  mingw: add symlink-specific error codes
  mingw: change default of `core.symlinks` to false
  mingw: factor out the retry logic
  mingw: compute the correct size for symlinks in `mingw_lstat()`
  mingw: teach dirent about symlinks
  mingw: let `mingw_lstat()` error early upon problems with reparse points
  mingw: drop the separate `do_lstat()` function
  mingw: implement `stat()` with symlink support
  mingw: don't call `GetFileAttributes()` twice in `mingw_lstat()`
2026-01-23 13:34:37 -08:00
Junio C Hamano
f2e92f7b04 Merge branch 'pw/mailmap-self'
Unify entries in .mailmap file for Phillip Wood.

* pw/mailmap-self:
  mailmap: add an entry for Phillip Wood
2026-01-23 13:34:36 -08:00
Junio C Hamano
1f047a6fba Merge branch 'js/ci-leak-skip-svn'
Dscho observed that SVN tests are taking too much time in CI leak
checking tasks, but most time is spent not in our code but in libsvn
code (which happen to be written in Perl), whose leaks have little
value to discover for us.  Skip SVN, P4, and CVS tests in the leak
checking tasks.

* js/ci-leak-skip-svn:
  ci: skip CVS and P4 tests in leaks job, too
  ci(*-leaks): skip the git-svn tests to save time
2026-01-23 13:34:36 -08:00
Junio C Hamano
3d95282129 Merge branch 'jx/build-options-gettext'
"git bugreport" and "git version --build-options" learned to
include use of 'gettext' feature, to make it easier to diagnose
problems around l10n.

* jx/build-options-gettext:
  help: report on whether or not gettext is enabled
2026-01-23 13:34:36 -08:00
Junio C Hamano
62627a3484 Merge branch 'ty/t1005-test-path-is-helpers'
Test clean-up.

* ty/t1005-test-path-is-helpers:
  t1005: modernize "! test -f" to "test_path_is_missing"
2026-01-23 13:34:36 -08:00
Junio C Hamano
cd8b8cba47 Merge branch 'rj/cygwin-test-fixes-for-2.53'
Test fixup.

* rj/cygwin-test-fixes-for-2.53:
  t0610-reftable-basics: mitigate a flaky test on cygwin
  t9700/test.pl: fix path type expectation on cygwin
2026-01-23 13:34:36 -08:00
Junio C Hamano
cfa173a5fa Merge branch 'sb/doc-update-ref-markup-fix'
Doc mark-up fix.

* sb/doc-update-ref-markup-fix:
  doc: fix `update-ref` `symref-create` formatting
2026-01-23 13:34:35 -08:00
Junio C Hamano
b3722b381e Merge branch 'kh/mailmap-avila'
* kh/mailmap-avila:
  .mailmap: fix and expand mappings for Jean-Noël Avila
2026-01-23 13:34:35 -08:00
Aindriú Mac Giolla Eoin
0c19f7f950
l10n: ga.po: Update Irish translation for Git 2.53
Signed-off-by: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>
2026-01-23 11:54:09 +00:00
Alexander Shopov
83a705b687 git-gui i18n: Update Bulgarian translation (557t)
Fix the meaning of a string

Signed-off-by: Alexander Shopov <ash@kambanaria.org>
2026-01-23 11:14:01 +01:00
Junio C Hamano
1faf5b085a A few on top of -rc1
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-21 16:16:28 -08:00
Junio C Hamano
214cbb7b1d Merge branch 'rs/tree-wo-the-repository'
Remove implicit reliance on the_repository global in the APIs
around tree objects and make it explicit which repository to work
in.

* rs/tree-wo-the-repository:
  cocci: remove obsolete the_repository rules
  cocci: convert parse_tree functions to repo_ variants
  tree: stop using the_repository
  tree: use repo_parse_tree()
  path-walk: use repo_parse_tree_gently()
  pack-bitmap-write: use repo_parse_tree()
  delta-islands: use repo_parse_tree()
  bloom: use repo_parse_tree()
  add-interactive: use repo_parse_tree_indirect()
  tree: add repo_parse_tree*()
  environment: move access to core.maxTreeDepth into repo settings
2026-01-21 16:16:28 -08:00
Junio C Hamano
c0b4d20979 Merge branch 'ps/config-doc-get-urlmatch-fix'
Docfix.

* ps/config-doc-get-urlmatch-fix:
  Documentation/config: fix replacement for --get-urlmatch
2026-01-21 16:16:28 -08:00
Junio C Hamano
e13de9ed8e Merge branch 'tb/midx-write-corrupt-checksum-fix'
The logic that avoids reusing MIDX files with a wrong checksum was
broken, which has been corrected.

* tb/midx-write-corrupt-checksum-fix:
  midx-write.c: assume checksum-invalid MIDXs require an update
  t/t5319-multi-pack-index.sh: drop early 'test_done'
2026-01-21 16:16:27 -08:00
Junio C Hamano
070fa41675 Merge branch 'ps/geometric-repacking-with-promisor-remotes'
"git repack --geometric" did not work with promisor packs, which
has been corrected.

* ps/geometric-repacking-with-promisor-remotes:
  builtin/repack: handle promisor packs with geometric repacking
  repack-promisor: extract function to remove redundant packs
  repack-promisor: extract function to finalize repacking
  repack-geometry: extract function to compute repacking split
  builtin/pack-objects: exclude promisor objects with "--stdin-packs"
2026-01-21 16:16:27 -08:00
Kristoffer Haugsbakk
7dfd1b4c13 .mailmap: fix and expand mappings for Jean-Noël Avila
The latest release candidate notes say that there is a new contributor:

    Jean-Noël Avila via GitGitGadget, ...

But this is a familiar face, just in a G.G. Gadget trench coat.

Also map the rest of the idents in the history.

Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-21 15:12:22 -08:00
Jean-Noël Avila
46933bf182 lint-gitlink: preemptively ignore all /ifn?def|endif/ macros
Instead of testing if the macro name is ifn?def:: as if it were a inline
macro, it is faster and safer to just ignore such block macro lines before
hand.

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-21 08:26:00 -08:00
D. Ben Knoble
ad228c24df replay: drop rev-list formatting options from manual
The rev-list options in our manuals are quite long; git-replay's manual
is no exception. Since replay doesn't use the formatting options at all
(it has its own output format), drop them.

This is the first time we have needed compound tests [1] for if[n]def in
our documentation:

    git grep '^ifn\?def::' Documentation | grep '[,+]'

[1]: https://docs.asciidoctor.org/asciidoc/latest/directives/ifdef-ifndef/

For both ifdef and ifndef, the "," takes on the intuitive meaning:
- ifdef: if any of the listed attributes are set…
- ifndef: unless any of the listed attributes are set

(Use "+" for "all".)

Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-20 09:38:56 -08:00
Phillip Wood
28cfac364f mailmap: add an entry for Phillip Wood
While all my commits appear under the same address, other addresses
appear in some commit trailers. Map those addresses to the canonical
one.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-20 07:45:38 -08:00
Junio C Hamano
047bd7dfe3 ci: skip CVS and P4 tests in leaks job, too
Looking at the CI logs, the p4 and cvs tests account for another 24
minutes of test time and they offer minimal value for quite a
similar reason as the previous step.

Let's introduce and use a mechanism to skip these tests to save
some resources.

Suggested-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-19 11:02:31 -08:00
Johannes Schindelin
d7971544fe ci(*-leaks): skip the git-svn tests to save time
I noticed recently that the leak-checking jobs still take a lot of time,
and upon analysis, the git-svn tests contribute significantly to this.

Analyzing a recent CI run, I saw that the Git test suite contains
1,017 tests, running for approximately 5¼ hours total. Of these, 65
git-svn-related tests (~6% of test count) took 42.24 minutes combined,
accounting for ~13.% of the total runtime. This implies that the git-svn
tests are roughly twice as expernsive compared to the other tests.

However, testing git-svn in the leak-checking jobs provides minimal
value: git-svn is implemented as a Perl script, and leak checking only
handles C code. While git-svn does call into Git's built-in commands
that are implemented in C, these are standard Git operations that are
already thoroughly exercised elsewhere in the test suite. Therefore,
running the git-svn tests in the leak-checking jobs only adds to the
overall run time with little value in return.

Given that the leak-checking jobs are particularly time-intensive and
these 42+ minutes of SVN tests per job provide no additional leak
detection value, skip them in the *-leaks jobs to reduce CI runtime.

Assisted-by: Claude Sonnet 4.5
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-17 10:23:59 -08:00
Tian Yuchen
bc8556d066 t1005: modernize "! test -f" to "test_path_is_missing"
Replace instances of "! test -f <file>" with "test_path_is_missing <file>".
This macro provides better diagnostics when the test fails (it prints
"Path exists:" instead of silently failing).

Signed-off-by: Tian Yuchen <a3205153416@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-17 10:01:14 -08:00
Jiang Xin
de985d69f6 help: report on whether or not gettext is enabled
When users report that Git has no localized output, we need to check not
only their locale settings, but also whether Git was built with GETTEXT
support in the first place.

Expose this information via the existing build info output by adding a
"gettext: enabled" line to `git version --build-options` (and therefore
also to `git bugreport`) when `NO_GETTEXT` is not defined at build time.

Signed-off-by: Jiang Xin <zhiyou.jx@alibaba-inc.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-17 09:57:59 -08:00
Ramsay Jones
59da9f292a t0610-reftable-basics: mitigate a flaky test on cygwin
Test #29 ('ref transaction: corrupted tables cause failure') started to
fail intermittently for me (from v2.52.0-rc0) when running the testsuite
with '-j8'. (Also, having moved to a new laptop and windows 11, rather
than windows 10). If the test is run by hand, or without any parallelism,
then it passes without issue.

When the test fails (e.g. 1 out of 32 parallel runs) the cause is due to
a permission error while corrupting a table file:

  ./test-lib.sh: line 1010: .git/reftable/0x000000000001-0x000000000002-d89bb8ee.ref: Permission denied

This corruption is done in a shell loop, directly after a 'test_commit',
which uses an ': >"$f"' expression to truncate the file. Adding a sleep
of one second after the 'test_commit' and before the shell loop fixes
the test (it is not clear why). Replacing the redirection shell expression
with a 'test-tool truncate "$f" 0' invocation also provides a fix, which
could simply be another way to change the timing sufficiently to win the
race.

During a debug session, I tried looking at the strace output for the
shell redirection:

  $ rm /tmp/hello; echo hello >/tmp/hello; ls -l /tmp/hello
  -rw-r--r-- 1 ramsay None 6 Nov 10 17:25 /tmp/hello
  $

  $ strace -o zzz bash -c ': >/tmp/hello'
  $

Similarly, for the test-tool solution:

  $ strace -o xxx ./t/helper/test-tool truncate /tmp/hello 0
  $

When comparing the output, the differences seemed to be what you would
expect and, if anything, the shell redirect probably would have taken
longer than the test-tool solution (many fcntl() calls to dup the stdout
to the <fd>).  The call to the win32 api NtCreateFile() was identical,
apart from the first (FileHandle) parameter, of course.

In order to fix this flaky test on cygwin, despite not knowing why it
works, replace the shell redirection with the above 'test-tool truncate'
invocation.

Helped-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-16 14:01:42 -08:00
Ramsay Jones
c381a21490 t9700/test.pl: fix path type expectation on cygwin
Commit 4ec7ac101b ("t9700: accommodate for Windows paths", 2025-12-17)
changed the type of the absolute path to the git directory from unix to
win32 for both GfW and cygwin. This fixed the test for GfW but causes
new failures on cygwin, since the test expectation is that it uses unix
paths on cygwin. In order to not break cygwin, disable the new code by
removing the "or $^O eq 'cygwin'" sub-expression from the conditional
part of the fix.

Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-16 13:59:57 -08:00
René Scharfe
4eb105c119 cocci: remove obsolete the_repository rules
035c7de9e9e (cocci: apply the "revision.h" part of
"the_repository.pending", 2023-03-28) removed the last of the repo-less
functions and macros mentioned in the_repository.cocci at the time.  No
stragglers appeared since then.  Remove the applied rules now that they
have outlived their usefulness.

Also add a reminder to eventually remove the just added rules for
tree.h.

Suggested-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-15 14:18:08 -08:00
Pushkar Singh
5814b04c02 Documentation/config: fix replacement for --get-urlmatch
The documentation claims that --get-urlmatch is replaced by

  git config get --all --show-names --url=<URL> <name>

However, --url cannot be combined with --all, and this command
fails in practice.

Update the replacement to use only --url, which matches the
actual behavior of --get-urlmatch.

Signed-off-by: Pushkar Singh <pushkarkumarsingh1970@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-15 05:50:55 -08:00
Patrick Steinhardt
dcc9c7ef47 builtin/repack: handle promisor packs with geometric repacking
When performing a fetch with an object filter, we mark the resulting
packfile as a promisor pack. An object part of such a pack may miss any
of its referenced objects, and Git knows to handle this case by fetching
any such missing objects from the promisor remote.

The "promisor" property needs to be retained going forward. So every
time we pack a promisor object, the resulting pack must be marked as a
promisor pack. git-repack(1) does this already: when a repository has a
promisor remote, it knows to pass "--exclude-promisor-objects" to the
git-pack-objects(1) child process. Promisor packs are written separately
when doing an all-into-one repack via `repack_promisor_objects()`.

But we don't support promisor objects when doing a geometric repack yet.
Promisor packs do not get any special treatment there, as we simply
merge promisor and non-promisor packs. The resulting pack is not even
marked as a promisor pack, which essentially corrupts the repository.

This corruption couldn't happen in the real world though: we pass both
"--exclude-promisor-objects" and "--stdin-packs" to git-pack-objects(1)
if a repository has a promisor remote, but as those options are mutually
exclusive we always end up dying. And while we made those flags
compatible with one another in a preceding commit, we still end up dying
in case git-pack-objects(1) is asked to repack a promisor pack.

There's multiple ways to fix this:

  - We can exclude promisor packs from the geometric progression
    altogether. This would have the consequence that we never repack
    promisor packs at all. But in a partial clone it is quite likely
    that the user generates a bunch of promisor packs over time, as
    every backfill fetch would create another one. So this doesn't
    really feel like a sensible option.

  - We can adapt git-pack-objects(1) to support repacking promisor packs
    and include them in the normal geometric progression. But this would
    mean that the set of promisor objects expands over time as the packs
    are merged with normal packs.

  - We can use a separate geometric progression to repack promisor
    packs.

The first two options both have significant downsides, so they aren't
really feasible. But the third option fixes both of these downsides: we
make sure that promisor packs get merged, and at the same time we never
expand the set of promisor objects beyond the set of objects that are
already marked as promisor objects.

Implement this strategy so that geometric repacking works in partial
clones.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-14 06:29:24 -08:00
Patrick Steinhardt
fa7b91247b repack-promisor: extract function to remove redundant packs
We're about to add a second caller that wants to remove redundant packs
after a geometric repack. Split out the function which does this to
prepare for that.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-14 06:29:24 -08:00
Patrick Steinhardt
dd8c4e12c2 repack-promisor: extract function to finalize repacking
We're about to add a second caller that wants to finalize repacking of
promisor objects. Split out the function which does this to prepare for
that.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-14 06:29:24 -08:00
Patrick Steinhardt
861248b946 repack-geometry: extract function to compute repacking split
We're about to add a second caller that wants to compute the repacking
split for a set of packfiles. Split out the function that computes this
split to prepare for that.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-14 06:29:24 -08:00
Patrick Steinhardt
0cd306ebc8 builtin/pack-objects: exclude promisor objects with "--stdin-packs"
It is currently not possible to combine "--exclude-promisor-objects"
with "--stdin-packs" because both flags want to set up a revision walk
to enumerate the objects to pack. In a subsequent commit though we want
to extend geometric repacks to support promisor objects, and for that we
need to handle the combination of both flags.

There are two cases we have to think about here:

  - "--stdin-packs" asks us to pack exactly the objects part of the
    specified packfiles. It is somewhat questionable what to do in the
    case where the user asks us to exclude promisor objects, but at the
    same time explicitly passes a promisor pack to us. For now, we
    simply abort the request as it is self-contradicting. As we have
    also been dying before this commit there is no regression here.

  - "--stdin-packs=follow" does the same as the first flag, but it also
    asks us to include all objects transitively reachable from any
    object in the packs we are about to repack. This is done by doing
    the revision walk mentioned further up. Luckily, fixing this case is
    trivial: we only need to modify the revision walk to also set the
    `exclude_promisor_objects` field.

Note that we do not support the "--exclude-promisor-objects-best-effort"
flag for now as we don't need it to support geometric repacking with
promisor objects.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-14 06:29:24 -08:00
Taylor Blau
38b72e5815 midx-write.c: assume checksum-invalid MIDXs require an update
In 6ce9d558ced (midx-write: skip rewriting MIDX with `--stdin-packs`
unless needed, 2025-12-10), the MIDX machinery learned how to optimize
out unnecessary writes with "--stdin-packs".

In order to do this, it compares the contents of the in-progress write
against a MIDX loaded directly from the object store. We load a separate
MIDX (as opposed to checking our update relative to "ctx.m") because the
MIDX code does not reuse an existing MIDX with --stdin-packs, and always
leaves "ctx.m" as NULL. See commit 0c5a62f14bc (midx-write.c: do not
read existing MIDX with `packs_to_include`, 2024-06-11) for details on
why.

If "ctx.m" is non-NULL, however, it is guaranteed to be checksum-valid,
since we only assign "ctx.m" when "midx_checksum_valid()" returns true.
Since the same guard does not exist for the MIDX we pass to
"midx_needs_update()", we may ignore on-disk corruption when determining
whether or not we can optimize out the write.

Add a similar guard within "midx_needs_update()" to prevent such an
issue.

A more robust fix would involve revising 0c5a62f14bc and teaching the
MIDX generation code how to reuse an existing MIDX even when invoked
with "--stdin-packs", such that we could avoid side-loading the MIDX
directly from the object store in order to call "midx_needs_update()".
For now, pursue the minimal fix.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-13 05:21:34 -08:00
Taylor Blau
e16ac6ca0d t/t5319-multi-pack-index.sh: drop early 'test_done'
In 6ce9d558ced (midx-write: skip rewriting MIDX with `--stdin-packs`
unless needed, 2025-12-10), an extra 'test_done' was added, causing the
test script to finish before having run all of its tests.

Dropping this extraneous 'test_done' exposes a bug from commit
6ce9d558ced that causes a subsequent test to fail. Mark that test with a
'test_expect_failure' for now, and the subsequent commit will explain
and fix the bug.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-13 05:21:34 -08:00
Junio C Hamano
cc06d7e7ff Merge branch 'ps/repack-avoid-noop-midx-rewrite' into tb/midx-write-corrupt-checksum-fix
* ps/repack-avoid-noop-midx-rewrite:
  midx-write: skip rewriting MIDX with `--stdin-packs` unless needed
  midx-write: extract function to test whether MIDX needs updating
  midx: fix `BUG()` when getting preferred pack without a reverse index
2026-01-13 05:21:09 -08:00
René Scharfe
ec7a16b145 cocci: convert parse_tree functions to repo_ variants
Add and apply a semantic patch to convert calls to parse_tree() and
friends to the corresponding variant that takes a repository argument,
to allow the functions that implicitly use the_repository to be retired
once all potential in-flight topics are settled and converted as well.

The changes in .c files were generated by Coccinelle, but I fixed a
whitespace bug it would have introduced to builtin/commit.c.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-09 18:36:18 -08:00
René Scharfe
a8a50f29ae tree: stop using the_repository
Push the use of the_repository to the remaining callers by turning the
compatibility wrappers into macros, whose use still requires
USE_THE_REPOSITORY_VARIABLE to be defined.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-09 18:36:17 -08:00
René Scharfe
e61c387a1b tree: use repo_parse_tree()
e092073d64 (tree.c: make read_tree*() take 'struct repository *',
2018-11-18) replaced explicit uses of the_repository.  parse_tree() uses
it internally, though, so call repo_parse_tree() instead and hand it the
correct repository.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-09 18:36:17 -08:00
René Scharfe
d473865154 path-walk: use repo_parse_tree_gently()
Use the passed in repository instead of the implicit the_repository when
parsing the tree.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-09 18:36:17 -08:00
René Scharfe
fd64c6fbcb pack-bitmap-write: use repo_parse_tree()
1a6768d1dd (pack-bitmap-write: stop depending on `the_repository`,
2025-03-10) replaced explicit uses of the_repository.  parse_tree() uses
it internally, though, so call repo_parse_tree() instead and hand it the
correct repository.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-09 18:36:17 -08:00
René Scharfe
d54eb12910 delta-islands: use repo_parse_tree()
19be71db9c (delta-islands: stop depending on `the_repository`,
2025-03-10) replaced explicit uses of the_repository.  parse_tree() uses
it internally, though, so call repo_parse_tree() instead and hand it the
correct repository.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-09 18:36:17 -08:00
René Scharfe
83131ed25c bloom: use repo_parse_tree()
Use the passed in repository instead of the implicit the_repository when
parsing the tree.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-09 18:36:16 -08:00
René Scharfe
548aaf9d06 add-interactive: use repo_parse_tree_indirect()
1b374ad71f (add-interactive: stop using `the_repository`, 2024-12-17)
replaced explicit uses of the_repository.  parse_tree_indirect() uses it
internally, though, so call repo_parse_tree_indirect() instead and hand
it the correct repository.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-09 18:36:16 -08:00
René Scharfe
2b74f68ca0 tree: add repo_parse_tree*()
Add variants of parse_tree(), parse_tree_gently() and
parse_tree_indirect() that allow using an arbitrary repository.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-09 18:36:16 -08:00
René Scharfe
e691395365 environment: move access to core.maxTreeDepth into repo settings
The config setting core.maxTreeDepth is stored in a global variable and
populated by the function git_default_core_config.  This won't work if
we need to access multiple repositories with different values of that
setting in the same process.  Store the setting in struct repo_settings
instead and track it separately for each repository.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-09 18:36:16 -08:00
Johannes Schindelin
44af34bde7 mingw: special-case index entries for symlinks with buggy size
In https://github.com/git-for-windows/git/pull/2637, we fixed a bug
where symbolic links' target path sizes were recorded incorrectly in the
index. The downside of this fix was that every user with tracked
symbolic links in their checkouts would see them as modified in `git
status`, but not in `git diff`, and only a `git add <path>` (or `git add
-u`) would "fix" this.

Let's do better than that: we can detect that situation and simply
pretend that a symbolic link with a known bad size (or a size that just
happens to be that bad size, a _very_ unlikely scenario because it would
overflow our buffers due to the trailing NUL byte) means that it needs
to be re-checked as if we had just checked it out.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-09 18:32:55 -08:00
Johannes Schindelin
2cba5746c0 mingw: emulate stat() a little more faithfully
When creating directories via `safe_create_leading_directories()`, we
might encounter an already-existing directory which is not
readable by the current user. To handle that situation, Git's code calls
`stat()` to determine whether we're looking at a directory.

In such a case, `CreateFile()` will fail, though, no matter what, and
consequently `mingw_stat()` will fail, too. But POSIX semantics seem to
still allow `stat()` to go forward.

So let's call `mingw_lstat()` to the rescue if we fail to get a file
handle due to denied permission in `mingw_stat()`, and fill the stat
info that way.

We need to be careful to not allow this to go forward in case that we're
looking at a symbolic link: to resolve the link, we would still have to
create a file handle, and we just found out that we cannot. Therefore,
`stat()` still needs to fail with `EACCES` in that case.

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

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-09 18:32:55 -08:00
Johannes Schindelin
6206f7aeb0 mingw: try to create symlinks without elevated permissions
As of Windows 10 Build 14972 in Developer Mode, a new flag is supported
by `CreateSymbolicLink()` to create symbolic links even when running
outside of an elevated session (which was previously required).

This new flag is called `SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE`
and has the numeric value 0x02.

Previous Windows 10 versions will not understand that flag and return
an `ERROR_INVALID_PARAMETER`, therefore we have to be careful to try
passing that flag only when the build number indicates that it is
supported.

For more information about the new flag, see this blog post:
https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-09 18:32:55 -08:00
Karsten Blees
97be7aa43a mingw: add support for symlinks to directories
Symlinks on Windows have a flag that indicates whether the target is a
file or a directory. Symlinks of wrong type simply don't work. This even
affects core Win32 APIs (e.g. `DeleteFile()` refuses to delete directory
symlinks).

However, `CreateFile()` with FILE_FLAG_BACKUP_SEMANTICS does work. Check
the target type by first creating a tentative file symlink, opening it,
and checking the type of the resulting handle. If it is a directory,
recreate the symlink with the directory flag set.

It is possible to create symlinks before the target exists (or in case
of symlinks to symlinks: before the target type is known). If this
happens, create a tentative file symlink and postpone the directory
decision: keep a list of phantom symlinks to be processed whenever a new
directory is created in `mingw_mkdir()`.

Limitations: This algorithm may fail if a link target changes from file
to directory or vice versa, or if the target directory is created in
another process. It's the best Git can do, though.

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>
2026-01-09 18:32:55 -08:00
Karsten Blees
593008b95d mingw: implement basic symlink() functionality (file symlinks only)
Implement `symlink()`. This implementation always creates _file_
symlinks (remember: Windows discerns between symlinks pointing to
directories and those pointing to files). Support for directory symlinks
will be added in a subseqeuent commit.

This implementation fails with `ENOSYS` if symlinks are disabled or
unsupported.

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>
2026-01-09 18:32:55 -08:00
Karsten Blees
980852dbff mingw: implement readlink()
Implement `readlink()` by reading NTFS reparse points via the
`read_reparse_point()` function that was introduced earlier to determine
the length of symlink targets. Works for symlinks and directory
junctions.

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>
2026-01-09 18:32:55 -08:00
Karsten Blees
43745a7d55 mingw: allow mingw_chdir() to change to symlink-resolved directories
If symlinks are enabled, resolve all symlinks when changing directories,
as required by POSIX.

Note: Git's `real_path()` function bases its link resolution algorithm
on this property of `chdir()`. Unfortunately, the current directory on
Windows is limited to only MAX_PATH (260) characters. Therefore using
symlinks and long paths in combination may be problematic.

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>
2026-01-09 18:32:55 -08:00
Karsten Blees
5e88e98c04 mingw: support renaming symlinks
Older MSVCRT's `_wrename()` function cannot rename symlinks over
existing files: it returns success without doing anything. Newer
MSVCR*.dll versions probably do not share this problem: according to CRT
sources, they just call `MoveFileEx()` with the `MOVEFILE_COPY_ALLOWED`
flag.

Avoid the `_wrename()` call, and go with directly calling
`MoveFileEx()`, with proper error handling of course.

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>
2026-01-09 18:32:55 -08:00
Karsten Blees
ac41bfa374 mingw: handle symlinks to directories in mingw_unlink()
The `_wunlink()` and `DeleteFileW()` functions refuse to delete symlinks
to directories on Windows; The error code would be `ERROR_ACCESS_DENIED`
in that case. Take that error code as an indicator that we need to try
`_wrmdir()` as well. In the best case, it will remove a symlink. In the
worst case, it will fail with the same error code again.

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>
2026-01-09 18:32:55 -08:00
Karsten Blees
9ac15c2ae3 mingw: add symlink-specific error codes
The Win32 API calls do not set `errno`; Instead, error codes for failed
operations must be obtained via the `GetLastError()` function. Git would
not know what to do with those error values, though, which is why Git's
Windows compatibility layer translates them to `errno` values.

Let's handle a couple of symlink-related error codes that will become
relevant with the upcoming support for symlinks on Windows.

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>
2026-01-09 18:32:55 -08:00
Karsten Blees
1bf1ffadc8 mingw: change default of core.symlinks to false
Symlinks on Windows don't work the same way as on Unix systems. For
example, there are different types of symlinks for directories and
files, and unless using a recent-ish Windows version in Developer Mode,
creating symlinks requires administrative privileges.

By default, disable symlink support on Windows. That is, users
explicitly have to enable it with `git config [--system|--global]
core.symlinks true`; For convenience, `git init` (and `git clone`)
will perform a test whether the current setup allows creating symlinks
and will configure that setting in the repository config.

The test suite ignores system / global config files. Allow
testing *with* symlink support by checking if native symlinks are
enabled in MSYS2 (via setting the special environment variable
`MSYS=winsymlinks:nativestrict` to ask the MSYS2 runtime to enable
creating symlinks).

Note: This assumes that Git's test suite is run in MSYS2's Bash, which
is true for the time being (an experiment to switch to BusyBox-w32
failed due to the experimental nature of BusyBox-w32).

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>
2026-01-09 18:32:55 -08:00
Karsten Blees
b0b32ff16f mingw: factor out the retry logic
In several places, Git's Windows-specific code follows the pattern where
it tries to perform an operation, and retries several times when that
operation fails, sleeping an increasing amount of time, before finally
giving up and asking the user whether to rety (after, say, closing an
editor that held a handle to a file, preventing the operation from
succeeding).

This logic is a bit hard to use, and inconsistent:
`mingw_unlink()` and `mingw_rmdir()` duplicate the code to retry,
and both of them do so incompletely. They also do not restore `errno` if the
user answers 'no'.

Introduce a `retry_ask_yes_no()` helper function that handles retry with
small delay, asking the user, and restoring `errno`.

Note that in `mingw_unlink()`, we include the `_wchmod()` call in the
retry loop (which may fail if the file is locked exclusively).

In `mingw_rmdir()`, we include special error handling in the retry loop.

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>
2026-01-09 18:32:55 -08:00
Bill Zissimopoulos
543a91ccf9 mingw: compute the correct size for symlinks in mingw_lstat()
POSIX specifies that upon successful return from `lstat()`: "the
value of the st_size member shall be set to the length of the pathname
contained in the symbolic link not including any terminating null byte".

Git typically doesn't trust the `stat.st_size` member of symlinks (e.g.
see `strbuf_readlink()`). Therefore, it is tempting to save on the extra
overhead of opening and reading the reparse point merely to calculate
the exact size of the link target.

This is, in fact, what Git for Windows did, from May 2015 to May 2020.
At least almost: some functions take shortcuts if `st_size` is 0 (e.g.
`diff_populate_filespec()`), hence Git for Windows hard-coded the length
of all symlinks to MAX_PATH.

This did cause problems, though, specifically in Git repositories
that were also accessed by Git for Cygwin or Git for WSL. For example,
doing `git reset --hard` using Git for Windows would update the size of
symlinks in the index to be MAX_PATH; at a later time Git for Cygwin
or Git for WSL would find that symlinks have changed size during `git
status` and update the index. And then Git for Windows would think that
the index needs to be updated. Even if the symlinks did not, in fact,
change. To avoid that, the correct size must be determined.

Signed-off-by: Bill Zissimopoulos <billziss@navimatics.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-01-09 18:32:55 -08:00
Karsten Blees
8a4f4131aa mingw: teach dirent about symlinks
Move the `S_IFLNK` detection to `file_attr_to_st_mode()`.

Implement `DT_LNK` detection in dirent.c's `readdir()` function.

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>
2026-01-09 18:32:55 -08:00
Karsten Blees
2c37842ff9 mingw: let mingw_lstat() error early upon problems with reparse points
When obtaining lstat information for reparse points, we need to call
`FindFirstFile()` in addition to `GetFileInformationEx()` to obtain
the type of the reparse point (symlink, mount point etc.). However,
currently there is no error handling whatsoever if `FindFirstFile()`
fails.

Call `FindFirstFile()` before modifying the `stat *buf` output parameter
and error out if the call fails.

Note: The `FindFirstFile()` return value includes all the data
that we get from `GetFileAttributesEx()`, so we could replace
`GetFileAttributesEx()` with `FindFirstFile()`. We don't do that because
`GetFileAttributesEx()` is about twice as fast for single files. I.e.
we only pay the extra cost of calling `FindFirstFile()` in the rare case
that we encounter a reparse point.

Please also note that the indentation the remaining reparse point
code changed, and hence the best way to look at this diff is with
`--color-moved -w`. That code was _not_ moved because a subsequent
commit will move it to an altogether different function, anyway.

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>
2026-01-09 18:32:55 -08:00
Karsten Blees
882e5e0528 mingw: drop the separate do_lstat() function
With the new `mingw_stat()` implementation, `do_lstat()` is only called
from `mingw_lstat()` (with the function parameter `follow == 0`). Remove
the extra function and the old `mingw_stat()`-specific (`follow == 1`)
logic.

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>
2026-01-09 18:32:54 -08:00
Karsten Blees
48bc5094de mingw: implement stat() with symlink support
With respect to symlinks, the current `mingw_stat()` implementation is
almost identical to `mingw_lstat()`: except for the file type (`st_mode
& S_IFMT`), it returns information about the link rather than the target.

Implement `mingw_stat()` by opening the file handle requesting minimal
permissions, and then calling `GetFileInformationByHandle()` on it. This
way, all links are resolved by the Windows file system layer.

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>
2026-01-09 18:32:54 -08:00
Karsten Blees
3b96b99683 mingw: don't call GetFileAttributes() twice in mingw_lstat()
The Win32 API function `GetFileAttributes()` cannot handle paths with
trailing dir separators. The current `mingw_stat()`/`mingw_lstat()`
implementation calls `GetFileAttributes()` twice if the path has
trailing slashes (first with the original path that was passed as
function parameter, and and a second time with a path copy with trailing
'/' removed).

With the conversion to wide Unicode, we get the length of the path for
free, and also have a (wide char) buffer that can be modified. This
makes it easy to avoid that extraneous Win32 API call.

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>
2026-01-09 18:32:54 -08:00
Junio C Hamano
ec13dca8d0 Merge branch 'js/prep-symlink-windows' into js/symlink-windows
* js/prep-symlink-windows:
  trim_last_path_component(): avoid hard-coding the directory separator
  strbuf_readlink(): support link targets that exceed 2*PATH_MAX
  strbuf_readlink(): avoid calling `readlink()` twice in corner-cases
  init: do parse _all_ core.* settings early
  mingw: do resolve symlinks in `getcwd()`
  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
2026-01-09 18:32:29 -08:00
Sam Bostock
5ae594f30b doc: fix update-ref symref-create formatting
`symref-create` should be followed `::`, not `:`. The lack of second
colon (`:`) causes it to appear as regular text (`<p>`) instead of as a
description list term (`<dt>`) in the HTML documentation.

Signed-off-by: Sam Bostock <sam@sambostock.ca>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-12-09 18:31:36 +09:00
80 changed files with 4779 additions and 4114 deletions

View File

@ -107,6 +107,9 @@ Jason Riedy <ejr@eecs.berkeley.edu> <ejr@cs.berkeley.edu>
Jay Soffian <jaysoffian@gmail.com> <jaysoffian+git@gmail.com>
Jean-Noël Avila <jn.avila@free.fr> Jean-Noel Avila
Jean-Noël Avila <jn.avila@free.fr> Jean-Noël AVILA
Jean-Noël Avila <jn.avila@free.fr> Jean-Noel Avila <jean-noel.avila@scantech.fr>
Jean-Noël Avila <jn.avila@free.fr> Jean-Noël AVILA <avila.jn@gmail.com>
Jean-Noël Avila <jn.avila@free.fr> Jean-Noël Avila via GitGitGadget <gitgitgadget@gmail.com>
Jeff King <peff@peff.net> <peff@github.com>
Jeff Muizelaar <jmuizelaar@mozilla.com> <jeff@infidigm.net>
Jens Axboe <axboe@kernel.dk> <axboe@suse.de>
@ -226,6 +229,8 @@ Philip Jägenstedt <philip@foolip.org> <philip.jagenstedt@gmail.com>
Philip Oakley <philipoakley@iee.email> <philipoakley@iee.org> # secondary <philipoakley@dunelm.org.uk>
Philipp A. Hartmann <pah@qo.cx> <ph@sorgh.de>
Philippe Bruhat <book@cpan.org>
Phillip Wood <phillip.wood@dunelm.org.uk> <phillip.wood123@gmail.com>
Phillip Wood <phillip.wood@dunelm.org.uk> <phillip.wood@talktalk.net>
Ralf Thielow <ralf.thielow@gmail.com> <ralf.thielow@googlemail.com>
Ramsay Jones <ramsay@ramsayjones.plus.com> <ramsay@ramsay1.demon.co.uk>
Ramkumar Ramachandra <r@artagnon.com> <artagnon@gmail.com>

View File

@ -20,8 +20,8 @@ UI, Workflows & Features
* Add a new manual that describes the data model.
* "git fast-import" learns "--strip-if-invalid" option to drop
invalid cryptographic signature from objects.
* "git fast-import" learns "--signed-commits=strip-if-invalid" option
to drop invalid cryptographic signature from objects.
* The use of "revision" (a connected set of commits) has been
clarified in the "git replay" documentation.
@ -38,12 +38,11 @@ UI, Workflows & Features
`--onto` option of "git replay". Test coverage of "git replay" has
been improved.
* The split command in "git subtree" (in contrib/) has been taught to
deal better with rebased history.
* The iconv library on macOS fails to correctly handle stateful
ISO/IEC 2022 encoded strings. Work it around instead of replacing
it wholesale from homebrew.
ISO/IEC 2022:1994 encoded strings. Work it around instead of
replacing it wholesale from homebrew.
* Upstream symbolic link support on Windows from Git-for-Windows.
Performance, Internal Implementation, Development Support etc.
@ -65,13 +64,13 @@ Performance, Internal Implementation, Development Support etc.
* "make strip" has been taught to strip "scalar" as well as "git".
* Dockerised jobs at the GitHub Actions CI have been taught to show
* Dockerized jobs at the GitHub Actions CI have been taught to show
more details of failed tests.
* Code refactoring around object database sources.
* Halve the memory consumed by artificial filepairs created during
"git diff --find-copioes-harder", also making the operation run
"git diff --find-copies-harder", also making the operation run
faster.
* The "git_istream" abstraction has been revamped to make it easier
@ -110,6 +109,21 @@ Performance, Internal Implementation, Development Support etc.
* Further preparation to upstream symbolic link support on Windows.
* Remove implicit reliance on the_repository global in the APIs
around tree objects and make it explicit which repository to work
in.
* "git bugreport" and "git version --build-options" learned to
include use of 'gettext' feature, to make it easier to diagnose
problems around l10n.
* Dscho observed that SVN tests are taking too much time in CI leak
checking tasks, but most time is spent not in our code but in libsvn
code (which happen to be written in Perl), whose leaks have little
value to discover for us. Skip SVN, P4, and CVS tests in the leak
checking tasks.
(merge 047bd7dfe3 js/ci-leak-skip-svn later to maint).
Fixes since v2.52
-----------------
@ -124,7 +138,7 @@ Fixes since v2.52
(merge 42ed046866 jk/attr-macroexpand-wo-recursion later to maint).
* Adding a repository that uses a different hash function is a no-no,
but "git submodule add" did nt prevent it, which has been corrected.
but "git submodule add" did not prevent it, which has been corrected.
(merge 6fe288bfbc bc/submodule-force-same-hash later to maint).
* An earlier check added to osx keychain credential helper to avoid
@ -145,7 +159,7 @@ Fixes since v2.52
* Test leakfix.
(merge 14b561e768 jk/test-mktemp-leakfix later to maint).
* Update a version of action used at the GitHub Actrions CI.
* Update a version of action used at the GitHub Actions CI.
(merge cd99203f86 js/ci-github-setup-go-update later to maint).
* The "return errno = EFOO, -1" construct, which is heavily used in
@ -280,6 +294,12 @@ Fixes since v2.52
terminating newline, which has been corrected.
(merge a8227ae8d5 kt/http-backend-errors later to maint).
* "git repack --geometric" did not work with promisor packs, which
has been corrected.
* The logic that avoids reusing MIDX files with a wrong checksum was
broken, which has been corrected.
* Other code cleanup, docfix, build fix, etc.
(merge 46207a54cc qj/doc-http-bad-want-response later to maint).
(merge df90eccd93 kh/doc-commit-extra-references later to maint).
@ -311,3 +331,6 @@ Fixes since v2.52
(merge 3f051fc9c9 kh/doc-patch-id later to maint).
(merge 555c8464e5 je/doc-reset later to maint).
(merge 220f888d7e ps/t1410-cleanup later to maint).
(merge 5814b04c02 ps/config-doc-get-urlmatch-fix later to maint).
(merge 5ae594f30b sb/doc-update-ref-markup-fix later to maint).
(merge bc8556d066 ty/t1005-test-path-is-helpers later to maint).

View File

@ -332,7 +332,7 @@ recommended to migrate to the new syntax.
Replaced by `git config get --all --show-names --regexp <name-regexp>`.
--get-urlmatch <name> <URL>::
Replaced by `git config get --all --show-names --url=<URL> <name>`.
Replaced by `git config get --url=<URL> <name>`.
--get-color <name> [<default>]::
Replaced by `git config get --type=color [--default=<default>] <name>`.

View File

@ -64,6 +64,7 @@ The default mode can be configured via the `replay.refAction` configuration vari
range should have a single tip, so that it's clear to which tip the
advanced <branch> should point.
:git-replay: 1
include::rev-list-options.adoc[]
[[output]]

View File

@ -119,7 +119,7 @@ verify::
Verify <ref> against <old-oid> but do not change it. If
<old-oid> is zero or missing, the ref must not exist.
symref-create:
symref-create::
Create symbolic ref <ref> with <new-target> after verifying that
it does not exist.

View File

@ -41,10 +41,11 @@ die "BUG: No list of valid linkgit:* files given" unless @ARGV;
@ARGV = $to_check;
while (<>) {
my $line = $_;
next if $line =~ /^\s*(ifn?def|endif)::/;
while ($line =~ m/(.{,8})((git[-a-z]+|scalar)\[(\d)*\])/g) {
my $pos = pos $line;
my ($macro, $target, $page, $section) = ($1, $2, $3, $4);
if ( $macro ne "linkgit:" && $macro !~ "ifn?def::" && $macro ne "endif::" ) {
if ( $macro ne "linkgit:" ) {
report($pos, $line, $target, "linkgit: macro expected");
}
}

View File

@ -1096,7 +1096,7 @@ endif::git-rev-list[]
Overrides a previous `--no-walk`.
endif::git-shortlog[]
ifndef::git-shortlog[]
ifndef::git-shortlog,git-replay[]
Commit Formatting
~~~~~~~~~~~~~~~~~
@ -1265,4 +1265,4 @@ ifdef::git-rev-list[]
counts and print the count for equivalent commits separated
by a tab.
endif::git-rev-list[]
endif::git-shortlog[]
endif::git-shortlog,git-replay[]

View File

@ -1,6 +1,6 @@
#!/bin/sh
DEF_VER=v2.53.0-rc0
DEF_VER=v2.53.0
LF='
'

View File

@ -840,7 +840,7 @@ static int run_revert(struct add_i_state *s, const struct pathspec *ps,
if (is_initial)
oidcpy(&oid, s->r->hash_algo->empty_tree);
else {
tree = parse_tree_indirect(&oid);
tree = repo_parse_tree_indirect(s->r, &oid);
if (!tree) {
res = error(_("Could not parse HEAD^{tree}"));
goto finish_revert;

View File

@ -519,7 +519,7 @@ static void parse_treeish_arg(const char **argv,
if (ar_args->mtime_option)
archive_time = approxidate(ar_args->mtime_option);
tree = parse_tree_indirect(&oid);
tree = repo_parse_tree_indirect(the_repository, &oid);
if (!tree)
die(_("not a tree object: %s"), oid_to_hex(&oid));

View File

@ -354,7 +354,7 @@ static void init_truncated_large_filter(struct bloom_filter *filter,
static int has_entries_with_high_bit(struct repository *r, struct tree *t)
{
if (parse_tree(t))
if (repo_parse_tree(r, t))
return 1;
if (!(t->object.flags & VISITED)) {

View File

@ -1998,7 +1998,7 @@ static int fast_forward_to(struct tree *head, struct tree *remote, int reset)
struct unpack_trees_options opts;
struct tree_desc t[2];
if (parse_tree(head) || parse_tree(remote))
if (repo_parse_tree(the_repository, head) || repo_parse_tree(the_repository, remote))
return -1;
repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
@ -2038,7 +2038,7 @@ static int merge_tree(struct tree *tree)
struct unpack_trees_options opts;
struct tree_desc t[1];
if (parse_tree(tree))
if (repo_parse_tree(the_repository, tree))
return -1;
repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
@ -2071,11 +2071,11 @@ static int clean_index(const struct object_id *head, const struct object_id *rem
struct tree *head_tree, *remote_tree, *index_tree;
struct object_id index;
head_tree = parse_tree_indirect(head);
head_tree = repo_parse_tree_indirect(the_repository, head);
if (!head_tree)
return error(_("Could not parse object '%s'."), oid_to_hex(head));
remote_tree = parse_tree_indirect(remote);
remote_tree = repo_parse_tree_indirect(the_repository, remote);
if (!remote_tree)
return error(_("Could not parse object '%s'."), oid_to_hex(remote));
@ -2089,7 +2089,7 @@ static int clean_index(const struct object_id *head, const struct object_id *rem
0, NULL))
return -1;
index_tree = parse_tree_indirect(&index);
index_tree = repo_parse_tree_indirect(the_repository, &index);
if (!index_tree)
return error(_("Could not parse object '%s'."), oid_to_hex(&index));

View File

@ -726,7 +726,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,
init_checkout_metadata(&opts.meta, info->refname,
info->commit ? &info->commit->object.oid : null_oid(the_hash_algo),
NULL);
if (parse_tree(tree) < 0)
if (repo_parse_tree(the_repository, tree) < 0)
return 128;
init_tree_desc(&tree_desc, &tree->object.oid, tree->buffer, tree->size);
switch (unpack_trees(1, &tree_desc, &opts)) {
@ -805,7 +805,8 @@ static int merge_working_tree(const struct checkout_opts *opts,
if (opts->new_orphan_branch && opts->orphan_from_empty_tree) {
if (new_branch_info->commit)
BUG("'switch --orphan' should never accept a commit as starting point");
new_tree = parse_tree_indirect(the_hash_algo->empty_tree);
new_tree = repo_parse_tree_indirect(the_repository,
the_hash_algo->empty_tree);
if (!new_tree)
BUG("unable to read empty tree");
} else {
@ -843,14 +844,15 @@ static int merge_working_tree(const struct checkout_opts *opts,
old_commit_oid = old_branch_info->commit ?
&old_branch_info->commit->object.oid :
the_hash_algo->empty_tree;
tree = parse_tree_indirect(old_commit_oid);
tree = repo_parse_tree_indirect(the_repository,
old_commit_oid);
if (!tree)
die(_("unable to parse commit %s"),
oid_to_hex(old_commit_oid));
init_tree_desc(&trees[0], &tree->object.oid,
tree->buffer, tree->size);
if (parse_tree(new_tree) < 0)
if (repo_parse_tree(the_repository, new_tree) < 0)
die(NULL);
tree = new_tree;
init_tree_desc(&trees[1], &tree->object.oid,
@ -1280,7 +1282,7 @@ static void setup_new_branch_info_and_source_tree(
new_branch_info->commit = lookup_commit_reference_gently(the_repository, rev, 1);
if (!new_branch_info->commit) {
/* not a commit */
*source_tree = parse_tree_indirect(rev);
*source_tree = repo_parse_tree_indirect(the_repository, rev);
if (!*source_tree)
die(_("unable to read tree (%s)"), oid_to_hex(rev));
} else {

View File

@ -680,10 +680,10 @@ static int checkout(int submodule_progress, int filter_submodules,
opts.dst_index = the_repository->index;
init_checkout_metadata(&opts.meta, head, &oid, NULL);
tree = parse_tree_indirect(&oid);
tree = repo_parse_tree_indirect(the_repository, &oid);
if (!tree)
die(_("unable to parse commit %s"), oid_to_hex(&oid));
if (parse_tree(tree) < 0)
if (repo_parse_tree(the_repository, tree) < 0)
exit(128);
init_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size);
if (unpack_trees(1, &t, &opts) < 0)

View File

@ -327,10 +327,11 @@ static void create_base_index(const struct commit *current_head)
opts.dst_index = the_repository->index;
opts.fn = oneway_merge;
tree = parse_tree_indirect(&current_head->object.oid);
tree = repo_parse_tree_indirect(the_repository,
&current_head->object.oid);
if (!tree)
die(_("failed to unpack HEAD tree object"));
if (parse_tree(tree) < 0)
if (repo_parse_tree(the_repository, tree) < 0)
exit(128);
init_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size);
if (unpack_trees(1, &t, &opts))

View File

@ -52,7 +52,7 @@ static int stdin_diff_trees(struct tree *tree1, const char *p)
if (!isspace(*p++) || parse_oid_hex(p, &oid, &p) || *p)
return error("Need exactly two trees, separated by a space");
tree2 = lookup_tree(the_repository, &oid);
if (!tree2 || parse_tree(tree2))
if (!tree2 || repo_parse_tree(the_repository, tree2))
return -1;
printf("%s %s\n", oid_to_hex(&tree1->object.oid),
oid_to_hex(&tree2->object.oid));

View File

@ -421,7 +421,7 @@ int cmd_ls_tree(int argc,
for (i = 0; i < options.pathspec.nr; i++)
options.pathspec.items[i].nowildcard_len = options.pathspec.items[i].len;
options.pathspec.has_wildcard = 0;
tree = parse_tree_indirect(&oid);
tree = repo_parse_tree_indirect(the_repository, &oid);
if (!tree)
die("not a tree object");
/*

View File

@ -447,17 +447,20 @@ static int real_merge(struct merge_tree_options *o,
if (repo_get_oid_treeish(the_repository, merge_base, &base_oid))
die(_("could not parse as tree '%s'"), merge_base);
base_tree = parse_tree_indirect(&base_oid);
base_tree = repo_parse_tree_indirect(the_repository,
&base_oid);
if (!base_tree)
die(_("unable to read tree (%s)"), oid_to_hex(&base_oid));
if (repo_get_oid_treeish(the_repository, branch1, &head_oid))
die(_("could not parse as tree '%s'"), branch1);
parent1_tree = parse_tree_indirect(&head_oid);
parent1_tree = repo_parse_tree_indirect(the_repository,
&head_oid);
if (!parent1_tree)
die(_("unable to read tree (%s)"), oid_to_hex(&head_oid));
if (repo_get_oid_treeish(the_repository, branch2, &merge_oid))
die(_("could not parse as tree '%s'"), branch2);
parent2_tree = parse_tree_indirect(&merge_oid);
parent2_tree = repo_parse_tree_indirect(the_repository,
&merge_oid);
if (!parent2_tree)
die(_("unable to read tree (%s)"), oid_to_hex(&merge_oid));

View File

@ -756,19 +756,19 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head,
opts.trivial_merges_only = 1;
opts.merge = 1;
opts.preserve_ignored = 0; /* FIXME: !overwrite_ignore */
trees[nr_trees] = parse_tree_indirect(common);
trees[nr_trees] = repo_parse_tree_indirect(the_repository, common);
if (!trees[nr_trees++])
return -1;
trees[nr_trees] = parse_tree_indirect(head);
trees[nr_trees] = repo_parse_tree_indirect(the_repository, head);
if (!trees[nr_trees++])
return -1;
trees[nr_trees] = parse_tree_indirect(one);
trees[nr_trees] = repo_parse_tree_indirect(the_repository, one);
if (!trees[nr_trees++])
return -1;
opts.fn = threeway_merge;
cache_tree_free(&the_repository->index->cache_tree);
for (i = 0; i < nr_trees; i++) {
parse_tree(trees[i]);
repo_parse_tree(the_repository, trees[i]);
init_tree_desc(t+i, &trees[i]->object.oid,
trees[i]->buffer, trees[i]->size);
}

View File

@ -3863,8 +3863,11 @@ static void read_packs_list_from_stdin(struct rev_info *revs)
repo_for_each_pack(the_repository, p) {
const char *pack_name = pack_basename(p);
if ((item = string_list_lookup(&include_packs, pack_name)))
if ((item = string_list_lookup(&include_packs, pack_name))) {
if (exclude_promisor_objects && p->pack_promisor)
die(_("packfile %s is a promisor but --exclude-promisor-objects was given"), p->pack_name);
item->util = p;
}
if ((item = string_list_lookup(&exclude_packs, pack_name)))
item->util = p;
}
@ -3942,6 +3945,7 @@ static void read_stdin_packs(enum stdin_packs_mode mode, int rev_list_unpacked)
revs.tree_objects = 1;
revs.tag_objects = 1;
revs.ignore_missing_links = 1;
revs.exclude_promisor_objects = exclude_promisor_objects;
/* avoids adding objects in excluded packs */
ignore_packed_keep_in_core = 1;
@ -5098,9 +5102,13 @@ int cmd_pack_objects(int argc,
exclude_promisor_objects_best_effort,
"--exclude-promisor-objects-best-effort");
if (exclude_promisor_objects) {
use_internal_rev_list = 1;
fetch_if_missing = 0;
strvec_push(&rp, "--exclude-promisor-objects");
/* --stdin-packs handles promisor objects separately. */
if (!stdin_packs) {
use_internal_rev_list = 1;
strvec_push(&rp, "--exclude-promisor-objects");
}
} else if (exclude_promisor_objects_best_effort) {
use_internal_rev_list = 1;
fetch_if_missing = 0;

View File

@ -32,7 +32,7 @@ static int list_tree(struct object_id *oid)
if (nr_trees >= MAX_UNPACK_TREES)
die("I cannot read more than %d trees", MAX_UNPACK_TREES);
tree = parse_tree_indirect(oid);
tree = repo_parse_tree_indirect(the_repository, oid);
if (!tree)
return -1;
trees[nr_trees++] = tree;
@ -268,7 +268,7 @@ int cmd_read_tree(int argc,
cache_tree_free(&the_repository->index->cache_tree);
for (i = 0; i < nr_trees; i++) {
struct tree *tree = trees[i];
if (parse_tree(tree) < 0)
if (repo_parse_tree(the_repository, tree) < 0)
return 128;
init_tree_desc(t+i, &tree->object.oid, tree->buffer, tree->size);
}

View File

@ -332,6 +332,9 @@ int cmd_repack(int argc,
!(pack_everything & PACK_CRUFT))
strvec_push(&cmd.args, "--pack-loose-unreachable");
} else if (geometry.split_factor) {
pack_geometry_repack_promisors(repo, &po_args, &geometry,
&names, packtmp);
if (midx_must_contain_cruft)
strvec_push(&cmd.args, "--stdin-packs");
else

View File

@ -121,7 +121,7 @@ static int reset_index(const char *ref, const struct object_id *oid, int reset_t
goto out;
if (reset_type == MIXED || reset_type == HARD) {
tree = parse_tree_indirect(oid);
tree = repo_parse_tree_indirect(the_repository, oid);
if (!tree) {
error(_("unable to read tree (%s)"), oid_to_hex(oid));
goto out;
@ -433,7 +433,7 @@ int cmd_reset(int argc,
struct tree *tree;
if (repo_get_oid_treeish(the_repository, rev, &oid))
die(_("Failed to resolve '%s' as a valid tree."), rev);
tree = parse_tree_indirect(&oid);
tree = repo_parse_tree_indirect(the_repository, &oid);
if (!tree)
die(_("Could not parse object '%s'."), rev);
oidcpy(&oid, &tree->object.oid);

View File

@ -347,8 +347,8 @@ static int reset_tree(struct object_id *i_tree, int update, int reset)
memset(&opts, 0, sizeof(opts));
tree = parse_tree_indirect(i_tree);
if (parse_tree(tree))
tree = repo_parse_tree_indirect(the_repository, i_tree);
if (repo_parse_tree(the_repository, tree))
return -1;
init_tree_desc(t, &tree->object.oid, tree->buffer, tree->size);
@ -940,8 +940,8 @@ static void diff_include_untracked(const struct stash_info *info, struct diff_op
struct unpack_trees_options unpack_tree_opt = { 0 };
for (size_t i = 0; i < ARRAY_SIZE(oid); i++) {
tree[i] = parse_tree_indirect(oid[i]);
if (parse_tree(tree[i]) < 0)
tree[i] = repo_parse_tree_indirect(the_repository, oid[i]);
if (repo_parse_tree(the_repository, tree[i]) < 0)
die(_("failed to parse tree"));
init_tree_desc(&tree_desc[i], &tree[i]->object.oid,
tree[i]->buffer, tree[i]->size);

View File

@ -813,7 +813,7 @@ static void prime_cache_tree_rec(struct repository *r,
struct cache_tree_sub *sub;
struct tree *subtree = lookup_tree(r, &entry.oid);
if (parse_tree(subtree) < 0)
if (repo_parse_tree(the_repository, subtree) < 0)
exit(128);
sub = cache_tree_sub(it, entry.path);
sub->cache_tree = cache_tree();

View File

@ -356,6 +356,9 @@ linux-musl-meson)
;;
linux-leaks|linux-reftable-leaks)
export SANITIZE=leak
export NO_CVS_TESTS=LetsSaveSomeTime
export NO_SVN_TESTS=LetsSaveSomeTime
export NO_P4_TESTS=LetsSaveSomeTime
;;
linux-asan-ubsan)
export SANITIZE=address,undefined

View File

@ -1184,8 +1184,96 @@ static int has_valid_directory_prefix(wchar_t *wfilename)
return 1;
}
static int readlink_1(const WCHAR *wpath, BOOL fail_on_unknown_tag,
char *tmpbuf, int *plen, DWORD *ptag);
#ifndef _WINNT_H
/*
* The REPARSE_DATA_BUFFER structure is defined in the Windows DDK (in
* ntifs.h) and in MSYS1's winnt.h (which defines _WINNT_H). So define
* it ourselves if we are on MSYS2 (whose winnt.h defines _WINNT_).
*/
typedef struct _REPARSE_DATA_BUFFER {
DWORD ReparseTag;
WORD ReparseDataLength;
WORD Reserved;
#ifndef _MSC_VER
_ANONYMOUS_UNION
#endif
union {
struct {
WORD SubstituteNameOffset;
WORD SubstituteNameLength;
WORD PrintNameOffset;
WORD PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct {
WORD SubstituteNameOffset;
WORD SubstituteNameLength;
WORD PrintNameOffset;
WORD PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct {
BYTE DataBuffer[1];
} GenericReparseBuffer;
} DUMMYUNIONNAME;
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
#endif
static int read_reparse_point(const WCHAR *wpath, BOOL fail_on_unknown_tag,
char *tmpbuf, int *plen, DWORD *ptag)
{
HANDLE handle;
WCHAR *wbuf;
REPARSE_DATA_BUFFER *b = alloca(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
DWORD dummy;
/* read reparse point data */
handle = CreateFileW(wpath, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
if (handle == INVALID_HANDLE_VALUE) {
errno = err_win_to_posix(GetLastError());
return -1;
}
if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, b,
MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &dummy, NULL)) {
errno = err_win_to_posix(GetLastError());
CloseHandle(handle);
return -1;
}
CloseHandle(handle);
/* get target path for symlinks or mount points (aka 'junctions') */
switch ((*ptag = b->ReparseTag)) {
case IO_REPARSE_TAG_SYMLINK:
wbuf = (WCHAR*) (((char*) b->SymbolicLinkReparseBuffer.PathBuffer)
+ b->SymbolicLinkReparseBuffer.SubstituteNameOffset);
*(WCHAR*) (((char*) wbuf)
+ b->SymbolicLinkReparseBuffer.SubstituteNameLength) = 0;
break;
case IO_REPARSE_TAG_MOUNT_POINT:
wbuf = (WCHAR*) (((char*) b->MountPointReparseBuffer.PathBuffer)
+ b->MountPointReparseBuffer.SubstituteNameOffset);
*(WCHAR*) (((char*) wbuf)
+ b->MountPointReparseBuffer.SubstituteNameLength) = 0;
break;
default:
if (fail_on_unknown_tag) {
errno = EINVAL;
return -1;
} else {
*plen = MAX_PATH;
return 0;
}
}
if ((*plen =
xwcstoutf(tmpbuf, normalize_ntpath(wbuf), MAX_PATH)) < 0)
return -1;
return 0;
}
int mingw_lstat(const char *file_name, struct stat *buf)
{
@ -1210,8 +1298,8 @@ int mingw_lstat(const char *file_name, struct stat *buf)
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
char tmpbuf[MAX_LONG_PATH];
if (readlink_1(wfilename, FALSE, tmpbuf, &link_len,
&reparse_tag) < 0)
if (read_reparse_point(wfilename, FALSE, tmpbuf,
&link_len, &reparse_tag) < 0)
return -1;
}
buf->st_ino = 0;
@ -3338,97 +3426,6 @@ int mingw_create_symlink(struct index_state *index, const char *target, const ch
return -1;
}
#ifndef _WINNT_H
/*
* The REPARSE_DATA_BUFFER structure is defined in the Windows DDK (in
* ntifs.h) and in MSYS1's winnt.h (which defines _WINNT_H). So define
* it ourselves if we are on MSYS2 (whose winnt.h defines _WINNT_).
*/
typedef struct _REPARSE_DATA_BUFFER {
DWORD ReparseTag;
WORD ReparseDataLength;
WORD Reserved;
#ifndef _MSC_VER
_ANONYMOUS_UNION
#endif
union {
struct {
WORD SubstituteNameOffset;
WORD SubstituteNameLength;
WORD PrintNameOffset;
WORD PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct {
WORD SubstituteNameOffset;
WORD SubstituteNameLength;
WORD PrintNameOffset;
WORD PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct {
BYTE DataBuffer[1];
} GenericReparseBuffer;
} DUMMYUNIONNAME;
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
#endif
static int readlink_1(const WCHAR *wpath, BOOL fail_on_unknown_tag,
char *tmpbuf, int *plen, DWORD *ptag)
{
HANDLE handle;
WCHAR *wbuf;
REPARSE_DATA_BUFFER *b = alloca(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
DWORD dummy;
/* read reparse point data */
handle = CreateFileW(wpath, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
if (handle == INVALID_HANDLE_VALUE) {
errno = err_win_to_posix(GetLastError());
return -1;
}
if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, b,
MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &dummy, NULL)) {
errno = err_win_to_posix(GetLastError());
CloseHandle(handle);
return -1;
}
CloseHandle(handle);
/* get target path for symlinks or mount points (aka 'junctions') */
switch ((*ptag = b->ReparseTag)) {
case IO_REPARSE_TAG_SYMLINK:
wbuf = (WCHAR*) (((char*) b->SymbolicLinkReparseBuffer.PathBuffer)
+ b->SymbolicLinkReparseBuffer.SubstituteNameOffset);
*(WCHAR*) (((char*) wbuf)
+ b->SymbolicLinkReparseBuffer.SubstituteNameLength) = 0;
break;
case IO_REPARSE_TAG_MOUNT_POINT:
wbuf = (WCHAR*) (((char*) b->MountPointReparseBuffer.PathBuffer)
+ b->MountPointReparseBuffer.SubstituteNameOffset);
*(WCHAR*) (((char*) wbuf)
+ b->MountPointReparseBuffer.SubstituteNameLength) = 0;
break;
default:
if (fail_on_unknown_tag) {
errno = EINVAL;
return -1;
} else {
*plen = MAX_LONG_PATH;
return 0;
}
}
if ((*plen =
xwcstoutf(tmpbuf, normalize_ntpath(wbuf), MAX_LONG_PATH)) < 0)
return -1;
return 0;
}
int readlink(const char *path, char *buf, size_t bufsiz)
{
WCHAR wpath[MAX_LONG_PATH];
@ -3439,7 +3436,7 @@ int readlink(const char *path, char *buf, size_t bufsiz)
if (xutftowcs_long_path(wpath, path) < 0)
return -1;
if (readlink_1(wpath, TRUE, tmpbuf, &len, &tag) < 0)
if (read_reparse_point(wpath, TRUE, tmpbuf, &len, &tag) < 0)
return -1;
/*

View File

@ -2,121 +2,16 @@
@@
@@
(
// cache.h
- get_oid
+ repo_get_oid
// TODO: remove the rules below and the macros from tree.h after the
// next Git release.
- parse_tree
+ repo_parse_tree
|
- get_oid_commit
+ repo_get_oid_commit
- parse_tree_gently
+ repo_parse_tree_gently
|
- get_oid_committish
+ repo_get_oid_committish
|
- get_oid_tree
+ repo_get_oid_tree
|
- get_oid_treeish
+ repo_get_oid_treeish
|
- get_oid_blob
+ repo_get_oid_blob
|
- get_oid_mb
+ repo_get_oid_mb
|
- find_unique_abbrev
+ repo_find_unique_abbrev
|
- find_unique_abbrev_r
+ repo_find_unique_abbrev_r
|
- for_each_abbrev
+ repo_for_each_abbrev
|
- interpret_branch_name
+ repo_interpret_branch_name
|
- peel_to_type
+ repo_peel_to_type
// commit-reach.h
|
- get_merge_bases
+ repo_get_merge_bases
|
- get_merge_bases_many
+ repo_get_merge_bases_many
|
- get_merge_bases_many_dirty
+ repo_get_merge_bases_many_dirty
|
- in_merge_bases
+ repo_in_merge_bases
|
- in_merge_bases_many
+ repo_in_merge_bases_many
// commit.h
|
- parse_commit_internal
+ repo_parse_commit_internal
|
- parse_commit
+ repo_parse_commit
|
- get_commit_buffer
+ repo_get_commit_buffer
|
- unuse_commit_buffer
+ repo_unuse_commit_buffer
|
- logmsg_reencode
+ repo_logmsg_reencode
|
- get_commit_tree
+ repo_get_commit_tree
// diff.h
|
- diff_setup
+ repo_diff_setup
// odb.h
|
- read_object_file
+ repo_read_object_file
|
- has_object_file
+ repo_has_object_file
|
- has_object_file_with_flags
+ repo_has_object_file_with_flags
// pretty.h
|
- format_commit_message
+ repo_format_commit_message
// packfile.h
|
- approximate_object_count
+ repo_approximate_object_count
// promisor-remote.h
|
- promisor_remote_reinit
+ repo_promisor_remote_reinit
|
- promisor_remote_find
+ repo_promisor_remote_find
|
- has_promisor_remote
+ repo_has_promisor_remote
// refs.h
|
- dwim_ref
+ repo_dwim_ref
// rerere.h
|
- rerere
+ repo_rerere
// revision.h
|
- init_revisions
+ repo_init_revisions
- parse_tree_indirect
+ repo_parse_tree_indirect
)
(
+ the_repository,

View File

@ -325,12 +325,6 @@ check_parents () {
done
}
# Usage: get_notree REV
get_notree () {
assert test $# = 1
test -r "$cachedir/notree/$1"
}
# Usage: set_notree REV
set_notree () {
assert test $# = 1
@ -517,71 +511,6 @@ find_existing_splits () {
done || exit $?
}
# Usage: find_other_splits DIR REV UNREVS...
#
# Scan history in REV UNREVS for other `git subtree split --rejoin`
# merge commits belonging to prefixes outside of DIR. These
# "other splits" don't contribute to DIR and can be ignored.
#
# If any such rejoins are found,
#
# * emit their second-parent as an UNREV, avoiding a
# potentially costly history traversal
#
# * mark the merge commit as "notree" to ignore it
find_other_splits () {
assert test $# -ge 2
dir="${1%/}"
rev="$2"
shift 2
debug "Looking for other splits with dir != $dir..."
git log \
--grep '^git-subtree-mainline:' \
--no-patch \
--no-show-signature \
--format='hash: %H%nparents: %P%n%(trailers:key=git-subtree-dir,key=git-subtree-mainline,key=git-subtree-split)%nEND' \
"$rev" ${@:+"$@"} |
while read -r key val
do
case "$key" in
hash:)
commit_hash="${val}"
commit_parents=
subtree_dir=
subtree_mainline=
subtree_split=
;;
parents:)
commit_parents="${val}" ;;
git-subtree-dir:)
subtree_dir="${val%/}/" ;;
git-subtree-mainline:)
subtree_mainline="${val}" ;;
git-subtree-split:)
subtree_split="${val}" ;;
END)
# verify:
# * all git-subtree-* trailers are present
# * this subtree is outside of $dir
# * the first parent is the git-subtree-mainline:
# * the commit has at least two parents
if test -n "${subtree_dir}" &&
test -n "${subtree_split}" &&
test -n "${subtree_mainline}" &&
test "${subtree_dir}" = "${subtree_dir#"${dir}/"}" &&
test "${commit_parents}" != "${commit_parents#"$subtree_mainline "}" &&
rev_exists "${commit_hash}^2"
then
debug "find_other_splits excluding dir=$subtree_dir merged in ${commit_hash}"
echo "^${commit_hash}^2"
set_notree "${commit_hash}"
fi
;;
esac
done
}
# Usage: copy_commit REV TREE FLAGS_STR
copy_commit () {
assert test $# = 3
@ -856,6 +785,42 @@ ensure_valid_ref_format () {
die "fatal: '$1' does not look like a ref"
}
# Usage: should_ignore_subtree_split_commit REV
#
# Check if REV is a commit from another subtree and should be
# ignored from processing for splits
should_ignore_subtree_split_commit () {
assert test $# = 1
git show \
--no-patch \
--no-show-signature \
--format='%(trailers:key=git-subtree-dir,key=git-subtree-mainline)' \
"$1" |
(
have_mainline=
subtree_dir=
while read -r trailer val
do
case "$trailer" in
git-subtree-dir:)
subtree_dir="${val%/}" ;;
git-subtree-mainline:)
have_mainline=y ;;
esac
done
if test -n "${subtree_dir}" &&
test -z "${have_mainline}" &&
test "${subtree_dir}" != "$arg_prefix"
then
return 0
fi
return 1
)
}
# Usage: process_split_commit REV PARENTS
process_split_commit () {
assert test $# = 2
@ -1029,39 +994,31 @@ cmd_split () {
fi
unrevs="$(find_existing_splits "$dir" "$rev" "$repository")" || exit $?
(find_other_splits >"$cachedir/prune" "$dir" "$rev" $unrevs) || exit $?
# We can't restrict rev-list to only $dir here, because some of our
# parents have the $dir contents the root, and those won't match.
# (and rev-list --follow doesn't seem to solve this)
revmax="$(git rev-list \
<"$cachedir/prune" \
--topo-order \
--reverse \
--parents \
--stdin \
--count \
"$rev" \
$unrevs
)"
grl='git rev-list --topo-order --reverse --parents $rev $unrevs'
revmax=$(eval "$grl" | wc -l)
revcount=0
createcount=0
extracount=0
git rev-list \
<"$cachedir/prune" \
--topo-order \
--reverse \
--parents \
--stdin \
"$rev" \
$unrevs |
eval "$grl" |
while read rev parents
do
if get_notree "$rev"
if should_ignore_subtree_split_commit "$rev"
then
continue
fi
process_split_commit "$rev" "$parents"
parsedparents=''
for parent in $parents
do
if ! should_ignore_subtree_split_commit "$parent"
then
parsedparents="$parsedparents$parent "
fi
done
process_split_commit "$rev" "$parsedparents"
done || exit $?
latest_new=$(cache_get latest_new) || exit $?

View File

@ -411,9 +411,8 @@ test_expect_success 'split sub dir/ with --rejoin' '
git fetch ./"sub proj" HEAD &&
git subtree merge --prefix="sub dir" FETCH_HEAD &&
split_hash=$(git subtree split --prefix="sub dir" --annotate="*") &&
git subtree split --prefix="sub dir" --annotate="*" -b spl --rejoin &&
test "$(last_commit_subject)" = "Split '\''sub dir/'\'' into commit '\''$split_hash'\''" &&
test "$(git rev-list --count spl)" -eq 5
git subtree split --prefix="sub dir" --annotate="*" --rejoin &&
test "$(last_commit_subject)" = "Split '\''sub dir/'\'' into commit '\''$split_hash'\''"
)
'
@ -443,25 +442,18 @@ test_expect_success 'split with multiple subtrees' '
git -C "$test_count" subtree add --prefix=subADir FETCH_HEAD &&
git -C "$test_count" fetch ./subB HEAD &&
git -C "$test_count" subtree add --prefix=subBDir FETCH_HEAD &&
test "$(git -C "$test_count" rev-list --count main)" -eq 7 &&
test_create_commit "$test_count" subADir/main-subA1 &&
test_create_commit "$test_count" subBDir/main-subB1 &&
git -C "$test_count" subtree split --prefix=subADir \
--squash --rejoin -m "Sub A Split 1" -b a1 &&
test "$(git -C "$test_count" rev-list --count main..a1)" -eq 1 &&
--squash --rejoin -m "Sub A Split 1" &&
git -C "$test_count" subtree split --prefix=subBDir \
--squash --rejoin -m "Sub B Split 1" -b b1 &&
test "$(git -C "$test_count" rev-list --count main..b1)" -eq 1 &&
--squash --rejoin -m "Sub B Split 1" &&
test_create_commit "$test_count" subADir/main-subA2 &&
test_create_commit "$test_count" subBDir/main-subB2 &&
git -C "$test_count" subtree split --prefix=subADir \
--squash --rejoin -m "Sub A Split 2" -b a2 &&
test "$(git -C "$test_count" rev-list --count main..a2)" -eq 2 &&
test "$(git -C "$test_count" rev-list --count a1..a2)" -eq 1 &&
--squash --rejoin -m "Sub A Split 2" &&
test "$(git -C "$test_count" subtree split --prefix=subBDir \
--squash --rejoin -d -m "Sub B Split 1" -b b2 2>&1 | grep -w "\[1\]")" = "" &&
test "$(git -C "$test_count" rev-list --count main..b2)" -eq 2 &&
test "$(git -C "$test_count" rev-list --count b1..b2)" -eq 1
--squash --rejoin -d -m "Sub B Split 1" 2>&1 | grep -w "\[1\]")" = ""
'
# When subtree split-ing a directory that has other subtree
@ -485,7 +477,6 @@ do
test_path_is_file subA/file1.t &&
test_path_is_file subA/subB/file2.t &&
git subtree split --prefix=subA --branch=bsplit &&
test "$(git rev-list --count bsplit)" -eq 2 &&
git checkout bsplit &&
test_path_is_file file1.t &&
test_path_is_file subB/file2.t &&
@ -498,7 +489,6 @@ do
--prefix=subA/subB mksubtree &&
test_path_is_file subA/subB/file3.t &&
git subtree split --prefix=subA --branch=bsplit &&
test "$(git rev-list --count bsplit)" -eq 3 &&
git checkout bsplit &&
test_path_is_file file1.t &&
test_path_is_file subB/file2.t &&
@ -507,67 +497,6 @@ do
'
done
# Usually,
#
# git subtree merge -P subA --squash f00...
#
# makes two commits, in this order:
#
# 1. Squashed 'subA/' content from commit f00...
# 2. Merge commit (1) as 'subA'
#
# Commit 1 updates the subtree but does *not* rewrite paths.
# Commit 2 rewrites all trees to start with `subA/`
#
# Commit 1 either has no parents or depends only on other
# "Squashed 'subA/' content" commits.
#
# For merge without --squash, subtree produces just one commit:
# a merge commit with git-subtree trailers.
#
# In either case, if the user rebases these commits, they will
# still have the git-subtree-* trailers… but will NOT have
# the layout described above.
#
# Test that subsequent `git subtree split` are not confused by this.
test_expect_success 'split with rebased subtree commit' '
subtree_test_create_repo "$test_count" &&
(
cd "$test_count" &&
test_commit file0 &&
test_create_subtree_add \
. mksubtree subA file1 --squash &&
test_path_is_file subA/file1.t &&
mkdir subB &&
test_commit subB/bfile &&
git commit --amend -F - <<'EOF' &&
Squashed '\''subB/'\'' content from commit '\''badf00da911bbe895347b4b236f5461d55dc9877'\''
Simulate a cherry-picked or rebased subtree commit.
git-subtree-dir: subB
git-subtree-split: badf00da911bbe895347b4b236f5461d55dc9877
EOF
test_commit subA/file2 &&
test_commit subB/bfile2 &&
git commit --amend -F - <<'EOF' &&
Split '\''subB/'\'' into commit '\''badf00da911bbe895347b4b236f5461d55dc9877'\''
Simulate a cherry-picked or rebased subtree commit.
git-subtree-dir: subB
git-subtree-mainline: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
git-subtree-split: badf00da911bbe895347b4b236f5461d55dc9877
EOF
git subtree split --prefix=subA --branch=bsplit &&
git checkout bsplit &&
test_path_is_file file1.t &&
test_path_is_file file2.t &&
test "$(last_commit_subject)" = "subA/file2" &&
test "$(git rev-list --count bsplit)" -eq 2
)
'
test_expect_success 'split sub dir/ with --rejoin from scratch' '
subtree_test_create_repo "$test_count" &&
test_create_commit "$test_count" main1 &&

View File

@ -283,7 +283,7 @@ void resolve_tree_islands(struct repository *r,
root_marks = kh_value(island_marks, pos);
tree = lookup_tree(r, &ent->idx.oid);
if (!tree || parse_tree(tree) < 0)
if (!tree || repo_parse_tree(r, tree) < 0)
die(_("bad tree object %s"), oid_to_hex(&ent->idx.oid));
init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);

View File

@ -552,7 +552,7 @@ static int diff_cache(struct rev_info *revs,
struct tree_desc t;
struct unpack_trees_options opts;
tree = parse_tree_indirect(tree_oid);
tree = repo_parse_tree_indirect(the_repository, tree_oid);
if (!tree)
return error("bad tree object %s",
tree_name ? tree_name : oid_to_hex(tree_oid));

View File

@ -80,36 +80,6 @@ int core_sparse_checkout_cone;
int sparse_expect_files_outside_of_patterns;
int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
unsigned long pack_size_limit_cfg;
int max_allowed_tree_depth =
#ifdef _MSC_VER
/*
* When traversing into too-deep trees, Visual C-compiled Git seems to
* run into some internal stack overflow detection in the
* `RtlpAllocateHeap()` function that is called from within
* `git_inflate_init()`'s call tree. The following value seems to be
* low enough to avoid that by letting Git exit with an error before
* the stack overflow can occur.
*/
512;
#elif defined(GIT_WINDOWS_NATIVE) && defined(__clang__)
/*
* Similar to Visual C, it seems that clang-based builds on Windows
* have a smaller stack space available. When running out of that
* stack space, a `STATUS_STACK_OVERFLOW` is produced. When the
* Git command was run from an MSYS2 Bash, this unfortunately results
* in an exit code 127. Let's prevent that by lowering the maximal
* tree depth; Unfortunately, it seems that the exact limit differs
* for aarch64 vs x86_64, and the difference is too large to simply
* use a single limit.
*/
#if defined(__aarch64__)
1280;
#else
1152;
#endif
#else
2048;
#endif
#ifndef PROTECT_HFS_DEFAULT
#define PROTECT_HFS_DEFAULT 0
@ -575,11 +545,6 @@ int git_default_core_config(const char *var, const char *value,
return 0;
}
if (!strcmp(var, "core.maxtreedepth")) {
max_allowed_tree_depth = git_config_int(var, value, ctx->kvi);
return 0;
}
/* Add other config variables here and to Documentation/config.adoc. */
return platform_core_config(var, value, ctx, cb);
}

View File

@ -158,7 +158,6 @@ extern char *git_attributes_file;
extern int zlib_compression_level;
extern int pack_compression_level;
extern unsigned long pack_size_limit_cfg;
extern int max_allowed_tree_depth;
extern int precomposed_unicode;
extern int protect_hfs;

2
fsck.c
View File

@ -360,7 +360,7 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op
int res = 0;
const char *name;
if (parse_tree(tree))
if (repo_parse_tree(the_repository, tree))
return -1;
name = fsck_get_object_name(options, &tree->object.oid);

View File

@ -605,6 +605,36 @@ static inline bool strip_suffix(const char *str, const char *suffix,
#define DEFAULT_PACKED_GIT_LIMIT \
((1024L * 1024L) * (size_t)(sizeof(void*) >= 8 ? (32 * 1024L * 1024L) : 256))
#ifdef _MSC_VER
/*
* When traversing into too-deep trees, Visual C-compiled Git seems to
* run into some internal stack overflow detection in the
* `RtlpAllocateHeap()` function that is called from within
* `git_inflate_init()`'s call tree. The following value seems to be
* low enough to avoid that by letting Git exit with an error before
* the stack overflow can occur.
*/
#define DEFAULT_MAX_ALLOWED_TREE_DEPTH 512
#elif defined(GIT_WINDOWS_NATIVE) && defined(__clang__)
/*
* Similar to Visual C, it seems that clang-based builds on Windows
* have a smaller stack space available. When running out of that
* stack space, a `STATUS_STACK_OVERFLOW` is produced. When the
* Git command was run from an MSYS2 Bash, this unfortunately results
* in an exit code 127. Let's prevent that by lowering the maximal
* tree depth; Unfortunately, it seems that the exact limit differs
* for aarch64 vs x86_64, and the difference is too large to simply
* use a single limit.
*/
#if defined(__aarch64__)
#define DEFAULT_MAX_ALLOWED_TREE_DEPTH 1280
#else
#define DEFAULT_MAX_ALLOWED_TREE_DEPTH 1152
#endif
#else
#define DEFAULT_MAX_ALLOWED_TREE_DEPTH 2048
#endif
int git_open_cloexec(const char *name, int flags);
#define git_open(name) git_open_cloexec(name, O_RDONLY)

View File

@ -1,7 +1,7 @@
* whitespace=indent-with-non-tab,trailing-space,space-before-tab,tabwidth=4
* encoding=US-ASCII
git-gui.sh encoding=UTF-8
/po/*.po encoding=UTF-8
*.po encoding=UTF-8
/GIT-VERSION-GEN eol=lf
Makefile whitespace=!indent,trail,space
meson.build whitespace=space

View File

@ -1,7 +1,7 @@
# Bulgarian translation of git-gui po-file.
# Copyright (C) 2012, 2013, 2014, 2015, 2016, 2024, 2025 Alexander Shopov <ash@kambanaria.org>.
# Copyright (C) 2012, 2013, 2014, 2015, 2016, 2024, 2025, 2026 Alexander Shopov <ash@kambanaria.org>.
# This file is distributed under the same license as the git package.
# Alexander Shopov <ash@kambanaria.org>, 2012, 2013, 2014, 2015, 2016, 2024, 2025.
# Alexander Shopov <ash@kambanaria.org>, 2012, 2013, 2014, 2015, 2016, 2024, 2025, 2026.
#
#
msgid ""
@ -9,7 +9,7 @@ msgstr ""
"Project-Id-Version: git-gui master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-07-22 17:37+0200\n"
"PO-Revision-Date: 2025-07-28 11:56+0200\n"
"PO-Revision-Date: 2026-01-19 10:12+0100\n"
"Last-Translator: Alexander Shopov <ash@kambanaria.org>\n"
"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
"Language: bg\n"
@ -230,7 +230,7 @@ msgid "Delete..."
msgstr "Изтриване…"
msgid "Reset..."
msgstr "Отмяна на промените…"
msgstr "Отмяна на промѐните…"
msgid "Done"
msgstr "Готово"
@ -322,7 +322,7 @@ msgid "Staged Changes (Will Commit)"
msgstr "Промени в индекса (за подаване)"
msgid "Stage Changed"
msgstr "Индексът е променен"
msgstr "Добавяне към индекса"
msgid "Push"
msgstr "Изтласкване"
@ -394,7 +394,7 @@ msgid "Revert To Base"
msgstr "Връщане към родителската версия"
msgid "Visualize These Changes In The Submodule"
msgstr "Визуализиране на промените в подмодула"
msgstr "Визуализиране на промѐните в подмодула"
msgid "Visualize Current Branch History In The Submodule"
msgstr "Визуализация на историята на текущия клон в историята за подмодула"
@ -535,7 +535,7 @@ msgid "Options"
msgstr "Опции"
msgid "Fetch Tracking Branch"
msgstr "Изтегляне на промените от следения клон"
msgstr "Изтегляне на промѐните от следения клон"
msgid "Detach From Local Branch"
msgstr "Изтриване от локалния клон"
@ -602,14 +602,14 @@ msgid "Local Branches"
msgstr "Локални клони"
msgid "Delete Only If Merged Into"
msgstr "Изтриване, само ако промените са слети и другаде"
msgstr "Изтриване, само ако промѐните са слети и другаде"
msgid "Always (Do not perform merge checks)"
msgstr "Винаги (без проверка за сливане)"
#, tcl-format
msgid "The following branches are not completely merged into %s:"
msgstr "Не всички промени в клоните са слети в „%s“:"
msgstr "Не всички промѐни в клоните са слети в „%s“:"
msgid ""
"Recovering deleted branches is difficult.\n"
@ -1035,10 +1035,37 @@ msgid ""
"\n"
"You must stage at least 1 file before you can commit.\n"
msgstr ""
"Няма промени за подаване.\n"
"Няма промѐни за подаване.\n"
"\n"
"Трябва да добавите поне един файл към индекса, за да подадете.\n"
msgid "Calling pre-commit hook..."
msgstr "Изпълняване на куката преди подаване…"
msgid "Commit declined by pre-commit hook."
msgstr "Подаването е отхвърлено от куката преди подаване."
msgid ""
"You are about to commit on a detached head. This is a potentially dangerous "
"thing to do because if you switch to another branch you will lose your "
"changes and it can be difficult to retrieve them later from the reflog. You "
"should probably cancel this commit and create a new branch to continue.\n"
" \n"
" Do you really want to proceed with your Commit?"
msgstr ""
"Ще подадете към несвързан, отделѐн указател „HEAD“. Това е опасно, защото "
"при преминаването към клон ще загубите промѐните си, като единственият начин "
"да ги върнете ще е чрез журнала на указателите (reflog). Най-вероятно трябва "
"да не правите това подаване, а да създадете нов клон, преди да продължите.\n"
" \n"
"Сигурни ли сте, че искате да извършите текущото подаване?"
msgid "Calling commit-msg hook..."
msgstr "Изпълняване на куката за съобщението при подаване…"
msgid "Commit declined by commit-msg hook."
msgstr "Подаването е отхвърлено от куката за съобщението при подаване."
msgid ""
"Please supply a commit message.\n"
"\n"
@ -1056,35 +1083,8 @@ msgstr ""
"● Втори ред: празен.\n"
"● Останалите редове: опишете защо се налага тази промяна.\n"
msgid "Calling pre-commit hook..."
msgstr "Изпълняване на куката преди подаване…"
msgid "Commit declined by pre-commit hook."
msgstr "Подаването е отхвърлено от куката преди подаване."
msgid ""
"You are about to commit on a detached head. This is a potentially dangerous "
"thing to do because if you switch to another branch you will lose your "
"changes and it can be difficult to retrieve them later from the reflog. You "
"should probably cancel this commit and create a new branch to continue.\n"
" \n"
" Do you really want to proceed with your Commit?"
msgstr ""
"Ще подадете към несвързан, отделѐн указател „HEAD“. Това е опасно, защото "
"при преминаването към клон ще загубите промените си, като единственият начин "
"да ги върнете ще е чрез журнала на указателите (reflog). Най-вероятно трябва "
"да не правите това подаване, а да създадете нов клон, преди да продължите.\n"
" \n"
"Сигурни ли сте, че искате да извършите текущото подаване?"
msgid "Calling commit-msg hook..."
msgstr "Изпълняване на куката за съобщението при подаване…"
msgid "Commit declined by commit-msg hook."
msgstr "Подаването е отхвърлено от куката за съобщението при подаване."
msgid "Committing changes..."
msgstr "Подаване на промените…"
msgstr "Подаване на промѐните…"
msgid "write-tree failed:"
msgstr "неуспешно запазване на дървото (write-tree):"
@ -1103,7 +1103,7 @@ msgid ""
"\n"
"A rescan will be automatically started now.\n"
msgstr ""
"Няма промени за подаване.\n"
"Няма промѐни за подаване.\n"
"\n"
"В това подаване не са променяни никакви файлове, а и не е подаване със "
"сливане.\n"
@ -1111,7 +1111,7 @@ msgstr ""
"Автоматично ще започне нова проверка.\n"
msgid "No changes to commit."
msgstr "Няма промени за подаване."
msgstr "Няма промѐни за подаване."
msgid "commit-tree failed:"
msgstr "неуспешно подаване на дървото (commit-tree):"
@ -1191,7 +1191,7 @@ msgid ""
"* No differences detected; stage the file to de-list it from Unstaged "
"Changes.\n"
msgstr ""
"● Няма разлики. Добавете файла към индекса, за да се извади от промените "
"● Няма разлики. Добавете файла към индекса, за да се извади от промѐните "
"извън индекса.\n"
msgid "* Click to find other files that may have the same state.\n"
@ -1350,15 +1350,15 @@ msgstr "Добавяне на всички променени файлове"
#, tcl-format
msgid "Revert changes in file %s?"
msgstr "Да се махнат ли промените във файла „%s“?"
msgstr "Да се махнат ли промѐните във файла „%s“?"
#, tcl-format
msgid "Revert changes in these %i files?"
msgstr "Да се махнат ли промените в тези %i файла?"
msgstr "Да се махнат ли промѐните в тези %i файла?"
msgid "Any unstaged changes will be permanently lost by the revert."
msgstr ""
"Всички промени, които не са били добавени в индекса, ще се загубят "
"Всички промѐни, които не са били добавени в индекса, ще се загубят "
"безвъзвратно."
msgid "Do Nothing"
@ -1393,11 +1393,11 @@ msgid "%d of the %d selected files could not be deleted."
msgstr "%d от избраните %d файла не бяха изтрити."
msgid "Reverting selected files"
msgstr "Махане на промените в избраните файлове"
msgstr "Махане на промѐните в избраните файлове"
#, tcl-format
msgid "Reverting %s"
msgstr "Махане на промените в „%s“"
msgstr "Махане на промѐните в „%s“"
msgid "Goto Line:"
msgstr "Към ред:"
@ -1507,7 +1507,7 @@ msgid ""
msgstr ""
"Да се преустанови ли сливането?\n"
"\n"
"В такъв случай ●ВСИЧКИ● неподадени промени ще се загубят безвъзвратно.\n"
"В такъв случай ●ВСИЧКИ● неподадени промѐни ще се загубят безвъзвратно.\n"
"\n"
"Наистина ли да се преустанови сливането?"
@ -1518,17 +1518,17 @@ msgid ""
"\n"
"Continue with resetting the current changes?"
msgstr ""
"Да се занулят ли промените?\n"
"Да се занулят ли промѐните?\n"
"\n"
"В такъв случай ●ВСИЧКИ● неподадени промени ще се загубят безвъзвратно.\n"
"В такъв случай ●ВСИЧКИ● неподадени промѐни ще се загубят безвъзвратно.\n"
"\n"
"Наистина ли да се занулят промените?"
"Наистина ли да се занулят промѐните?"
msgid "Aborting"
msgstr "Преустановяване"
msgid "files reset"
msgstr "файла със занулени промени"
msgstr "файла със занулени промѐни"
msgid "Abort failed."
msgstr "Неуспешно преустановяване."
@ -1766,7 +1766,7 @@ msgid "Fetch Immediately"
msgstr "Незабавно доставяне"
msgid "Initialize Remote Repository and Push"
msgstr "Инициализиране на отдалеченото хранилище и изтласкване на промените"
msgstr "Инициализиране на отдалеченото хранилище и изтласкване на промѐните"
msgid "Do Nothing Else Now"
msgstr "Да не се прави нищо"
@ -1896,6 +1896,10 @@ msgstr "Главни/Малки"
msgid "%s (%s): Create Desktop Icon"
msgstr "%s (%s): Добавяне на икона на работния плот"
#, tcl-format
msgid "Replace existing shortcut: %s?"
msgstr "Да се замени ли съществуващата клавишна комбинация: %s?"
msgid "Cannot write shortcut:"
msgstr "Клавишната комбинация не може да се запази:"
@ -2081,7 +2085,7 @@ msgstr "Командата върна грешка: %s"
#, tcl-format
msgid "Fetching new changes from %s"
msgstr "Доставяне на промените от „%s“"
msgstr "Доставяне на промѐните от „%s“"
#, tcl-format
msgid "remote prune %s"
@ -2095,7 +2099,7 @@ msgid "fetch all remotes"
msgstr "доставяне от всички отдалечени"
msgid "Fetching new changes from all remotes"
msgstr "Доставяне на промените от всички отдалечени хранилища"
msgstr "Доставяне на промѐните от всички отдалечени хранилища"
msgid "remote prune all remotes"
msgstr "окастряне на следящите изтрити"
@ -2107,7 +2111,7 @@ msgstr ""
#, tcl-format
msgid "Pushing changes to %s"
msgstr "Изтласкване на промените към „%s“"
msgstr "Изтласкване на промѐните към „%s“"
#, tcl-format
msgid "Mirroring to %s"
@ -2131,7 +2135,7 @@ msgstr "Настройки при пренасянето"
msgid "Force overwrite existing branch (may discard changes)"
msgstr ""
"Изрично презаписване на съществуващ клон (някои промени може да се загубят)"
"Изрично презаписване на съществуващ клон (някои промѐни може да се загубят)"
msgid "Use thin pack (for slow network connections)"
msgstr "Максимална компресия (за бавни мрежови връзки)"

View File

@ -1,14 +1,14 @@
# Bulgarian translation of git-gui-glossary po-file.
# Copyright (C) 2012, 2013, 2014 Alexander Shopov <ash@kambanaria.org>.
# Copyright (C) 2012, 2013, 2014, 2026 Alexander Shopov <ash@kambanaria.org>.
# This file is distributed under the same license as the git package.
# Alexander Shopov <ash@kambanaria.org>, 2012, 2013, 2014.
# Alexander Shopov <ash@kambanaria.org>, 2012, 2013, 2014, 2026.
#
#
msgid ""
msgstr ""
"Project-Id-Version: git-gui-glossary master\n"
"POT-Creation-Date: 2014-01-13 21:39+0200\n"
"PO-Revision-Date: 2014-01-13 21:39+0200\n"
"POT-Creation-Date: 2020-01-26 22:26+0100\n"
"PO-Revision-Date: 2026-01-24 11:18+0100\n"
"Last-Translator: Alexander Shopov <ash@kambanaria.org>\n"
"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
"Language: bg\n"
@ -20,23 +20,55 @@ msgstr ""
#. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)"
msgid ""
"English Term (Dear translator: This file will never be visible to the user!)"
msgstr "Термин"
msgstr "Български превод на термина"
#. "prematurely stop and abandon an operation"
msgid "abort"
msgstr "преустановявам"
#. ""
msgid "amend"
msgstr "поправям"
#. "a commit that succeeds the current one in git's graph of commits (not necessarily directly)"
msgid "ancestor"
msgstr "предшественик"
#. ""
msgid "annotate"
msgstr "анотирам"
#. "The person who initially created (authored) a commit"
msgid "author"
msgstr "автор"
#. "a repository with only .git directory, without working directory"
msgid "bare repository"
msgstr "голо хранилище"
#. "a parent version of the current file"
msgid "base"
msgstr "базова версия"
#. ""
msgid "bisect"
msgstr "двоично търсене"
#. "get the authors responsible for each line in a file"
msgid "blame"
msgstr "анотирам/анотиране"
#. ""
msgid "blob"
msgstr "обект-BLOB"
#. "A 'branch' is an active line of development."
msgid "branch [noun]"
msgstr "клон, разклонение [съществително]"
msgstr "клон [съществително]"
#. ""
msgid "branch [verb]"
msgstr "разклонявам [глагол]"
msgstr "създавам клон [глагол]"
#. ""
msgid "checkout [noun]"
@ -46,6 +78,18 @@ msgstr "изтегляне [съществително]"
msgid "checkout [verb]"
msgstr "изтегляне [глагол]"
#. "to select and apply a single commit to the current HEAD without merging"
msgid "cherry-pick"
msgstr "отбирам"
#. "a commit that directly succeeds the current one in git's graph of commits"
msgid "child commit"
msgstr "подаване-наследник"
#. "clean the state of the git repository, often after manually stopped operation"
msgid "cleanup"
msgstr "зачиствам"
#. ""
msgid "clone [verb]"
msgstr "клонирам [глагол]"
@ -56,180 +100,80 @@ msgstr "подаване [съществително]"
#. "The action of storing a new snapshot of the project's state in the git history."
msgid "commit [verb]"
msgstr "подавам [съществително]"
msgstr "подавам [глагол]"
#. "a message that gets attached with any commit"
msgid "commit message"
msgstr "съобщение при подаване"
#. "The person who committed a commit (to the current branch), which might be different than the author."
msgid "committer"
msgstr "подаващ"
#. "a commit that precedes the current one in git's graph of commits (not necessarily directly)"
msgid "descendant"
msgstr "наследник"
#. "checkout of a revision rather than some head"
msgid "detached HEAD"
msgstr "несвързан указател „HEAD“"
#. "checkout of a revision rather than some head"
msgid "detached checkout"
msgstr "несвързано изтегляне"
#. ""
msgid "diff [noun]"
msgstr "разлика/промени [съществително]"
msgstr "разлика/промѐни [съществително]"
#. ""
msgid "diff [verb]"
msgstr "изчислявам разлика/промени [глагол]"
msgstr "изчислявам разлика/промѐни [глагол]"
#. "A fast-forward is a special type of merge where you have a revision and you are merging another branch's changes that happen to be a descendant of what you have."
msgid "fast forward merge"
msgstr "превъртащо/директно/тривиално сливане"
#. ""
msgid "directory"
msgstr "директория"
#. "A fast-forward merge is a special type of merge where you have a revision and you are merging another branch's changes that happen to be a descendant of what you have."
msgid "fast-forward"
msgstr "превъртане"
#. "Fetching a branch means to get the branch's head from a remote repository, to find out which objects are missing from the local object database, and to get them, too."
msgid "fetch"
msgstr "доставяне"
#. "any merge strategy that works on a file by file basis"
msgid "file level merging"
msgstr "пофайлово сливане"
#. ""
msgid "file"
msgstr "файл"
#. "the last revision in a branch"
msgid "head"
msgstr "връх (на клон, разработка)"
#. "script that gets executed automatically on some event"
msgid "hook"
msgstr "кука"
#. "One context of consecutive lines in a whole patch, which consists of many such hunks"
msgid "hunk"
msgstr "парче"
#. "A collection of files. The index is a stored version of your working tree."
msgid "index (in git-gui: staging area)"
msgstr "скеле/индекс/изба"
#. "A successful merge results in the creation of a new commit representing the result of the merge."
msgid "merge [noun]"
msgstr "сливане/обединяване [съществително]"
#. "To bring the contents of another branch into the current branch."
msgid "merge [verb]"
msgstr "сливам/обединявам [глагол]"
#. ""
msgid "message"
msgstr "съобщение"
#. "Deletes all stale tracking branches under <name>. These stale branches have already been removed from the remote repository referenced by <name>, but are still locally available in 'remotes/<name>'."
msgid "prune"
msgstr "окастрям"
#. "Pulling a branch means to fetch it and merge it."
msgid "pull"
msgstr "издърпвам"
#. "Pushing a branch means to get the branch's head ref from a remote repository, and ... (well, can someone please explain it for mere mortals?)"
msgid "push"
msgstr "изтласквам"
#. ""
msgid "redo"
msgstr "повтарям/правя наново"
#. "An other repository ('remote'). One might have a set of remotes whose branches one tracks."
msgid "remote"
msgstr "отдалечено хранилище"
#. "A collection of refs (?) together with an object database containing all objects which are reachable from the refs... (oops, you've lost me here. Again, please an explanation for mere mortals?)"
msgid "repository"
msgstr "хранилище"
#. ""
msgid "reset"
msgstr "занулявам/отменям"
#. ""
msgid "revert"
msgstr "връщам/отменям"
#. "A particular state of files and directories which was stored in the object database."
msgid "revision"
msgstr "версия"
#. ""
msgid "sign off"
msgstr "подписвам"
#. ""
msgid "staging area"
msgstr "скеле/индекс/изба"
#. ""
msgid "status"
msgstr "състояние"
#. "A ref pointing to a tag or commit object"
msgid "tag [noun]"
msgstr "етикет [съществително]"
#. ""
msgid "tag [verb]"
msgstr "задавам етикет [глагол]"
#. "A regular git branch that is used to follow changes from another repository."
msgid "tracking branch"
msgstr "следящ клон"
#. ""
msgid "undo"
msgstr "отменям"
#. ""
msgid "update"
msgstr "обновявам"
#. ""
msgid "verify"
msgstr "проверявам"
#. "The tree of actual checked out files."
msgid "working copy, working tree"
msgstr "работно копие/работно дърво"
#. "a commit that succeeds the current one in git's graph of commits (not necessarily directly)"
msgid "ancestor"
msgstr "предшественик"
#. "prematurely stop and abandon an operation"
msgid "abort"
msgstr "преустановявам"
#. "a repository with only .git directory, without working directory"
msgid "bare repository"
msgstr "голо хранилище"
#. "a parent version of the current file"
msgid "base"
msgstr "родителска версия"
#. "get the authors responsible for each line in a file"
msgid "blame"
msgstr "анотирам/анотиране"
#. "to select and apply a single commit without merging"
msgid "cherry-pick"
msgstr "отбирам"
#. "a commit that directly succeeds the current one in git's graph of commits"
msgid "child"
msgstr "дете"
#. "clean the state of the git repository, often after manually stopped operation"
msgid "cleanup"
msgstr "зачиствам"
#. "a message that gets attached with any commit"
msgid "commit message"
msgstr "съобщение при подаване"
#. "a commit that precedes the current one in git's graph of commits (not necessarily directly)"
msgid "descendant"
msgstr "наследник"
#. "checkout of a revision rather than a some head"
msgid "detached checkout"
msgstr "несвързано изтегляне"
#. "any merge strategy that works on a file by file basis"
msgid "file level merging"
msgstr "пофайлово сливане"
#. "the last revision in a branch"
msgid "head"
msgstr "глава/връх (на клон, разработка)"
#. "script that gets executed automatically on some event"
msgid "hook"
msgstr "кука/автоматичен скрипт"
msgstr "индекс"
#. "the first checkout during a clone operation"
msgid "initial checkout"
msgstr "първоначално изтегляне"
#. "The very first commit in a repository"
msgid "initial commit"
msgstr "първоначално подаване"
#. "a branch that resides in the local git repository"
msgid "local branch"
msgstr "локален клон"
@ -242,26 +186,112 @@ msgstr "непакетиран обект"
msgid "master branch"
msgstr "основен клон"
#. "A successful merge results in the creation of a new commit representing the result of the merge."
msgid "merge [noun]"
msgstr "сливане [съществително]"
#. "To bring the contents of another branch into the current branch."
msgid "merge [verb]"
msgstr "сливам [глагол]"
#. ""
msgid "message"
msgstr "съобщение"
#. "a remote called by convention 'origin' that the current git repository has been cloned from"
msgid "origin"
msgstr "хранилище-източник"
#. ""
msgid "orphan commit"
msgstr "неродено подаване"
#. ""
msgid "orphan reference"
msgstr "неродѐн указател"
#. "a file containing many git objects packed together"
msgid "pack [noun]"
msgstr "етикет"
msgstr "пакет [глагол]"
#. "the process of creating a pack file"
msgid "pack [verb]"
msgstr "пакетирам [глагол]"
#. "a Git object part of some pack"
msgid "packed object"
msgstr "пакетиран обект"
#. "a commit that directly precedes the current one in git's graph of commits"
msgid "parent"
msgstr "родител"
msgid "parent commit"
msgstr "подаване-родител"
msgid "patch"
msgstr "кръпка"
#. "The path to a file"
msgid "path"
msgstr "път"
#. "Delete all stale tracking branches under <name>. These stale branches have already been removed from the remote repository referenced by <name>, but are still locally available in 'remotes/<name>'."
msgid "prune"
msgstr "окастрям"
#. "Pulling a branch means to fetch it and merge it."
msgid "pull"
msgstr "издърпвам"
#. "Pushing a branch means to get the branch's head ref from a remote repository, and ... (well, can someone please explain it for mere mortals?)"
msgid "push"
msgstr "изтласквам"
#. "The process of rebasing one set of commits on top of another branch's head"
msgid "rebase [noun]"
msgstr "пребазиране [съществително]"
#. "Re-apply one set of commits on top of another branch's head. Contrary to merge."
msgid "rebase [verb]"
msgstr "пребазирам [глагол]"
#. ""
msgid "redo"
msgstr "повтарям/правя наново"
#. ""
msgid "reference"
msgstr "указател"
#. "the log file containing all states of the HEAD reference (in other words past pristine states of the working copy)"
msgid "reflog"
msgstr "журнал на указателите"
msgid "refmap"
msgstr "карта с указатели"
#. ""
msgid "refspec"
msgstr "указател на версия"
#. "The adjective for anything which is outside of the current (local) repository"
msgid "remote [adj]"
msgstr "отдалечен [прилагателно]"
#. "A branch in any other ('remote') repository"
msgid "remote branch"
msgstr "отдалечен клон"
#. "An other repository ('remote'). One might have a set of remotes whose branches one tracks."
msgid "remote repository"
msgstr "отдалечено/насрещно хранилище"
#. "A collection of refs (?) together with an object database containing all objects which are reachable from the refs... (oops, you've lost me here. Again, please an explanation for mere mortals?)"
msgid "repository"
msgstr "хранилище"
#. ""
msgid "reset"
msgstr "занулявам"
#. "decide which changes from alternative versions of a file should persist in Git"
msgid "resolve (a conflict)"
msgstr "коригирам (конфликт)"
@ -270,18 +300,102 @@ msgstr "коригирам (конфликт)"
msgid "revert changes"
msgstr "връщане на оригинала"
#. ""
msgid "revert"
msgstr "отменям"
#. "expression that signifies a revision in git"
msgid "revision expression"
msgstr "израз за версия"
#. "A particular state of files and directories which was stored in the object database."
msgid "revision"
msgstr "версия"
#. ""
msgid "sign off"
msgstr "подписвам"
#. "see: staging area. In some areas of git this is called 'index'."
msgid "stage [noun], index"
msgstr "индекс [съществително]"
#. "add some content of files and directories to the staging area in preparation for a commit"
msgid "stage/unstage"
msgstr "(добавяне) към скелето за подаване/изваждане от скелето за подаване"
msgid "stage [verb]"
msgstr "добавям в индекса [глагол]"
#. "The place where changes from files are marked to be included for the next commit. In some areas of git this is called 'index'."
msgid "staging area"
msgstr "индекс"
#. "The place (stack) where changes can be temporarily saved without committing"
msgid "stash [noun]"
msgstr "скатано [съществително]"
#. "temporarily save changes in a stack without committing"
msgid "stash"
msgstr "скатавам промени"
msgid "stash [verb]"
msgstr "скатано [глагол]"
#. ""
msgid "status"
msgstr "състояние"
#. ""
msgid "submodule"
msgstr "подмодул"
#. "A ref pointing to some commit object. In other words: A label on a specific commit."
msgid "tag [noun]"
msgstr "етикет [съществително]"
#. "The process of creating a tag at a specific commit object"
msgid "tag [verb]"
msgstr "задавам етикет [глагол]"
#. "The person who created a tag"
msgid "tagger"
msgstr "етикиращ"
#. "file whose content is tracked/not tracked by git"
msgid "tracked/untracked"
msgstr "следен/неследен"
#. "A regular git branch that is used to follow changes from another repository."
msgid "tracking branch"
msgstr "следящ клон"
#. ""
msgid "trailer"
msgstr "епилог"
#. "1. tree object, 2. directory tree"
msgid "tree"
msgstr "обект-дърво/дърво"
#. ""
msgid "undo"
msgstr "отменям"
#. "Remove content of files from the staging area again so that it will not be part of the next commit"
msgid "unstage"
msgstr "изваждено от индекса"
#. "Retrieving the temporarily saved changes back again from the stash"
msgid "unstash [verb]"
msgstr "изваждам от индекса [глагол]"
#. ""
msgid "update"
msgstr "обновявам"
#. ""
msgid "upstream branch"
msgstr "следен клон"
#. ""
msgid "verify"
msgstr "проверявам"
#. "The tree of actual checked out files."
msgid "working directory, working copy, working tree"
msgstr "работна директория, работно копие, работно дърво"

3
help.c
View File

@ -799,6 +799,9 @@ void get_version_info(struct strbuf *buf, int show_build_options)
if (fsmonitor_ipc__is_supported())
strbuf_addstr(buf, "feature: fsmonitor--daemon\n");
#if !defined NO_GETTEXT
strbuf_addstr(buf, "gettext: enabled\n");
#endif
#if defined LIBCURL_VERSION
strbuf_addf(buf, "libcurl: %s\n", LIBCURL_VERSION);
#endif

View File

@ -1311,7 +1311,7 @@ static struct object_list **process_tree(struct tree *tree,
if (obj->flags & (UNINTERESTING | SEEN))
return p;
if (parse_tree(tree) < 0)
if (repo_parse_tree(the_repository, tree) < 0)
die("bad tree object %s", oid_to_hex(&obj->oid));
obj->flags |= SEEN;

View File

@ -167,10 +167,10 @@ static void process_tree(struct traversal_context *ctx,
!revs->include_check_obj(&tree->object, revs->include_check_data))
return;
if (ctx->depth > max_allowed_tree_depth)
if (ctx->depth > revs->repo->settings.max_allowed_tree_depth)
die("exceeded maximum allowed tree depth");
failed_parse = parse_tree_gently(tree, 1);
failed_parse = repo_parse_tree_gently(the_repository, tree, 1);
if (failed_parse) {
if (revs->ignore_missing_links)
return;

View File

@ -1732,9 +1732,9 @@ static int collect_merge_info(struct merge_options *opt,
info.data = opt;
info.show_all_errors = 1;
if (parse_tree(merge_base) < 0 ||
parse_tree(side1) < 0 ||
parse_tree(side2) < 0)
if (repo_parse_tree(the_repository, merge_base) < 0 ||
repo_parse_tree(the_repository, side1) < 0 ||
repo_parse_tree(the_repository, side2) < 0)
return -1;
init_tree_desc(t + 0, &merge_base->object.oid,
merge_base->buffer, merge_base->size);
@ -4619,10 +4619,10 @@ static int checkout(struct merge_options *opt,
unpack_opts.verbose_update = (opt->verbosity > 2);
unpack_opts.fn = twoway_merge;
unpack_opts.preserve_ignored = 0; /* FIXME: !opts->overwrite_ignore */
if (parse_tree(prev) < 0)
if (repo_parse_tree(the_repository, prev) < 0)
return -1;
init_tree_desc(&trees[0], &prev->object.oid, prev->buffer, prev->size);
if (parse_tree(next) < 0)
if (repo_parse_tree(the_repository, next) < 0)
return -1;
init_tree_desc(&trees[1], &next->object.oid, next->buffer, next->size);
@ -5280,7 +5280,8 @@ redo:
if (result->clean >= 0) {
if (!opt->mergeability_only) {
result->tree = parse_tree_indirect(&working_tree_oid);
result->tree = repo_parse_tree_indirect(the_repository,
&working_tree_oid);
if (!result->tree)
die(_("unable to read tree (%s)"),
oid_to_hex(&working_tree_oid));

View File

@ -68,18 +68,18 @@ int checkout_fast_forward(struct repository *r,
memset(&trees, 0, sizeof(trees));
memset(&t, 0, sizeof(t));
trees[nr_trees] = parse_tree_indirect(head);
trees[nr_trees] = repo_parse_tree_indirect(the_repository, head);
if (!trees[nr_trees++]) {
rollback_lock_file(&lock_file);
return -1;
}
trees[nr_trees] = parse_tree_indirect(remote);
trees[nr_trees] = repo_parse_tree_indirect(the_repository, remote);
if (!trees[nr_trees++]) {
rollback_lock_file(&lock_file);
return -1;
}
for (i = 0; i < nr_trees; i++) {
if (parse_tree(trees[i]) < 0) {
if (repo_parse_tree(the_repository, trees[i]) < 0) {
rollback_lock_file(&lock_file);
return -1;
}

View File

@ -1011,6 +1011,20 @@ static bool midx_needs_update(struct multi_pack_index *midx, struct write_midx_c
struct strbuf buf = STRBUF_INIT;
bool needed = true;
/*
* Ensure that we have a valid checksum before consulting the
* exisiting MIDX in order to determine if we can avoid an
* update.
*
* This is necessary because the given MIDX is loaded directly
* from the object store (because we still compare our proposed
* update to any on-disk MIDX regardless of whether or not we
* have assigned "ctx.m") and is thus not guaranteed to have a
* valid checksum.
*/
if (!midx_checksum_valid(midx))
goto out;
/*
* Ignore incremental updates for now. The assumption is that any
* incremental update would be either empty (in which case we will bail

View File

@ -474,7 +474,7 @@ static int fill_bitmap_tree(struct bitmap_writer *writer,
return 0;
bitmap_set(bitmap, pos);
if (parse_tree(tree) < 0)
if (repo_parse_tree(writer->repo, tree) < 0)
die("unable to load tree object %s",
oid_to_hex(&tree->object.oid));
init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);

View File

@ -137,7 +137,7 @@ static int add_tree_entries(struct path_walk_context *ctx,
error(_("failed to walk children of tree %s: not found"),
oid_to_hex(oid));
return -1;
} else if (parse_tree_gently(tree, 1)) {
} else if (repo_parse_tree_gently(ctx->repo, tree, 1)) {
error("bad tree object %s", oid_to_hex(oid));
return -1;
}

576
po/bg.po

File diff suppressed because it is too large Load Diff

534
po/fr.po
View File

@ -87,8 +87,8 @@ msgid ""
msgstr ""
"Project-Id-Version: git\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
"POT-Creation-Date: 2025-11-07 21:01+0100\n"
"PO-Revision-Date: 2025-11-09 14:56+0100\n"
"POT-Creation-Date: 2026-01-22 23:57+0000\n"
"PO-Revision-Date: 2026-01-28 19:43+0100\n"
"Last-Translator: Cédric Malard <c.malard-git@valdun.net>\n"
"Language-Team: Jean-Noël Avila <jn.avila@free.fr>\n"
"Language: fr\n"
@ -1851,8 +1851,8 @@ msgstr ""
msgid "'%s' is not a valid branch name"
msgstr "'%s' n'est pas un nom de branche valide"
msgid "See `man git check-ref-format`"
msgstr "Voir `man git check-ref-format`"
msgid "See 'git help check-ref-format'"
msgstr "Voir 'git help check-ref-format'"
#, c-format
msgid "a branch named '%s' already exists"
@ -2765,6 +2765,17 @@ msgstr "couleur attendue : %s"
msgid "must end with a color"
msgstr "doit finir avec une couleur"
#, c-format
msgid "unknown value for config '%s': %s"
msgstr "valeur inconnue pour la config '%s' : %s"
msgid ""
"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
"\"histogram\""
msgstr ""
"l'option diff-algorithm accept \"myers\", \"minimal\", \"patience\" et "
"\"histogram\""
#, c-format
msgid "cannot find revision %s to ignore"
msgstr "référence à ignorer %s introuvable"
@ -2822,6 +2833,12 @@ msgstr "afficher le courriel de l'auteur au lieu du nom (Défaut : désactivé)"
msgid "ignore whitespace differences"
msgstr "ignorer les différences d'espace"
msgid "<algorithm>"
msgstr "<algorithme>"
msgid "choose a diff algorithm"
msgstr "choisir un algorithme de différence"
msgid "rev"
msgstr "rév"
@ -2838,7 +2855,7 @@ msgstr ""
msgid "color lines by age"
msgstr "colorier les lignes par âge"
msgid "spend extra cycles to find better match"
msgid "spend extra cycles to find a better match"
msgstr ""
"dépenser des cycles supplémentaires pour trouver une meilleure correspondance"
@ -4054,8 +4071,8 @@ msgid "missing branch name; try -%c"
msgstr "nom de branche manquant ; essayez -%c"
#, c-format
msgid "could not resolve %s"
msgstr "impossible de résoudre %s"
msgid "could not resolve '%s'"
msgstr "impossible de résoudre '%s'"
msgid "invalid path specification"
msgstr "spécification de chemin invalide"
@ -5561,10 +5578,18 @@ msgstr "--append ne s'applique pas avec --value=<motif>"
#, c-format
msgid ""
"cannot overwrite multiple values with a single value\n"
" Use a regexp, --add or --replace-all to change %s."
" Use --value=<pattern>, --append or --all to change %s."
msgstr ""
"impossible de surcharger des valeurs multiples avec une seule valeur\n"
" Utilisez une regex, --add ou --replace-all pour modifier %s."
" Utilisez --value=<motif>, --append ou --all pour modifier %s."
msgid "unset all multi-valued config options"
msgstr "réinitialiser toutes les options de configuration multi-valeurs"
msgid "unset multi-valued config options with matching values"
msgstr ""
"réinitialiser toutes les options de configuration multi-valeurs ayant des "
"valeurs correspondantes"
#, c-format
msgid "no such section: %s"
@ -5651,6 +5676,14 @@ msgstr "--default n'est applicable qu'avec --get"
msgid "--comment is only applicable to add/set/replace operations"
msgstr "--comment n'est applicable qu'avec les opérations add/set/replace"
#, c-format
msgid ""
"cannot overwrite multiple values with a single value\n"
" Use a regexp, --add or --replace-all to change %s."
msgstr ""
"impossible de surcharger des valeurs multiples avec une seule valeur\n"
" Utilisez une regex, --add ou --replace-all pour modifier %s."
msgid "print sizes in human readable format"
msgstr "affiche les tailles dans un format humainement lisible"
@ -6057,11 +6090,6 @@ msgstr ""
"encodage spécifique à un commit %.*s rencontré dans le commit %s; utilisez "
"--reencode=(yes|no) pour le gérer"
#, c-format
msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
msgstr ""
"commit signé %s rencontré; utilisez --signed-commits=<mode> pour le gérer"
#, c-format
msgid "exporting %<PRIuMAX> signature(s) for commit %s"
msgstr "export de %<PRIuMAX> signature(s) pour le commit %s"
@ -6070,6 +6098,18 @@ msgstr "export de %<PRIuMAX> signature(s) pour le commit %s"
msgid "stripping signature(s) from commit %s"
msgstr "suppression de signature(s) du commit %s"
#, c-format
msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
msgstr ""
"commit signé %s rencontré; utilisez --signed-commits=<mode> pour le gérer"
msgid ""
"'strip-if-invalid' is not a valid mode for git fast-export with --signed-"
"commits=<mode>"
msgstr ""
"'strip-if-invalid' n'est pas un mode valide pour git fast-export avec --"
"signed-commits=<mode>"
#, c-format
msgid ""
"omitting tag %s,\n"
@ -6083,11 +6123,6 @@ msgstr ""
msgid "could not read tag %s"
msgstr "impossible de lire l'étiquette %s"
#, c-format
msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
msgstr ""
"étiquette signée %s rencontrée; utilisez --signed-tags=<mode> pour la gérer"
#, c-format
msgid "exporting signed tag %s"
msgstr "export de l'étiquette signée %s"
@ -6096,6 +6131,18 @@ msgstr "export de l'étiquette signée %s"
msgid "stripping signature from tag %s"
msgstr "suppression de la signature dans l'étiquette %s"
#, c-format
msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
msgstr ""
"étiquette signée %s rencontrée; utilisez --signed-tags=<mode> pour la gérer"
msgid ""
"'strip-if-invalid' is not a valid mode for git fast-export with --signed-"
"tags=<mode>"
msgstr ""
"'strip-if-invalid' n'est pas un mode valide pour git fast-export avec --"
"signed-tags=<mode>"
#, c-format
msgid ""
"tag %s tags unexported object; use --tag-of-filtered-object=<mode> to handle "
@ -6491,6 +6538,33 @@ msgstr "multiple signatures %s trouvées, signatures additionnelles ignorées"
msgid "parse_one_signature() returned unknown hash algo"
msgstr "parse_one_signature() a renvoyé un algo d'empreinte inconnu"
msgid "unknown"
msgstr "inconnu"
#, c-format
msgid ""
"stripping invalid signature for commit '%.100s...'\n"
" allegedly by %s"
msgstr ""
"suppression de la signature invalide pour le commit '%.100s...'\n"
" prétendument par %s"
#, c-format
msgid ""
"stripping invalid signature for commit '%.*s'\n"
" allegedly by %s"
msgstr ""
"suppression de la signature invalide pour le commit '%.*s'\n"
" prétendument par %s"
#, c-format
msgid ""
"stripping invalid signature for commit\n"
" allegedly by %s"
msgstr ""
"suppression de la signature invalide pour le commit\n"
" prétendument par %s"
msgid "expected committer but didn't get one"
msgstr "validateur attendu mais aucune information fournie"
@ -6504,10 +6578,6 @@ msgstr "une signature de commit ignorée"
msgid "importing a commit signature verbatim"
msgstr "import d'une signature de commit verbatim"
msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
msgstr ""
"étiquette signée rencontrée; utilisez --signed-tags=<mode> pour la gérer"
#, c-format
msgid "importing a tag signature verbatim for tag '%s'"
msgstr "import d'une signature d'étiquette verbatim pour l'étiquette '%s'"
@ -6516,6 +6586,17 @@ msgstr "import d'une signature d'étiquette verbatim pour l'étiquette '%s'"
msgid "stripping a tag signature for tag '%s'"
msgstr "suppression d'une signature d'étiquette de l'étiquette '%s'"
msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
msgstr ""
"étiquette signée rencontrée; utilisez --signed-tags=<mode> pour la gérer"
msgid ""
"'strip-if-invalid' is not a valid mode for git fast-import with --signed-"
"tags=<mode>"
msgstr ""
"'strip-if-invalid' n'est pas un mode valide pour git fast-import avec --"
"signed-tags=<mode>"
#, c-format
msgid "expected 'from' command, got '%s'"
msgstr "Commande 'from' attendue, '%s' trouvé"
@ -6675,8 +6756,8 @@ msgstr "git fetch [<options>] [<dépôt> [<spécification-de-référence>...]]"
msgid "git fetch [<options>] <group>"
msgstr "git fetch [<options>] <groupe>"
msgid "git fetch --multiple [<options>] [(<repository> | <group>)...]"
msgstr "git fetch --multiple [<options>] [(<dépôt> | <groupe>)...]"
msgid "git fetch --multiple [<options>] [(<repository>|<group>)...]"
msgstr "git fetch --multiple [<options>] [(<dépôt>|<groupe>)...]"
msgid "git fetch --all [<options>]"
msgstr "git fetch --all [<options>]"
@ -7159,9 +7240,6 @@ msgstr "--config=<config> manquant"
msgid "got bad config --config=%s"
msgstr "config incorrecte --config=%s"
msgid "unknown"
msgstr "inconnu"
#. TRANSLATORS: e.g. error in tree 01bfda: <more explanation>
#, c-format
msgid "error in %s %s: %s"
@ -7256,6 +7334,10 @@ msgstr "%s : pointeur de sha1 invalide %s"
msgid "%s: not a commit"
msgstr "l'objet %s n'est pas un commit"
#, c-format
msgid "invalid parameter: expected sha1, got '%s'"
msgstr "paramètre invalide : sha-1 attendu, '%s' trouvé"
msgid "notice: No default references"
msgstr "note : pas de référence par défaut"
@ -7281,26 +7363,6 @@ msgstr "Vérification du répertoire d'objet"
msgid "Checking object directories"
msgstr "Vérification des répertoires d'objet"
#, c-format
msgid "Checking %s link"
msgstr "Vérification du lien %s"
#, c-format
msgid "invalid %s"
msgstr "%s invalide"
#, c-format
msgid "%s points to something strange (%s)"
msgstr "%s pointe sur quelque chose bizarre (%s)"
#, c-format
msgid "%s: detached HEAD points at nothing"
msgstr "%s : la HEAD détachée ne pointe sur rien"
#, c-format
msgid "notice: %s points to an unborn branch (%s)"
msgstr "note : %s pointe sur une branche non-née (%s)"
#, c-format
msgid "Checking cache tree of %s"
msgstr "Vérification de l'arbre cache de %s"
@ -7381,14 +7443,6 @@ msgstr "vérifier la cohérence de la base de données des références"
msgid "Checking objects"
msgstr "Vérification des objets"
#, c-format
msgid "%s: object missing"
msgstr "%s : objet manquant"
#, c-format
msgid "invalid parameter: expected sha1, got '%s'"
msgstr "paramètre invalide : sha-1 attendu, '%s' trouvé"
msgid "git fsmonitor--daemon start [<options>]"
msgstr "git fsmonitor--daemon start [<options>]"
@ -7777,6 +7831,9 @@ msgstr "impossible de mettre en place la planification de maintenance"
msgid "failed to add repo to global config"
msgstr "échec de l'ajout du dépôt à la config globale"
msgid "check a specific task"
msgstr "vérifier une tâche spécifique"
msgid "git maintenance <subcommand> [<options>]"
msgstr "git maintenance <subcommand> [<options>]"
@ -8237,6 +8294,10 @@ msgstr "objet blob invalide %s"
msgid "fsck error in packed object"
msgstr "erreur de fsck dans l'objet empaqueté"
#, c-format
msgid "invalid %s"
msgstr "%s invalide"
#, c-format
msgid "Not all child objects of %s are reachable"
msgstr "Tous les objets enfants de %s ne sont pas accessibles"
@ -8380,6 +8441,11 @@ msgstr "--stdin requiert un dépôt git"
msgid "--verify with no packfile name given"
msgstr "--verify sans nom de fichier paquet donné"
msgid "cannot perform queued object checks outside of a repository"
msgstr ""
"impossible d'effectuer les vérifications des objets en attentes hors d'un "
"dépôt"
msgid "fsck error in pack objects"
msgstr "erreur de fsck dans les objets paquets"
@ -9155,13 +9221,6 @@ msgstr ""
"git merge-file [<options>] [-L <nom1> [-L <orig> [-L <nom2>]]] <fichier1> "
"<fichier-orig> <fichier2>"
msgid ""
"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
"\"histogram\""
msgstr ""
"l'option diff-algorithm accept \"myers\", \"minimal\", \"patience\" et "
"\"histogram\""
msgid "send results to standard output"
msgstr "envoyer les résultats sur la sortie standard"
@ -9174,12 +9233,6 @@ msgstr "utiliser une fusion basée sur diff3"
msgid "use a zealous diff3 based merge"
msgstr "utiliser une fusion basée sur un diff3 zélée"
msgid "<algorithm>"
msgstr "<algorithme>"
msgid "choose a diff algorithm"
msgstr "choisir un algorithme de différence"
msgid "for conflicts, use this marker size"
msgstr "pour les conflits, utiliser cette taille de marqueur"
@ -10270,6 +10323,12 @@ msgstr ""
msgid "could not get type of object %s in pack %s"
msgstr "impossible d'obtenir le type de l'objet %s dans le paquet %s"
#, c-format
msgid "packfile %s is a promisor but --exclude-promisor-objects was given"
msgstr ""
"le fichier paquet %s est un prometteur mais --exclude-promisor-objects a été "
"spécifé"
#, c-format
msgid "could not find pack '%s'"
msgstr "impossible de trouver le paquet '%s'"
@ -10539,10 +10598,10 @@ msgstr "git pack-refs "
msgid "git patch-id [--stable | --unstable | --verbatim]"
msgstr "git patch-id [--stable | --unstable | --verbatim]"
msgid "use the unstable patch-id algorithm"
msgstr "utiliser l'algorithme instable patch-id"
msgid "use the unstable patch ID algorithm"
msgstr "utiliser l'algorithme patch-id instable"
msgid "use the stable patch-id algorithm"
msgid "use the stable patch ID algorithm"
msgstr "utiliser l'algorithme stable patch-id"
msgid "don't strip whitespace from the patch"
@ -10566,39 +10625,6 @@ msgstr "impossible d'élaguer dans un dépôt d'objets précieux"
msgid "git pull [<options>] [<repository> [<refspec>...]]"
msgstr "git pull [<options>] [<dépôt> [<spécification-de-référence>...]]"
msgid "control for recursive fetching of submodules"
msgstr "contrôler la récupération récursive dans les sous-modules"
msgid "Options related to merging"
msgstr "Options relatives à la fusion"
msgid "incorporate changes by rebasing rather than merging"
msgstr "incorporer les modifications en rebasant plutôt qu'en fusionnant"
msgid "allow fast-forward"
msgstr "autoriser l'avance rapide"
msgid "control use of pre-merge-commit and commit-msg hooks"
msgstr "contrôler l'utilisation des crochets pre-merge-commit et commit-msg"
msgid "automatically stash/stash pop before and after"
msgstr "remiser et réappliquer automatiquement avant et après"
msgid "Options related to fetching"
msgstr "Options relatives au rapatriement"
msgid "force overwrite of local branch"
msgstr "forcer l'écrasement de la branche locale"
msgid "number of submodules pulled in parallel"
msgstr "nombre de sous-modules tirés en parallèle"
msgid "use IPv4 addresses only"
msgstr "n'utiliser que des adresses IPv4"
msgid "use IPv6 addresses only"
msgstr "n'utiliser que des adresses IPv6"
msgid ""
"There is no candidate for rebasing against among the refs that you just "
"fetched."
@ -10705,6 +10731,39 @@ msgstr ""
"passer --rebase, --no-rebase ou --ff-only sur la ligne de commande pour\n"
"remplacer à l'invocation la valeur par défaut configurée.\n"
msgid "control for recursive fetching of submodules"
msgstr "contrôler la récupération récursive dans les sous-modules"
msgid "Options related to merging"
msgstr "Options relatives à la fusion"
msgid "incorporate changes by rebasing rather than merging"
msgstr "incorporer les modifications en rebasant plutôt qu'en fusionnant"
msgid "allow fast-forward"
msgstr "autoriser l'avance rapide"
msgid "control use of pre-merge-commit and commit-msg hooks"
msgstr "contrôler l'utilisation des crochets pre-merge-commit et commit-msg"
msgid "automatically stash/stash pop before and after"
msgstr "remiser et réappliquer automatiquement avant et après"
msgid "Options related to fetching"
msgstr "Options relatives au rapatriement"
msgid "force overwrite of local branch"
msgstr "forcer l'écrasement de la branche locale"
msgid "number of submodules pulled in parallel"
msgstr "nombre de sous-modules tirés en parallèle"
msgid "use IPv4 addresses only"
msgstr "n'utiliser que des adresses IPv4"
msgid "use IPv6 addresses only"
msgstr "n'utiliser que des adresses IPv6"
msgid "Updating an unborn branch with changes added to the index."
msgstr ""
"Mise à jour d'une branche non encore créée avec les changements ajoutés dans "
@ -12600,6 +12659,10 @@ msgstr "--convert-graft-file ne supporte aucun argument"
msgid "only one pattern can be given with -l"
msgstr "-l n'accepte qu'un motifs"
#, c-format
msgid "'%s' is not a valid commit-ish for %s"
msgstr "'%s' n'est pas un commit-esque valide pour l'option %s"
msgid "need some commits to replay"
msgstr "commits requis pour pouvoir rejouer"
@ -12616,28 +12679,16 @@ msgstr ""
"impossible d'avancer la cible avec des sources multiples parce l'ordre ne "
"serait pas total"
msgid ""
"cannot implicitly determine whether this is an --advance or --onto operation"
msgstr ""
"impossible de déterminer implicitement s'il y a une opération --advance ou --"
"onto"
msgid ""
"cannot advance target with multiple source branches because ordering would "
"be ill-defined"
msgstr ""
"impossible d'avancer la cible sur des branches sources multiples parce que "
"l'ordre ne serait pas total"
msgid "cannot implicitly determine correct base for --onto"
msgstr "impossible de déterminer implicitement une base correcte pour --onto"
#, c-format
msgid "invalid %s value: '%s'"
msgstr "valeur invalide de %s : '%s'"
msgid ""
"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
"<branch>) <revision-range>..."
"<branch>) [--ref-action[=<mode>]] <revision-range>"
msgstr ""
"(EXPERIMENTAL!) git replay ([--contained] --onto <nouvelle-base> | --advance "
"<branche>) <plage-de-révision>..."
"<branche>) [--ref-action[=<mode>]] <plage-de-révision>"
msgid "make replay advance given branch"
msgstr "faire rejouer en avançant la branche indiquée"
@ -12645,8 +12696,13 @@ msgstr "faire rejouer en avançant la branche indiquée"
msgid "replay onto given commit"
msgstr "rejouer par-dessus le commit indiqué"
msgid "advance all branches contained in revision-range"
msgstr "avancer toutes les branches contenues dans la plage-de-révisions"
msgid "update all branches that point at commits in <revision-range>"
msgstr ""
"mettre à jour les branches qui pointent sur les commits dans <plage-de-"
"révisions>"
msgid "control ref update behavior (update|print)"
msgstr "contrôler le comportement de mise à jour de ref (update|print)"
msgid "option --onto or --advance is mandatory"
msgstr "une option --onto ou --advance est obligatoire"
@ -12659,15 +12715,27 @@ msgstr ""
"certaines options de parcours de révs seront surchargées car le bit '%s' "
"dans 'struct rev_info' sera forcé"
#, c-format
msgid "failed to begin ref transaction: %s"
msgstr "impossible de commencer la transaction de réf; %s"
msgid "error preparing revisions"
msgstr "erreur lors de la préparation des révisions"
msgid "replaying down to root commit is not supported yet!"
msgstr "rejouer jusqu'au commit racine n'est pas encore géré !"
msgid "replaying down from root commit is not supported yet!"
msgstr "rejouer depuis le commit racine n'est pas encore géré !"
msgid "replaying merge commits is not supported yet!"
msgstr "rejouer des commits de fusion n'est pas encore géré !"
#, c-format
msgid "failed to update ref '%s': %s"
msgstr "échec de la mise à jour de la réf '%s': %s"
#, c-format
msgid "failed to commit ref transaction: %s"
msgstr "impossible de valider la transaction de réf: %s"
#, c-format
msgid "key '%s' not found"
msgstr "clé '%s' non trouvée"
@ -12682,9 +12750,15 @@ msgstr "format de sortie"
msgid "synonym for --format=nul"
msgstr "synonymes de --format=nul"
msgid "print all keys/values"
msgstr "afficher toutes les clés/valeurs"
msgid "unsupported output format"
msgstr "format de sortie non géré"
msgid "--all and <key> cannot be used together"
msgstr "--all et <clé> ne peuvent pas être utilisées ensemble"
msgid "References"
msgstr "Références"
@ -12715,6 +12789,12 @@ msgstr "Arbres"
msgid "Blobs"
msgstr "Blobs"
msgid "Inflated size"
msgstr "taille décompressée"
msgid "Disk size"
msgstr "Taille sur disque"
msgid "Repository structure"
msgstr "Structure de dépôt"
@ -15271,6 +15351,10 @@ msgstr "impossible d'analyser la clé de liste de colis %s avec la valeur '%s'"
msgid "bundle list at '%s' has no mode"
msgstr "la liste de colis n'a pas de mode à '%s'"
#, c-format
msgid "bundle list at '%s': bundle '%s' has no uri"
msgstr "la liste de colis à '%s'; le colis '%s' n'a pas d'URI"
msgid "failed to create temporary file"
msgstr "impossible de créer un fichier temporaire"
@ -15292,6 +15376,10 @@ msgstr "mode de colisage non reconnu depuis l'URI '%s'"
msgid "exceeded bundle URI recursion limit (%d)"
msgstr "limite de récursion d'URI de colis dépassée (%d)"
#, c-format
msgid "bundle '%s' has no uri"
msgstr "le colis '%s' n'a pas d'URI"
#, c-format
msgid "failed to download bundle from URI '%s'"
msgstr "impossible de télécharger le colis depuis l'URI '%s'"
@ -15805,8 +15893,8 @@ msgstr "Générer une résumé des modifications en attentes"
msgid "Reuse recorded resolution of conflicted merges"
msgstr "Réutiliser une résolution enregistrée de fusions conflictuelles"
msgid "Reset current HEAD to the specified state"
msgstr "Réinitialiser la HEAD courante à l'état spécifié"
msgid "Set `HEAD` or the index to a known state"
msgstr "Positionner `HEAD` ou l'index à un état connu"
msgid "Restore working tree files"
msgstr "Restaurer les fichiers l'arbre de travail"
@ -17375,10 +17463,6 @@ msgid "Unknown value for 'diff.submodule' config variable: '%s'"
msgstr ""
"Valeur inconnue pour la variable de configuration 'diff.submodule' : '%s'"
#, c-format
msgid "unknown value for config '%s': %s"
msgstr "valeur inconnue pour la config '%s' : %s"
#, c-format
msgid ""
"Found errors in 'diff.dirstat' config variable:\n"
@ -19555,6 +19639,10 @@ msgstr "lecture tronquée pendant l'indexation de %s"
msgid "%s: failed to insert into database"
msgstr "%s : échec de l'insertion dans la base de données"
msgid "cannot add a submodule of a different hash algorithm"
msgstr ""
"impossible d'ajouter un sous-module ayant un algorithme d'empreinte différent"
#, c-format
msgid "%s: unsupported file type"
msgstr "%s : type de fichier non supporté"
@ -21037,6 +21125,10 @@ msgstr "cette commande rejette l'atome %%(%.*s)"
msgid "--format=%.*s cannot be used with --python, --shell, --tcl"
msgstr "--format=%.*s ne peut pas être utilisé avec --python, --shell, --tcl"
#, c-format
msgid "parse_object_buffer failed on %s for %s"
msgstr "échec de parse_object_buffer sur %s pour %s"
msgid "failed to run 'describe'"
msgstr "échec pour lancer 'describe'"
@ -21067,10 +21159,6 @@ msgstr "(aucune branche)"
msgid "missing object %s for %s"
msgstr "objet manquant %s pour %s"
#, c-format
msgid "parse_object_buffer failed on %s for %s"
msgstr "échec de parse_object_buffer sur %s pour %s"
#, c-format
msgid "malformed object at '%s'"
msgstr "objet malformé à '%s'"
@ -21376,6 +21464,18 @@ msgid "refname %s is a symbolic ref, copying it is not supported"
msgstr ""
"le nom de réf %s est une réf symbolique, la copie n'est pas prise en charge"
#, c-format
msgid "reftable stack for worktree '%s' is broken"
msgstr "la pile de reftable pour l'arbre-de-travail '%s' est cassée"
#, c-format
msgid "could not create iterator for worktree '%s'"
msgstr "impossible de créer l'itérateur l'arbre-de-travail '%s'"
#, c-format
msgid "could not read record for worktree '%s'"
msgstr "impossible de lire l'enregistrement pour l'arbre-de-travail '%s'"
#, c-format
msgid "pattern '%s' has no '*'"
msgstr "la valeur '%s' du motif n'a pas de '*'"
@ -21800,10 +21900,11 @@ msgstr "impossible de revenir la bitmap obsolète : %s"
msgid "could not start pack-objects to repack promisor objects"
msgstr ""
"ne pas démarrer pack-objects pour ré-empaqueter les objects de prometteur"
"échec du démarrage de pack-objects pour ré-empaqueter les objets de "
"prometteur"
msgid "failed to feed promisor objects to pack-objects"
msgstr "Échéc de la fourniture les objets du prometteur à pack-objects"
msgstr "échec de la fourniture les objets du prometteur à pack-objects"
msgid "repack: Expecting full hex object ID lines only from pack-objects."
msgstr ""
@ -21815,6 +21916,11 @@ msgstr ""
"impossible de terminer pack-objects pour ré-empaqueter les objets de "
"prometteur"
msgid "could not start pack-objects to repack promisor packs"
msgstr ""
"échec du démarrage de pack-objects pour ré-empaqueter les paquets de "
"prometteur"
#, c-format
msgid "pack prefix %s does not begin with objdir %s"
msgstr "le préfixe %s ne commence pas avec objdir %s"
@ -22820,10 +22926,6 @@ msgstr ""
msgid "illegal label name: '%.*s'"
msgstr "nom de label illégal '%.*s'"
#, c-format
msgid "could not resolve '%s'"
msgstr "impossible de résoudre '%s'"
msgid "writing fake root commit"
msgstr "écriture d'un commit racine bidon"
@ -23309,49 +23411,68 @@ msgstr "mauvais format '%s' : l'élément '%s' ne se termine pas ')'"
msgid "bad %s format: %%%.*s"
msgstr "mauvais format %s : %%%.*s"
#. TRANSLATORS: IEC 80000-13:2008 gibibyte
#, c-format
msgid "%u.%2.2u GiB"
msgstr "%u.%2.2u Gio"
msgid "%u.%2.2u"
msgstr "%u.%2.2u"
#. TRANSLATORS: IEC 80000-13:2008 gibibyte/second
#, c-format
msgid "%u.%2.2u GiB/s"
msgstr "%u.%2.2u Gio/s"
#. TRANSLATORS: SI decimal prefix symbol for 10^9
msgid "G"
msgstr "G"
#. TRANSLATORS: IEC 80000-13:2008 mebibyte
#, c-format
msgid "%u.%2.2u MiB"
msgstr "%u.%2.2u Mio"
#. TRANSLATORS: SI decimal prefix symbol for 10^6
msgid "M"
msgstr "M"
#. TRANSLATORS: IEC 80000-13:2008 mebibyte/second
#, c-format
msgid "%u.%2.2u MiB/s"
msgstr "%u.%2.2u Mio/s"
#. TRANSLATORS: SI decimal prefix symbol for 10^3
msgid "k"
msgstr "k"
#. TRANSLATORS: IEC 80000-13:2008 kibibyte
#, c-format
msgid "%u.%2.2u KiB"
msgstr "%u.%2.2u Kio"
#. TRANSLATORS: IEC 80000-13:2008 gibibyte/second and gibibyte
msgid "GiB/s"
msgstr "GiO/s"
#. TRANSLATORS: IEC 80000-13:2008 kibibyte/second
#, c-format
msgid "%u.%2.2u KiB/s"
msgstr "%u.%2.2u Kio/s"
msgid "GiB"
msgstr "GiO"
#. TRANSLATORS: IEC 80000-13:2008 byte
#, c-format
msgid "%u byte"
msgid_plural "%u bytes"
msgstr[0] "%u octet"
msgstr[1] "%u octets"
#. TRANSLATORS: IEC 80000-13:2008 mebibyte/second and mebibyte
msgid "MiB/s"
msgstr "MiO/s"
msgid "MiB"
msgstr "MiO"
#. TRANSLATORS: IEC 80000-13:2008 kibibyte/second and kibibyte
msgid "KiB/s"
msgstr "KiO/s"
msgid "KiB"
msgstr "KiO"
#. TRANSLATORS: IEC 80000-13:2008 byte/second and byte
msgid "B/s"
msgstr "Octets/s"
msgid "B"
msgstr "Octets"
#. TRANSLATORS: IEC 80000-13:2008 byte/second
msgid "byte/s"
msgid_plural "bytes/s"
msgstr[0] "octet/s"
msgstr[1] "octets/s"
#. TRANSLATORS: IEC 80000-13:2008 byte
msgid "byte"
msgid_plural "bytes"
msgstr[0] "octet"
msgstr[1] "octets"
#. TRANSLATORS: The first argument is the number string. The second
#. argument is the unit string (i.e. "12.34 MiB/s").
#.
#, c-format
msgid "%u byte/s"
msgid_plural "%u bytes/s"
msgstr[0] "%u octet/s"
msgstr[1] "%u octets/s"
msgid "%s %s"
msgstr "%s %s"
#, c-format
msgid "ignoring suspicious submodule name: %s"
@ -23651,9 +23772,6 @@ msgstr "nombre d'octets"
msgid "number of requests per thread"
msgstr "nombre de requêtes par fil d'exécution"
msgid "byte"
msgstr "octet"
msgid "ballast character"
msgstr "caractère ballast"
@ -25268,63 +25386,3 @@ msgstr "%s sauté avec un suffix de sauvegarde '%s'.\n"
#, perl-format
msgid "Do you really want to send %s? [y|N]: "
msgstr "Souhaitez-vous réellement envoyer %s ?[y|N] : "
#~ msgid "No previous hunk"
#~ msgstr "Pas de section précédente"
#~ msgid "No next hunk"
#~ msgstr "Pas de section suivante"
#~ msgid "git for-each-ref [<options>] [<pattern>]"
#~ msgstr "git for-each-ref [<options>] [<motif>]"
#~ msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
#~ msgstr "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"
#~ msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
#~ msgstr "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"
#~ msgid "git for-each-ref [--start-after <marker>]"
#~ msgstr "git for-each-ref [--start-after <marqueur>]"
#~ msgid ""
#~ "git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--"
#~ "exclude <pattern>]"
#~ msgstr ""
#~ "git pack-refs [--all] [--no-prune] [--auto] [--include <motif>] [--"
#~ "exclude <motif>]"
#, c-format
#~ msgid "deleting '%s' failed"
#~ msgstr "échec de suppression de '%s'"
#, c-format
#~ msgid "creating '%s' failed"
#~ msgstr "échec de création de '%s'"
#, c-format
#~ msgid "could not open index for %s"
#~ msgstr "impossible d'ouvrir l'index pour %s"
#~ msgid "cannot handle pushes this big"
#~ msgstr "impossible de gérer des poussées aussi grosses"
#, c-format
#~ msgid ""
#~ "'%s' is nominated for removal.\n"
#~ "If you still use this command, please add an extra\n"
#~ "option, '--i-still-use-this', on the command line\n"
#~ "and let us know you still use it by sending an e-mail\n"
#~ "to <git@vger.kernel.org>. Thanks.\n"
#~ msgstr ""
#~ "La suppression de '%s' est prévue.\n"
#~ "Si vous utilisez cette commande, veuillez ajouter\n"
#~ "une option supplémentaire, '--i-still-use-this',\n"
#~ "sur la ligne de commande pour nous avertir par\n"
#~ "un courriel à <git@vger.kernel.org>. Merci.\n"
#~ msgid "start-after"
#~ msgstr "start-after"
#~ msgid "compact-summary"
#~ msgstr "résumé-compact"

627
po/ga.po

File diff suppressed because it is too large Load Diff

568
po/id.po
View File

@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Git\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
"POT-Creation-Date: 2025-11-06 23:58+0000\n"
"PO-Revision-Date: 2025-11-13 08:58+0700\n"
"POT-Creation-Date: 2026-01-22 23:57+0000\n"
"PO-Revision-Date: 2025-01-27 09:10+0700\n"
"Last-Translator: Bagas Sanjaya <bagasdotme@gmail.com>\n"
"Language-Team: Indonesian\n"
"Language: id\n"
@ -957,9 +957,9 @@ msgstr "opsi abai spasi putih tidak dikenal '%s'"
#: builtin/fast-export.c builtin/fetch.c builtin/help.c builtin/index-pack.c
#: builtin/init-db.c builtin/log.c builtin/ls-files.c builtin/merge-base.c
#: builtin/merge-tree.c builtin/merge.c builtin/rebase.c builtin/repack.c
#: builtin/replay.c builtin/reset.c builtin/rev-parse.c builtin/show-branch.c
#: builtin/stash.c builtin/submodule--helper.c builtin/tag.c builtin/worktree.c
#: parse-options.c range-diff.c revision.c
#: builtin/reset.c builtin/rev-parse.c builtin/show-branch.c builtin/stash.c
#: builtin/submodule--helper.c builtin/tag.c builtin/worktree.c parse-options.c
#: range-diff.c revision.c
#, c-format
msgid "options '%s' and '%s' cannot be used together"
msgstr "Opsi '%s' dan '%s' tidak dapat digunakan bersamaan"
@ -2134,8 +2134,8 @@ msgid "'%s' is not a valid branch name"
msgstr "'%s' bukan nama cabang valid"
#: branch.c builtin/branch.c
msgid "See `man git check-ref-format`"
msgstr "Lihat `man git check-ref-format`"
msgid "See 'git help check-ref-format'"
msgstr "Lihat `git help check-ref-format`"
#: branch.c
#, c-format
@ -3276,6 +3276,19 @@ msgstr "mengharapkan warna: %s"
msgid "must end with a color"
msgstr "harus berakhir dengan warna"
#: builtin/blame.c diff.c merge-ort.c transport.c
#, c-format
msgid "unknown value for config '%s': %s"
msgstr "nilai tidak dikenal untuk konfigurasi '%s': %s"
#: builtin/blame.c builtin/merge-file.c diff.c
msgid ""
"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
"\"histogram\""
msgstr ""
"opsi diff-algorithm terima \"myers\", \"minimal\", \"patience\" dan "
"\"histogram\""
#: builtin/blame.c
#, c-format
msgid "cannot find revision %s to ignore"
@ -3347,6 +3360,14 @@ msgstr "perlihatkan email pengarang daripada nama (asali: off)"
msgid "ignore whitespace differences"
msgstr "abaikan perbedaan spasi putih"
#: builtin/blame.c builtin/merge-file.c diff.c
msgid "<algorithm>"
msgstr "<algoritma>"
#: builtin/blame.c builtin/merge-file.c diff.c
msgid "choose a diff algorithm"
msgstr "pilih algoritma diff"
#: builtin/blame.c builtin/clone.c builtin/log.c
msgid "rev"
msgstr "revisi"
@ -3368,8 +3389,8 @@ msgid "color lines by age"
msgstr "warnai baris oleh umur"
#: builtin/blame.c
msgid "spend extra cycles to find better match"
msgstr "perlihatkan siklus ekstra untuk menemukan cocokan yang lebih baik"
msgid "spend extra cycles to find a better match"
msgstr "habiskan siklus tambahan untuk mencari pasangan yang lebih baik"
#: builtin/blame.c
msgid "use revisions from <file> instead of calling git-rev-list"
@ -3922,7 +3943,7 @@ msgstr ""
"Anda dapat menghapus baris-baris yang Anda tidak ingin dibagi.\n"
#: builtin/bugreport.c builtin/commit.c builtin/fast-export.c
#: builtin/pack-objects.c builtin/rebase.c parse-options.h
#: builtin/pack-objects.c builtin/rebase.c builtin/replay.c parse-options.h
msgid "mode"
msgstr "mode"
@ -4857,10 +4878,10 @@ msgstr "--track butuh nama cabang"
msgid "missing branch name; try -%c"
msgstr "kehilangan nama cabang; coba -%c"
#: builtin/checkout.c
#: builtin/checkout.c sequencer.c
#, c-format
msgid "could not resolve %s"
msgstr "tidak dapat menyelesaikan %s"
msgid "could not resolve '%s'"
msgstr "tidak dapat menguraikan '%s'"
#: builtin/checkout.c
msgid "invalid path specification"
@ -6715,10 +6736,18 @@ msgstr "--append tidak dapat digunakan dengan --value=<pola>"
#, c-format
msgid ""
"cannot overwrite multiple values with a single value\n"
" Use a regexp, --add or --replace-all to change %s."
" Use --value=<pattern>, --append or --all to change %s."
msgstr ""
"tidak dapat menimpa banyak nilai dengan nilai tunggal\n"
" Gunakan regexp, --add atau --replace-all untuk mengubah %s."
" Gunakan --value=<pola>, --append atau --all untuk mengubah %s."
#: builtin/config.c
msgid "unset all multi-valued config options"
msgstr "batal setel semua opsi konfigurasi multi-nilai"
#: builtin/config.c
msgid "unset multi-valued config options with matching values"
msgstr "batal setel opsi konfigurasi multi-nilai dengan nilai yang sepadan"
#: builtin/config.c
#, c-format
@ -6832,6 +6861,15 @@ msgstr ""
"--comment hanya dapat diterapkan pada operasi penambahan/penyetelan/"
"penggantian"
#: builtin/config.c
#, c-format
msgid ""
"cannot overwrite multiple values with a single value\n"
" Use a regexp, --add or --replace-all to change %s."
msgstr ""
"tidak dapat menimpa banyak nilai dengan nilai tunggal\n"
" Gunakan regexp, --add atau --replace-all untuk mengubah %s."
#: builtin/count-objects.c
msgid "print sizes in human readable format"
msgstr "cetak ukuran dalam format yang bisa dibaca manusia"
@ -7342,13 +7380,6 @@ msgstr ""
"menemukan pengkodean komit-spesifik %.*s pada komit %s; gunakan --"
"reencode=[yes|no] untuk menanganinya"
#: builtin/fast-export.c
#, c-format
msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
msgstr ""
"menemukan komit bertandatangan %s; gunakan --signed-commits=<mode> untuk "
"menanganinya"
#: builtin/fast-export.c
#, c-format
msgid "exporting %<PRIuMAX> signature(s) for commit %s"
@ -7359,6 +7390,21 @@ msgstr "mengekspor %<PRIuMAX> tandatangan untuk komit %s"
msgid "stripping signature(s) from commit %s"
msgstr "mengupas tandatangan dari komit %s"
#: builtin/fast-export.c
#, c-format
msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
msgstr ""
"menemukan komit bertandatangan %s; gunakan --signed-commits=<mode> untuk "
"menanganinya"
#: builtin/fast-export.c
msgid ""
"'strip-if-invalid' is not a valid mode for git fast-export with --signed-"
"commits=<mode>"
msgstr ""
"'strip-if-invalid' bukan mode valid untuk git fast-export dengan --signed-"
"commits=<mode>"
#: builtin/fast-export.c
#, c-format
msgid ""
@ -7373,13 +7419,6 @@ msgstr ""
msgid "could not read tag %s"
msgstr "tidak dapat membaca tag %s"
#: builtin/fast-export.c
#, c-format
msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
msgstr ""
"menemukan tag bertandatangan %s; gunakan --signed-tags=<mode> untuk "
"menanganinya"
#: builtin/fast-export.c
#, c-format
msgid "exporting signed tag %s"
@ -7390,6 +7429,21 @@ msgstr "mengekspor tag bertandatangan %s"
msgid "stripping signature from tag %s"
msgstr "mengupas tandatangan dari tag %s"
#: builtin/fast-export.c
#, c-format
msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
msgstr ""
"menemukan tag bertandatangan %s; gunakan --signed-tags=<mode> untuk "
"menanganinya"
#: builtin/fast-export.c
msgid ""
"'strip-if-invalid' is not a valid mode for git fast-export with --signed-"
"tags=<mode>"
msgstr ""
"'strip-if-invalid' bukan mode valid untuk git fast-export dengan --signed-"
"tags=<mode>"
#: builtin/fast-export.c
#, c-format
msgid ""
@ -7883,6 +7937,37 @@ msgstr "beberapa %s tandatangan ditemukan, abaikan tandatangan tambahan"
msgid "parse_one_signature() returned unknown hash algo"
msgstr "parse_one_signature() mengembalikan algoritma hash tak dikenal"
#: builtin/fast-import.c builtin/fsck.c
msgid "unknown"
msgstr "tidak dikenal"
#: builtin/fast-import.c
#, c-format
msgid ""
"stripping invalid signature for commit '%.100s...'\n"
" allegedly by %s"
msgstr ""
"mengupas tandatangan tidak valid untuk komit '%.100s...'\n"
" yang diduga dibuat oleh %s"
#: builtin/fast-import.c
#, c-format
msgid ""
"stripping invalid signature for commit '%.*s'\n"
" allegedly by %s"
msgstr ""
"mengupas tandatangan tidak valid untuk komit '%.*s'\n"
" yang diduga dibuat oleh %s"
#: builtin/fast-import.c
#, c-format
msgid ""
"stripping invalid signature for commit\n"
" allegedly by %s"
msgstr ""
"mengupas tandatangan tidak valid untuk komit\n"
" yang diduga dibuat oleh %s"
#: builtin/fast-import.c
msgid "expected committer but didn't get one"
msgstr "pengkomit diharapkan tapi tidak mendapatkannya"
@ -7901,11 +7986,6 @@ msgstr "mengupas tandatangan komit"
msgid "importing a commit signature verbatim"
msgstr "mengimpor tandatangan komit secara verbatim"
#: builtin/fast-import.c
msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
msgstr ""
"menemukan tag bertandatangan; gunakan --signed-tags=<mode> untuk menanganinya"
#: builtin/fast-import.c
#, c-format
msgid "importing a tag signature verbatim for tag '%s'"
@ -7916,6 +7996,19 @@ msgstr "mengimpor tag secara verbatim untuk tag '%s'"
msgid "stripping a tag signature for tag '%s'"
msgstr "mengupas tandatangan tag untuk tag '%s'"
#: builtin/fast-import.c
msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
msgstr ""
"menemukan tag bertandatangan; gunakan --signed-tags=<mode> untuk menanganinya"
#: builtin/fast-import.c
msgid ""
"'strip-if-invalid' is not a valid mode for git fast-import with --signed-"
"tags=<mode>"
msgstr ""
"'strip-if-invalid' bukan mode valid untuk git fast-import dengan --signed-"
"tags=<mode>"
#: builtin/fast-import.c
#, c-format
msgid "expected 'from' command, got '%s'"
@ -8114,8 +8207,8 @@ msgid "git fetch [<options>] <group>"
msgstr "git fetch [<opsi>] <grup>"
#: builtin/fetch.c
msgid "git fetch --multiple [<options>] [(<repository> | <group>)...]"
msgstr "git fetch --multiple [<opsi>] [(<repositori> | <grup>)]"
msgid "git fetch --multiple [<options>] [(<repository>|<group>)...]"
msgstr "git fetch --multiple [<opsi>] [(<repositori> | <grup>)...]"
#: builtin/fetch.c
msgid "git fetch --all [<options>]"
@ -8708,10 +8801,6 @@ msgstr "kehilangan --config=<config>"
msgid "got bad config --config=%s"
msgstr "dapat konfigurasi jelek --config=%s"
#: builtin/fsck.c
msgid "unknown"
msgstr "tidak dikenal"
#. TRANSLATORS: e.g. error in tree 01bfda: <more explanation>
#: builtin/fsck.c
#, c-format
@ -8830,6 +8919,11 @@ msgstr "%s: penunjuk sha1 tidak valid %s"
msgid "%s: not a commit"
msgstr "%s: bukan sebuah komit"
#: builtin/fsck.c
#, c-format
msgid "invalid parameter: expected sha1, got '%s'"
msgstr "parameter tidak valid: sha1 diharapkan, dapat '%s'"
#: builtin/fsck.c
msgid "notice: No default references"
msgstr "catatan: Tidak ada referensi asali"
@ -8862,31 +8956,6 @@ msgstr "Memeriksa direktori objek"
msgid "Checking object directories"
msgstr "Memeriksa direktori objek"
#: builtin/fsck.c
#, c-format
msgid "Checking %s link"
msgstr "Memeriksa tautan %s"
#: builtin/fsck.c builtin/index-pack.c
#, c-format
msgid "invalid %s"
msgstr "%s tidak valid"
#: builtin/fsck.c
#, c-format
msgid "%s points to something strange (%s)"
msgstr "%s menunjuk ke sesuatu yang aneh (%s)"
#: builtin/fsck.c
#, c-format
msgid "%s: detached HEAD points at nothing"
msgstr "%s: HEAD terpisah tidak menunjuk ke apapun"
#: builtin/fsck.c
#, c-format
msgid "notice: %s points to an unborn branch (%s)"
msgstr "catatan: %s menunjuk ke cabang yang belum lahir (%s)"
#: builtin/fsck.c
#, c-format
msgid "Checking cache tree of %s"
@ -8988,16 +9057,6 @@ msgstr "Memeriksa konsistensi basis data referensi"
msgid "Checking objects"
msgstr "Memeriksa objek"
#: builtin/fsck.c
#, c-format
msgid "%s: object missing"
msgstr "%s: objek hilang"
#: builtin/fsck.c
#, c-format
msgid "invalid parameter: expected sha1, got '%s'"
msgstr "parameter tidak valid: sha1 diharapkan, dapat '%s'"
#: builtin/fsmonitor--daemon.c
msgid "git fsmonitor--daemon start [<options>]"
msgstr "git fsmonitor--daemon start [<opsi>]"
@ -9477,6 +9536,10 @@ msgstr "gagal mempersiapkan jadwal pemeliharaan"
msgid "failed to add repo to global config"
msgstr "gagal menambahkan repositori ke konfigurasi global"
#: builtin/gc.c
msgid "check a specific task"
msgstr "periksa tugas yang spesifik"
#: builtin/gc.c
msgid "git maintenance <subcommand> [<options>]"
msgstr "git maintenance <subperintah> [<opsi>]"
@ -10058,6 +10121,11 @@ msgstr "objek blob tidak valid %s"
msgid "fsck error in packed object"
msgstr "kesalahan fsck dalam objek terpaket"
#: builtin/index-pack.c
#, c-format
msgid "invalid %s"
msgstr "%s tidak valid"
#: builtin/index-pack.c
#, c-format
msgid "Not all child objects of %s are reachable"
@ -10234,6 +10302,11 @@ msgstr "--stdin memerlukan repositori git"
msgid "--verify with no packfile name given"
msgstr "--verify tanpa nama berkas paket diberikan"
#: builtin/index-pack.c
msgid "cannot perform queued object checks outside of a repository"
msgstr ""
"tidak dapat melakukan pemeriksaan objek yang mengantre di luar repositori"
#: builtin/index-pack.c builtin/unpack-objects.c
msgid "fsck error in pack objects"
msgstr "kesalahan fsck dalam objek paket"
@ -11208,14 +11281,6 @@ msgstr ""
"git merge-file [<opsi>] [-L <nama 1> [-L <asli> [-L <nama 2>]]] <berkas 1> "
"<berkas asli> <berkas 2>"
#: builtin/merge-file.c diff.c
msgid ""
"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
"\"histogram\""
msgstr ""
"opsi diff-algorithm terima \"myers\", \"minimal\", \"patience\" dan "
"\"histogram\""
#: builtin/merge-file.c
msgid "send results to standard output"
msgstr "kirim hasil ke keluaran standar"
@ -11232,14 +11297,6 @@ msgstr "gunakan penggabungan berdasarkan diff3"
msgid "use a zealous diff3 based merge"
msgstr "gunakan penggabungan berdasarkan diff3 yang bersemangat"
#: builtin/merge-file.c diff.c
msgid "<algorithm>"
msgstr "<algoritma>"
#: builtin/merge-file.c diff.c
msgid "choose a diff algorithm"
msgstr "pilih algoritma diff"
#: builtin/merge-file.c
msgid "for conflicts, use this marker size"
msgstr "untuk konflik, gunakan ukuran penanda ini"
@ -12592,6 +12649,11 @@ msgstr ""
msgid "could not get type of object %s in pack %s"
msgstr "tidak dapat mendapatkan tipe objek %s di dalam pak %s"
#: builtin/pack-objects.c
#, c-format
msgid "packfile %s is a promisor but --exclude-promisor-objects was given"
msgstr "berkas pak %s adalah pejanji tapi --exclude-promisor-objects diberikan"
#: builtin/pack-objects.c
#, c-format
msgid "could not find pack '%s'"
@ -12930,12 +12992,12 @@ msgid "git patch-id [--stable | --unstable | --verbatim]"
msgstr "git patch-id [--stable | --unstable | --verbatim]"
#: builtin/patch-id.c
msgid "use the unstable patch-id algorithm"
msgstr "gunakan algoritma id tambalan tidak stabil"
msgid "use the unstable patch ID algorithm"
msgstr "gunakan algoritma ID tambalan yang tidak stabil"
#: builtin/patch-id.c
msgid "use the stable patch-id algorithm"
msgstr "gunakan algoritma id tambalan stabil"
msgid "use the stable patch ID algorithm"
msgstr "gunakan algoritma ID tambalan yang stabil"
#: builtin/patch-id.c
msgid "don't strip whitespace from the patch"
@ -12965,50 +13027,6 @@ msgstr "tidak dapat memangkas di dalam repositori objek berharga"
msgid "git pull [<options>] [<repository> [<refspec>...]]"
msgstr "git pull [<opsi>] [<repositori> [<spek referensi>]]"
#: builtin/pull.c
msgid "control for recursive fetching of submodules"
msgstr "kontrol pengambilan rekursif submodul"
#: builtin/pull.c
msgid "Options related to merging"
msgstr "Opsi yang berkaitan dengan penggabungan"
#: builtin/pull.c
msgid "incorporate changes by rebasing rather than merging"
msgstr "masukkan perubahan dengan pendasaran ulang daripada penggabungan"
#: builtin/pull.c builtin/revert.c
msgid "allow fast-forward"
msgstr "perbolehkan maju cepat"
#: builtin/pull.c
msgid "control use of pre-merge-commit and commit-msg hooks"
msgstr "kontrol penggunaan kail pre-merge-commit dan commit-msg"
#: builtin/pull.c parse-options.h
msgid "automatically stash/stash pop before and after"
msgstr "stash/stash pop otomatis sebelum dan sesudah"
#: builtin/pull.c
msgid "Options related to fetching"
msgstr "Opsi yang berkaitan dengan pengambilan"
#: builtin/pull.c
msgid "force overwrite of local branch"
msgstr "paksa timpa cabang lokal"
#: builtin/pull.c
msgid "number of submodules pulled in parallel"
msgstr "nomor submodul ditarik dalam paralel"
#: builtin/pull.c parse-options.h
msgid "use IPv4 addresses only"
msgstr "gunakan hanya alamat IPv4"
#: builtin/pull.c parse-options.h
msgid "use IPv6 addresses only"
msgstr "gunakan hanya alamat IPv6"
#: builtin/pull.c
msgid ""
"There is no candidate for rebasing against among the refs that you just "
@ -13132,6 +13150,50 @@ msgstr ""
"--rebase, --no-rebase, atau --ff-only pada baris perintah untuk menimpa\n"
"asali terkonfigurasi untuk setiap invokasi.\n"
#: builtin/pull.c
msgid "control for recursive fetching of submodules"
msgstr "kontrol pengambilan rekursif submodul"
#: builtin/pull.c
msgid "Options related to merging"
msgstr "Opsi yang berkaitan dengan penggabungan"
#: builtin/pull.c
msgid "incorporate changes by rebasing rather than merging"
msgstr "masukkan perubahan dengan pendasaran ulang daripada penggabungan"
#: builtin/pull.c builtin/revert.c
msgid "allow fast-forward"
msgstr "perbolehkan maju cepat"
#: builtin/pull.c
msgid "control use of pre-merge-commit and commit-msg hooks"
msgstr "kontrol penggunaan kail pre-merge-commit dan commit-msg"
#: builtin/pull.c parse-options.h
msgid "automatically stash/stash pop before and after"
msgstr "stash/stash pop otomatis sebelum dan sesudah"
#: builtin/pull.c
msgid "Options related to fetching"
msgstr "Opsi yang berkaitan dengan pengambilan"
#: builtin/pull.c
msgid "force overwrite of local branch"
msgstr "paksa timpa cabang lokal"
#: builtin/pull.c
msgid "number of submodules pulled in parallel"
msgstr "nomor submodul ditarik dalam paralel"
#: builtin/pull.c parse-options.h
msgid "use IPv4 addresses only"
msgstr "gunakan hanya alamat IPv4"
#: builtin/pull.c parse-options.h
msgid "use IPv6 addresses only"
msgstr "gunakan hanya alamat IPv6"
#: builtin/pull.c
msgid "Updating an unborn branch with changes added to the index."
msgstr ""
@ -15420,6 +15482,11 @@ msgstr "--convert-graft-file tidak mengambil argumen"
msgid "only one pattern can be given with -l"
msgstr "hanya satu pola yang dapat diberikan dengan -l"
#: builtin/replay.c
#, c-format
msgid "'%s' is not a valid commit-ish for %s"
msgstr "'%s' bukan mirip komit yang valid untuk %s"
#: builtin/replay.c
msgid "need some commits to replay"
msgstr "butuh beberapa komit untuk dimainkan ulang"
@ -15441,31 +15508,17 @@ msgstr ""
"menjadi tidak jelas"
#: builtin/replay.c
msgid ""
"cannot implicitly determine whether this is an --advance or --onto operation"
msgstr ""
"tidak dapat menentukan secara tidak langsung apakah ini operasi --advance "
"atau --onto"
#: builtin/replay.c
msgid ""
"cannot advance target with multiple source branches because ordering would "
"be ill-defined"
msgstr ""
"tidak dapat memajukan target dengan banyak cabang sumber karena "
"pengurutannya akan menjadi tidak jelas"
#: builtin/replay.c
msgid "cannot implicitly determine correct base for --onto"
msgstr "tidak dapat menentukan secara tidak langsung dasar untuk --onto"
#, c-format
msgid "invalid %s value: '%s'"
msgstr "nilai %s tidak valid: '%s'"
#: builtin/replay.c
msgid ""
"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
"<branch>) <revision-range>..."
"<branch>) [--ref-action[=<mode>]] <revision-range>"
msgstr ""
"(EKSPERIMENTAL!) git replay ([--contained] --onto <dasar baru> | --advance "
"<cabang>) <rentang revisi>..."
"<cabang>) [--ref-action[=<mode>]] <rentang revisi>"
#: builtin/replay.c
msgid "make replay advance given branch"
@ -15476,8 +15529,13 @@ msgid "replay onto given commit"
msgstr "mainkan ulang pada komit yang diberikan"
#: builtin/replay.c
msgid "advance all branches contained in revision-range"
msgstr "majukan semua cabang yang berada pada rentang komit"
msgid "update all branches that point at commits in <revision-range>"
msgstr ""
"perbarui semua cabang yang menunjuk pada komit di dalam <rentang revisi>"
#: builtin/replay.c
msgid "control ref update behavior (update|print)"
msgstr "atur perilaku pembaruan referensi (update|print)"
#: builtin/replay.c
msgid "option --onto or --advance is mandatory"
@ -15492,18 +15550,33 @@ msgstr ""
"beberapa opsi jalan revisi akan ditimpa oleh karena bit '%s' di 'struct "
"rev_info' akan dipaksakan"
#: builtin/replay.c
#, c-format
msgid "failed to begin ref transaction: %s"
msgstr "gagal memulai transaksi referensi: %s"
#: builtin/replay.c
msgid "error preparing revisions"
msgstr "kesalahan menyiapkan revisi"
#: builtin/replay.c
msgid "replaying down to root commit is not supported yet!"
msgstr "memainkan ulang ke komit akar belum didukung!"
msgid "replaying down from root commit is not supported yet!"
msgstr "memainkan ulang dari komit akar belum didukung!"
#: builtin/replay.c
msgid "replaying merge commits is not supported yet!"
msgstr "memainkan ulang komit penggabungan belum didukung!"
#: builtin/replay.c
#, c-format
msgid "failed to update ref '%s': %s"
msgstr "gagal memperbarui referensi '%s': %s"
#: builtin/replay.c
#, c-format
msgid "failed to commit ref transaction: %s"
msgstr "gagal mengkomit transaksi referensi: %s"
#: builtin/repo.c
#, c-format
msgid "key '%s' not found"
@ -15522,10 +15595,18 @@ msgstr "format keluaran"
msgid "synonym for --format=nul"
msgstr "sinonim untuk --format=nul"
#: builtin/repo.c
msgid "print all keys/values"
msgstr "cetak semua kunci/nilai"
#: builtin/repo.c
msgid "unsupported output format"
msgstr "format keluaran tidak didukung"
#: builtin/repo.c
msgid "--all and <key> cannot be used together"
msgstr "--all dan <kunci> tidak dapat digunakan bersamaan"
#: builtin/repo.c
msgid "References"
msgstr "Referensi"
@ -15566,6 +15647,14 @@ msgstr "Pohon"
msgid "Blobs"
msgstr "Blob"
#: builtin/repo.c
msgid "Inflated size"
msgstr "Ukuran yang berkembang"
#: builtin/repo.c
msgid "Disk size"
msgstr "Ukuran disk"
#: builtin/repo.c
msgid "Repository structure"
msgstr "Struktur repositori"
@ -17604,7 +17693,7 @@ msgstr "'%s' sudah ada di dalam indeks"
msgid "'%s' already exists in the index and is not a submodule"
msgstr "'%s' sudah ada di dalam indeks dan bukan submodul"
#: builtin/submodule--helper.c read-cache.c
#: builtin/submodule--helper.c object-file.c
#, c-format
msgid "'%s' does not have a commit checked out"
msgstr "'%s' tidak punya sebuah komit tercheckout"
@ -18674,6 +18763,11 @@ msgstr "tidak dapat mengurai kunci daftar bundel %s dengan nilai '%s'"
msgid "bundle list at '%s' has no mode"
msgstr "daftar bundel pada '%s' tidak punya mode"
#: bundle-uri.c
#, c-format
msgid "bundle list at '%s': bundle '%s' has no uri"
msgstr "daftar bundel pada '%s': bundel '%s' tidak punya uri"
#: bundle-uri.c
msgid "failed to create temporary file"
msgstr "tidak dapat membuat berkas sementara"
@ -18701,6 +18795,11 @@ msgstr "mode bundel tidak dikenal dari URI '%s'"
msgid "exceeded bundle URI recursion limit (%d)"
msgstr "batas rekursi URI bundel (%d) terlewati"
#: bundle-uri.c
#, c-format
msgid "bundle '%s' has no uri"
msgstr "bundel '%s' tidak punya uri"
#: bundle-uri.c
#, c-format
msgid "failed to download bundle from URI '%s'"
@ -19357,8 +19456,8 @@ msgid "Reuse recorded resolution of conflicted merges"
msgstr "Gunakan ulang resolusi konflik penggabungan terekam"
#: command-list.h
msgid "Reset current HEAD to the specified state"
msgstr "Setel ulang HEAD saat ini ke keadaan yang disebutkan"
msgid "Set `HEAD` or the index to a known state"
msgstr "Setel `HEAD` atau indeks ke keadaan yang diketahui"
#: command-list.h
msgid "Restore working tree files"
@ -21243,11 +21342,6 @@ msgstr ""
msgid "Unknown value for 'diff.submodule' config variable: '%s'"
msgstr "Nilai tidak dikenal untuk variabel konfigurasi 'diff.submodule': '%s'"
#: diff.c merge-ort.c transport.c
#, c-format
msgid "unknown value for config '%s': %s"
msgstr "nilai tidak dikenal untuk konfigurasi '%s': %s"
#: diff.c
#, c-format
msgid ""
@ -23871,6 +23965,10 @@ msgstr "pembacaan pendek ketika mengindeks %s"
msgid "%s: failed to insert into database"
msgstr "%s: gagal memasukkan ke dalam basis data"
#: object-file.c
msgid "cannot add a submodule of a different hash algorithm"
msgstr "tidak dapat menambahkan submodul dari algoritma hash yang berbeda"
#: object-file.c
#, c-format
msgid "%s: unsupported file type"
@ -25641,6 +25739,11 @@ msgstr "perintah ini menolak atom %%(%.*s)"
msgid "--format=%.*s cannot be used with --python, --shell, --tcl"
msgstr "--format=%.*s tidak dapat digunakan dengan --python, --shell, --tcl"
#: ref-filter.c
#, c-format
msgid "parse_object_buffer failed on %s for %s"
msgstr "parse_object_buffer gagal pada %s untuk %s"
#: ref-filter.c
msgid "failed to run 'describe'"
msgstr "gagal menjalankan 'describe'"
@ -25679,11 +25782,6 @@ msgstr "(tanpa cabang)"
msgid "missing object %s for %s"
msgstr "objek %s hilang untuk %s"
#: ref-filter.c
#, c-format
msgid "parse_object_buffer failed on %s for %s"
msgstr "parse_object_buffer gagal pada %s untuk %s"
#: ref-filter.c
#, c-format
msgid "malformed object at '%s'"
@ -26046,6 +26144,21 @@ msgstr "nama referensi %s tidak ditemukan"
msgid "refname %s is a symbolic ref, copying it is not supported"
msgstr "nama referensi %s simbolik, menyalinnya tidak didukung"
#: refs/reftable-backend.c
#, c-format
msgid "reftable stack for worktree '%s' is broken"
msgstr "tumpukan tabel referensi untuk pohon kerja '%s' rusak"
#: refs/reftable-backend.c
#, c-format
msgid "could not create iterator for worktree '%s'"
msgstr "tidak dapat membuat iterator untuk pohon kerja '%s'"
#: refs/reftable-backend.c
#, c-format
msgid "could not read record for worktree '%s'"
msgstr "tidak dapat membaca rekaman untuk pohon kerja '%s'"
#: refspec.c
#, c-format
msgid "pattern '%s' has no '*'"
@ -26559,6 +26672,10 @@ msgid "could not finish pack-objects to repack promisor objects"
msgstr ""
"tidak dapat menyelesaikan pack-objects untuk mengepak ulang objek pejanji"
#: repack-promisor.c
msgid "could not start pack-objects to repack promisor packs"
msgstr "tidak dapat memulai pack-objects untuk mengepak ulang pak pejanji"
#: repack.c
#, c-format
msgid "pack prefix %s does not begin with objdir %s"
@ -27784,11 +27901,6 @@ msgstr ""
msgid "illegal label name: '%.*s'"
msgstr "nama label ilegal: '%.*s'"
#: sequencer.c
#, c-format
msgid "could not resolve '%s'"
msgstr "tidak dapat menguraikan '%s'"
#: sequencer.c
msgid "writing fake root commit"
msgstr "menulis komit akar palsu"
@ -28373,57 +28485,83 @@ msgstr "format %s jelek: elemen '%s' tidak diakhiri dengan ')'"
msgid "bad %s format: %%%.*s"
msgstr "format %s jelek: %%%.*s"
#. TRANSLATORS: IEC 80000-13:2008 gibibyte
#: strbuf.c
#, c-format
msgid "%u.%2.2u GiB"
msgstr "%u.%2.2u gibibita"
msgid "%u.%2.2u"
msgstr "%u.%2.2u"
#. TRANSLATORS: IEC 80000-13:2008 gibibyte/second
#. TRANSLATORS: SI decimal prefix symbol for 10^9
#: strbuf.c
#, c-format
msgid "%u.%2.2u GiB/s"
msgstr "%u.%2.2u gibibita/detik"
msgid "G"
msgstr "G"
#. TRANSLATORS: IEC 80000-13:2008 mebibyte
#. TRANSLATORS: SI decimal prefix symbol for 10^6
#: strbuf.c
#, c-format
msgid "%u.%2.2u MiB"
msgstr "%u.%2.2u mebibita"
msgid "M"
msgstr "M"
#. TRANSLATORS: IEC 80000-13:2008 mebibyte/second
#. TRANSLATORS: SI decimal prefix symbol for 10^3
#: strbuf.c
#, c-format
msgid "%u.%2.2u MiB/s"
msgstr "%u.%2.2u mebibita/detik"
msgid "k"
msgstr "k"
#. TRANSLATORS: IEC 80000-13:2008 kibibyte
#. TRANSLATORS: IEC 80000-13:2008 gibibyte/second and gibibyte
#: strbuf.c
#, c-format
msgid "%u.%2.2u KiB"
msgstr "%u.%2.2u kibibita"
msgid "GiB/s"
msgstr "GiB/detik"
#. TRANSLATORS: IEC 80000-13:2008 kibibyte/second
#: strbuf.c
#, c-format
msgid "%u.%2.2u KiB/s"
msgstr "%u.%2.2u kibibita/detik"
msgid "GiB"
msgstr "GiB"
#. TRANSLATORS: IEC 80000-13:2008 byte
#. TRANSLATORS: IEC 80000-13:2008 mebibyte/second and mebibyte
#: strbuf.c
#, c-format
msgid "%u byte"
msgid_plural "%u bytes"
msgstr[0] "%u bita"
msgstr[1] "%u bita"
msgid "MiB/s"
msgstr "MiB/detik"
#: strbuf.c
msgid "MiB"
msgstr "MiB"
#. TRANSLATORS: IEC 80000-13:2008 kibibyte/second and kibibyte
#: strbuf.c
msgid "KiB/s"
msgstr "KiB/detik"
#: strbuf.c
msgid "KiB"
msgstr "KiB"
#. TRANSLATORS: IEC 80000-13:2008 byte/second and byte
#: strbuf.c
msgid "B/s"
msgstr "B/detik"
#: strbuf.c
msgid "B"
msgstr "B"
#. TRANSLATORS: IEC 80000-13:2008 byte/second
#: strbuf.c
msgid "byte/s"
msgid_plural "bytes/s"
msgstr[0] "bita/detik"
msgstr[1] "bita/detik"
#. TRANSLATORS: IEC 80000-13:2008 byte
#: strbuf.c
msgid "byte"
msgid_plural "bytes"
msgstr[0] "bita"
msgstr[1] "bita"
#. TRANSLATORS: The first argument is the number string. The second
#. argument is the unit string (i.e. "12.34 MiB/s").
#.
#: strbuf.c
#, c-format
msgid "%u byte/s"
msgid_plural "%u bytes/s"
msgstr[0] "%u bita/detik"
msgstr[1] "%u bita/detik"
msgid "%s %s"
msgstr "%s %s"
#: submodule-config.c
#, c-format
@ -28789,10 +28927,6 @@ msgstr "jumlah bita"
msgid "number of requests per thread"
msgstr "jumlah permintaan tiap utas"
#: t/helper/test-simple-ipc.c
msgid "byte"
msgstr "bita"
#: t/helper/test-simple-ipc.c
msgid "ballast character"
msgstr "karakter pemberat"

484
po/sv.po
View File

@ -1,14 +1,14 @@
# Swedish translations for Git.
# Copyright (C) 2010-2025 Peter Krefting <peter@softwolves.pp.se>
# Copyright (C) 2010-2026 Peter Krefting <peter@softwolves.pp.se>
# This file is distributed under the same license as the Git package.
# Peter Krefting <peter@softwolves.pp.se>, 2010-2025.
# Peter Krefting <peter@softwolves.pp.se>, 2010-2026.
#
msgid ""
msgstr ""
"Project-Id-Version: git 2.52.0\n"
"Project-Id-Version: git 2.53.0\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
"POT-Creation-Date: 2025-11-06 23:58+0000\n"
"PO-Revision-Date: 2025-11-07 15:54+0100\n"
"POT-Creation-Date: 2026-01-22 23:57+0000\n"
"PO-Revision-Date: 2026-01-27 19:33+0100\n"
"Last-Translator: Peter Krefting <peter@softwolves.pp.se>\n"
"Language-Team: Svenska <tp-sv@listor.tp-sv.se>\n"
"Language: sv\n"
@ -552,7 +552,7 @@ msgstr ""
"j - gå till nästa obestämda stycke, börja om vid slutet\n"
"J - gå till nästa stycke, börja om vid slutet\n"
"k - gå till föregående obestämda stycke, börja om vid början\n"
"K - gå till föregående styckem, börja om vid början\n"
"K - gå till föregående stycken, börja om vid början\n"
"g - välj ett stycke att gå till\n"
"/ - sök efter stycke som motsvarar angivet reguljärt uttryck\n"
"s - dela aktuellt stycke i mindre styckens\n"
@ -1733,8 +1733,8 @@ msgstr ""
msgid "'%s' is not a valid branch name"
msgstr "”%s” är inte ett giltigt grennamn"
msgid "See `man git check-ref-format`"
msgstr "Se ”man git check-ref-format”"
msgid "See 'git help check-ref-format'"
msgstr "Se ”git help check-ref-format”"
#, c-format
msgid "a branch named '%s' already exists"
@ -2627,6 +2627,16 @@ msgstr "förväntade en färg: %s"
msgid "must end with a color"
msgstr "måste sluta med en färg"
#, c-format
msgid "unknown value for config '%s': %s"
msgstr "okänt värde för inställningen ”%s”: %s"
msgid ""
"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
"\"histogram\""
msgstr ""
"flaggan diff-algorithm godtar ”myers”, ”minimal”, ”patience” och ”histogram”"
#, c-format
msgid "cannot find revision %s to ignore"
msgstr "kan inte hitta revision %s att ignorera"
@ -2679,6 +2689,12 @@ msgstr "visa författarens e-post istället för namn (Standard: av)"
msgid "ignore whitespace differences"
msgstr "ignorera ändringar i blanksteg"
msgid "<algorithm>"
msgstr "<algoritm>"
msgid "choose a diff algorithm"
msgstr "välj en diff-algoritm"
msgid "rev"
msgstr "incheckning"
@ -2694,8 +2710,8 @@ msgstr "färglägg redundant metadata från tidigare rader annorlunda"
msgid "color lines by age"
msgstr "färglägg rader efter ålder"
msgid "spend extra cycles to find better match"
msgstr "slösa extra cykler med att hitta bättre träff"
msgid "spend extra cycles to find a better match"
msgstr "slösa extra cykler med att hitta en bättre träff"
msgid "use revisions from <file> instead of calling git-rev-list"
msgstr "använd revisioner från <fil> istället för att anropa git-rev-list"
@ -3877,8 +3893,8 @@ msgid "missing branch name; try -%c"
msgstr "grennamn saknas; försök med -%c"
#, c-format
msgid "could not resolve %s"
msgstr "kunde inte upplösa %s"
msgid "could not resolve '%s'"
msgstr "kunde inte upplösa %s"
msgid "invalid path specification"
msgstr "felaktig sökvägsangivelse"
@ -5341,10 +5357,16 @@ msgstr "--append kan inte användas med --value=<mönster>"
#, c-format
msgid ""
"cannot overwrite multiple values with a single value\n"
" Use a regexp, --add or --replace-all to change %s."
" Use --value=<pattern>, --append or --all to change %s."
msgstr ""
"kan inte skriva över flera värden med ett ensamt värde\n"
" Använd en regexp, --add eller --replace-all för att ändra %s."
" Använd --value=<mönster>, --append eller --all för att ändra %s."
msgid "unset all multi-valued config options"
msgstr "ta bort alla värden för konfigurationsflagga med flera värden"
msgid "unset multi-valued config options with matching values"
msgstr "ta bort konfigurationsflagga med flera värden för träffade värden"
#, c-format
msgid "no such section: %s"
@ -5429,6 +5451,14 @@ msgstr "--default gäller bara för --get"
msgid "--comment is only applicable to add/set/replace operations"
msgstr "--comment gäller bara för ”get”/”set”/”replace”-operationerna"
#, c-format
msgid ""
"cannot overwrite multiple values with a single value\n"
" Use a regexp, --add or --replace-all to change %s."
msgstr ""
"kan inte skriva över flera värden med ett ensamt värde\n"
" Använd en regexp, --add eller --replace-all för att ändra %s."
msgid "print sizes in human readable format"
msgstr "skriv storlekar i människoläsbart format"
@ -5788,7 +5818,7 @@ msgstr "git fast-export [<rev-list-flaggor>]"
#, c-format
msgid "unknown %s mode: %s"
msgstr "okänd läge för %s: %s"
msgstr "okänt läge för %s: %s"
#, c-format
msgid "unknown tag-of-filtered mode: %s"
@ -5830,14 +5860,8 @@ msgid ""
"encountered commit-specific encoding %.*s in commit %s; use --reencode=[yes|"
"no] to handle it"
msgstr ""
"påträffade incheckningsspecifik teckenkodning %.*s i incheckningen %s; "
"använd --reencode=[yes|no] för att hantera den"
#, c-format
msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
msgstr ""
"påträffade en signerad incheckning %s; använd --signed-commits=<läge> för "
"att hantera den"
"påträffade den incheckningsspecifika teckenkodningen %.*s i incheckningen "
"%s; använd --reencode=[yes|no] för att hantera den"
#, c-format
msgid "exporting %<PRIuMAX> signature(s) for commit %s"
@ -5847,6 +5871,19 @@ msgstr "exporterar %<PRIuMAX> signatur(er) för incheckningen %s"
msgid "stripping signature(s) from commit %s"
msgstr "tar bort signatur(er) från incheckning %s"
#, c-format
msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
msgstr ""
"påträffade den signerade incheckningen %s; använd --signed-commits=<läge> "
"för att hantera den"
msgid ""
"'strip-if-invalid' is not a valid mode for git fast-export with --signed-"
"commits=<mode>"
msgstr ""
"”strip-if-invalid” är inte ett giltigt läge för git fast-export med --signed-"
"commits=<läge>"
#, c-format
msgid ""
"omitting tag %s,\n"
@ -5859,12 +5896,6 @@ msgstr ""
msgid "could not read tag %s"
msgstr "kunde inte läsa taggen %s"
#, c-format
msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
msgstr ""
"påträffade signerade taggen %s; använd --signed-tags=<läge> för att hantera "
"den"
#, c-format
msgid "exporting signed tag %s"
msgstr "exporterar signerad tagg %s"
@ -5873,6 +5904,19 @@ msgstr "exporterar signerad tagg %s"
msgid "stripping signature from tag %s"
msgstr "tar bort signatur från taggen %s"
#, c-format
msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
msgstr ""
"påträffade den signerade taggen %s; använd --signed-tags=<läge> för att "
"hantera den"
msgid ""
"'strip-if-invalid' is not a valid mode for git fast-export with --signed-"
"tags=<mode>"
msgstr ""
"”strip-if-invalid” är inte ett giltigt läge för git fast-export med --signed-"
"tags=<läge>"
#, c-format
msgid ""
"tag %s tags unexported object; use --tag-of-filtered-object=<mode> to handle "
@ -6261,6 +6305,33 @@ msgstr "multipla %s-signaturer hittade, ignorerar ytterligare signatur"
msgid "parse_one_signature() returned unknown hash algo"
msgstr "parse_one_signature() returnerade okänd hashningsalgoritm"
msgid "unknown"
msgstr "okänd"
#, c-format
msgid ""
"stripping invalid signature for commit '%.100s...'\n"
" allegedly by %s"
msgstr ""
"tar bort ogiltig signatur från incheckning ”%.100s...”\n"
" påstås vara av %s"
#, c-format
msgid ""
"stripping invalid signature for commit '%.*s'\n"
" allegedly by %s"
msgstr ""
"tar bort ogiltig signatur från incheckning ”%.*s”\n"
" påstås vara av %s"
#, c-format
msgid ""
"stripping invalid signature for commit\n"
" allegedly by %s"
msgstr ""
"tar bort ogiltig signatur från incheckning\n"
" påstås vara av %s"
msgid "expected committer but didn't get one"
msgstr "förväntade incheckare men fick ingen"
@ -6275,10 +6346,6 @@ msgstr "tar bort en incheckningssignatur"
msgid "importing a commit signature verbatim"
msgstr "importerar en incheckningssignatur oförändrad"
msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
msgstr ""
"upptäckte en signerad tagg; använd --signed-tags=<läge> för att hantera den"
#, c-format
msgid "importing a tag signature verbatim for tag '%s'"
msgstr "importerar en taggsignatur oförändrad för taggen ”%s”"
@ -6287,6 +6354,17 @@ msgstr "importerar en taggsignatur oförändrad för taggen ”%s”"
msgid "stripping a tag signature for tag '%s'"
msgstr "tar bort en taggsignatur för taggen ”%s”"
msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
msgstr ""
"upptäckte en signerad tagg; använd --signed-tags=<läge> för att hantera den"
msgid ""
"'strip-if-invalid' is not a valid mode for git fast-import with --signed-"
"tags=<mode>"
msgstr ""
"”strip-if-invalid” är inte ett giltigt läge för git fast-import med --signed-"
"tags=<läge>"
#, c-format
msgid "expected 'from' command, got '%s'"
msgstr "förväntade ”from”-kommando, fick %s"
@ -6443,8 +6521,8 @@ msgstr "git fetch [<flaggor>] [<arkiv> [<refspec>...]]"
msgid "git fetch [<options>] <group>"
msgstr "git fetch [<flaggor>] <grupp>"
msgid "git fetch --multiple [<options>] [(<repository> | <group>)...]"
msgstr "git fetch --multiple [<flaggor>] [(<arkiv> | <grupp>)...]"
msgid "git fetch --multiple [<options>] [(<repository>|<group>)...]"
msgstr "git fetch --multiple [<flaggor>] [(<arkiv>|<grupp>)...]"
msgid "git fetch --all [<options>]"
msgstr "git fetch --all [<flaggor>]"
@ -6912,9 +6990,6 @@ msgstr "saknar --config=<konfig>"
msgid "got bad config --config=%s"
msgstr "fick felaktig konfiguration --config=%s"
msgid "unknown"
msgstr "okänd"
#. TRANSLATORS: e.g. error in tree 01bfda: <more explanation>
#, c-format
msgid "error in %s %s: %s"
@ -7013,6 +7088,10 @@ msgstr "%s: ogiltig sha1-pekare %s"
msgid "%s: not a commit"
msgstr "%s: inte en incheckning!"
#, c-format
msgid "invalid parameter: expected sha1, got '%s'"
msgstr "ogiltig parameter: förväntade sha1, fick ”%s”"
msgid "notice: No default references"
msgstr "obs: Inga förvalda referenser"
@ -7038,26 +7117,6 @@ msgstr "Kontrollerar objektkatalog"
msgid "Checking object directories"
msgstr "Kontrollerar objektkataloger"
#, c-format
msgid "Checking %s link"
msgstr "Kontrollerar %s-länk"
#, c-format
msgid "invalid %s"
msgstr "ogiltigt %s"
#, c-format
msgid "%s points to something strange (%s)"
msgstr "%s pekar på något konstigt (%s)"
#, c-format
msgid "%s: detached HEAD points at nothing"
msgstr "%s: frånkopplat HEAD pekar på ingenting"
#, c-format
msgid "notice: %s points to an unborn branch (%s)"
msgstr "obs: %s pekar på en ofödd gren (%s)"
#, c-format
msgid "Checking cache tree of %s"
msgstr "Kontrollerar cacheträd för %s"
@ -7139,14 +7198,6 @@ msgstr "kontrollerar referensdatabasens konsistens"
msgid "Checking objects"
msgstr "Kontrollerar objekt"
#, c-format
msgid "%s: object missing"
msgstr "%s: objekt saknas"
#, c-format
msgid "invalid parameter: expected sha1, got '%s'"
msgstr "ogiltig parameter: förväntade sha1, fick ”%s”"
msgid "git fsmonitor--daemon start [<options>]"
msgstr "git fsmonitor--daemon start [<flaggor>]"
@ -7523,6 +7574,9 @@ msgstr "misslyckades uppdatera underhållsschema"
msgid "failed to add repo to global config"
msgstr "misslyckades lägga till arkiv till global konfiguration"
msgid "check a specific task"
msgstr "kontrollera en specifik uppgift"
msgid "git maintenance <subcommand> [<options>]"
msgstr "git maintenance <underkommando> [<flaggor>]"
@ -7971,6 +8025,10 @@ msgstr "ogiltigt blob-objekt %s"
msgid "fsck error in packed object"
msgstr "fsck-fel i packat objekt"
#, c-format
msgid "invalid %s"
msgstr "ogiltigt %s"
#, c-format
msgid "Not all child objects of %s are reachable"
msgstr "Inte alla barnobjekt för %s kan nås"
@ -8110,6 +8168,9 @@ msgstr "--stdin kräver ett git-arkiv"
msgid "--verify with no packfile name given"
msgstr "--verify angavs utan paketfilnamn"
msgid "cannot perform queued object checks outside of a repository"
msgstr "kan inte utföra köade objektkontroller utanför ett arkiv"
msgid "fsck error in pack objects"
msgstr "fsck-fel i packat objekt"
@ -8361,7 +8422,7 @@ msgid "insane in-reply-to: %s"
msgstr "tokigt in-reply-to: %s"
msgid "git format-patch [<options>] [<since> | <revision-range>]"
msgstr "git format-patch [<flaggor>] [<sedan> | <revisionsintervall>]"
msgstr "git format-patch [<flaggor>] [<sedan> | <revisions-intervall>]"
msgid "two output directories?"
msgstr "två utdatakataloger?"
@ -8852,12 +8913,6 @@ msgstr ""
"git merge-file [<alternativ>] [-L <namn1> [-L <orig> [-L <namn2>]]] <fil1> "
"<origfil> <fil2>"
msgid ""
"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
"\"histogram\""
msgstr ""
"flaggan diff-algorithm godtar ”myers”, ”minimal”, ”patience” och ”histogram”"
msgid "send results to standard output"
msgstr "sänd resultat till standard ut"
@ -8870,12 +8925,6 @@ msgstr "använd diff3-baserad sammanslagning"
msgid "use a zealous diff3 based merge"
msgstr "använd nitisk diff3-baserad sammanslagning"
msgid "<algorithm>"
msgstr "<algoritm>"
msgid "choose a diff algorithm"
msgstr "välj en diff-algoritm"
msgid "for conflicts, use this marker size"
msgstr "för konflikter, använd denna markörstorlek"
@ -9942,6 +9991,10 @@ msgstr ""
msgid "could not get type of object %s in pack %s"
msgstr "kunde inte hämta typ för objektet %s i paketet %s"
#, c-format
msgid "packfile %s is a promisor but --exclude-promisor-objects was given"
msgstr "packfilen %s är ett kontrakt men --exclude-promisor-objects angavs"
#, c-format
msgid "could not find pack '%s'"
msgstr "kunde inte hitta paketet ”%s”"
@ -10199,11 +10252,11 @@ msgstr "git pack-refs "
msgid "git patch-id [--stable | --unstable | --verbatim]"
msgstr "git patch-id [--stable | --unstable | --verbatim]"
msgid "use the unstable patch-id algorithm"
msgstr "använd den instabila patch-id-algoritmen"
msgid "use the unstable patch ID algorithm"
msgstr "använd den instabila patch ID-algoritmen"
msgid "use the stable patch-id algorithm"
msgstr "använd den stabila patch-id-algoritmen"
msgid "use the stable patch ID algorithm"
msgstr "använd den stabila patch ID-algoritmen"
msgid "don't strip whitespace from the patch"
msgstr "ta inte bort blanksteg från patchen"
@ -10226,39 +10279,6 @@ msgstr "kan inte rensa i ett ”precious-objekt”-arkiv"
msgid "git pull [<options>] [<repository> [<refspec>...]]"
msgstr "git pull [<flaggor>] [<arkiv> [<refspec>...]]"
msgid "control for recursive fetching of submodules"
msgstr "styrning för rekursiv hämtning av undermoduler"
msgid "Options related to merging"
msgstr "Alternativ gällande sammanslagning"
msgid "incorporate changes by rebasing rather than merging"
msgstr "inlemma ändringar genom ombasering i stället för sammanslagning"
msgid "allow fast-forward"
msgstr "tillåt snabbspolning"
msgid "control use of pre-merge-commit and commit-msg hooks"
msgstr "styr användning av pre-merge-commit- och commit-msg-krokar"
msgid "automatically stash/stash pop before and after"
msgstr "utför automatiskt stash/stash pop före och efter"
msgid "Options related to fetching"
msgstr "Alternativ gällande hämtningar"
msgid "force overwrite of local branch"
msgstr "tvinga överskrivning av lokal gren"
msgid "number of submodules pulled in parallel"
msgstr "antal undermoduler som hämtas parallellt"
msgid "use IPv4 addresses only"
msgstr "använd endast IPv4-adresser"
msgid "use IPv6 addresses only"
msgstr "använd endast IPv6-adresser"
msgid ""
"There is no candidate for rebasing against among the refs that you just "
"fetched."
@ -10361,6 +10381,39 @@ msgstr ""
"eller --ff-only på kommandoraden för att överstyra det konfigurerade\n"
"förvalet vid körning.\n"
msgid "control for recursive fetching of submodules"
msgstr "styrning för rekursiv hämtning av undermoduler"
msgid "Options related to merging"
msgstr "Alternativ gällande sammanslagning"
msgid "incorporate changes by rebasing rather than merging"
msgstr "inlemma ändringar genom ombasering i stället för sammanslagning"
msgid "allow fast-forward"
msgstr "tillåt snabbspolning"
msgid "control use of pre-merge-commit and commit-msg hooks"
msgstr "styr användning av pre-merge-commit- och commit-msg-krokar"
msgid "automatically stash/stash pop before and after"
msgstr "utför automatiskt stash/stash pop före och efter"
msgid "Options related to fetching"
msgstr "Alternativ gällande hämtningar"
msgid "force overwrite of local branch"
msgstr "tvinga överskrivning av lokal gren"
msgid "number of submodules pulled in parallel"
msgstr "antal undermoduler som hämtas parallellt"
msgid "use IPv4 addresses only"
msgstr "använd endast IPv4-adresser"
msgid "use IPv6 addresses only"
msgstr "använd endast IPv6-adresser"
msgid "Updating an unborn branch with changes added to the index."
msgstr "Uppdaterar en ofödd gren med ändringar som lagts till i indexet."
@ -11344,7 +11397,7 @@ msgstr "Markerar nåbara objekt..."
#, c-format
msgid "reflog could not be found: '%s'"
msgstr "refernsloggen hittades inte: ”%s”"
msgstr "referensloggen hittades inte: ”%s”"
msgid "no reflog specified to delete"
msgstr "ingen referenslogg att ta bort angavs"
@ -12206,6 +12259,10 @@ msgstr "--convert-graft-file tar inga argument"
msgid "only one pattern can be given with -l"
msgstr "endast ett mönster kan anges med -l"
#, c-format
msgid "'%s' is not a valid commit-ish for %s"
msgstr "”%s” är inte en giltig incheckning-igt för %s"
msgid "need some commits to replay"
msgstr "behöver några incheckningar för omspelning"
@ -12222,27 +12279,16 @@ msgstr ""
"kan inte flytta målet framåt när det finns flera källor eftersom ordningen "
"inte kan fastställas"
msgid ""
"cannot implicitly determine whether this is an --advance or --onto operation"
msgstr ""
"kan inte avgöra om den underförstådda processen är --advance eller --onto"
msgid ""
"cannot advance target with multiple source branches because ordering would "
"be ill-defined"
msgstr ""
"kan inte flytta målet framåt när det finns flera källgrenar eftersom "
"ordningen inte kan fastställas"
msgid "cannot implicitly determine correct base for --onto"
msgstr "kan inte avgöra den underförstådda basen för --onto"
#, c-format
msgid "invalid %s value: '%s'"
msgstr "ogiltigt värde för %s: ”%s”"
msgid ""
"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
"<branch>) <revision-range>..."
"<branch>) [--ref-action[=<mode>]] <revision-range>"
msgstr ""
"(EXPERIMENTELLT!) git replay ([--contained] --onto <nybas> | --advance "
"<gren>) <revisions-intervall>..."
"<gren>) [--ref-action[=<läge>]] <revisions-intervall>"
msgid "make replay advance given branch"
msgstr "låt omspelningen flytta den givna grenen framåt"
@ -12250,8 +12296,12 @@ msgstr "låt omspelningen flytta den givna grenen framåt"
msgid "replay onto given commit"
msgstr "spela om ovanpå en given incheckning"
msgid "advance all branches contained in revision-range"
msgstr "flytta alla grenar som finns i revisionsintervallet framåt"
msgid "update all branches that point at commits in <revision-range>"
msgstr ""
"uppdatera alla grenar som pekar på incheckningar i <revisions-intervall>"
msgid "control ref update behavior (update|print)"
msgstr "styr beteende för referensuppdatering (update|print)"
msgid "option --onto or --advance is mandatory"
msgstr "flaggan --onto eller --advance måste anges"
@ -12264,15 +12314,27 @@ msgstr ""
"några flaggor för revisionstraversering kommer överstyras eftersom ”%s”-"
"biten i ”struct rev_info” kommer att tvingas"
#, c-format
msgid "failed to begin ref transaction: %s"
msgstr "misslyckades påbörja ref-transaktion: %s"
msgid "error preparing revisions"
msgstr "fel när revisioner skulle förberedas"
msgid "replaying down to root commit is not supported yet!"
msgstr "kan ännu inte spela om hela vägen ned till rotincheckningen!"
msgid "replaying down from root commit is not supported yet!"
msgstr "kan ännu inte spela om hela vägen ned från rotincheckningen!"
msgid "replaying merge commits is not supported yet!"
msgstr "kan ännu inte spela om sammanslagningsincheckningar!"
#, c-format
msgid "failed to update ref '%s': %s"
msgstr "misslyckades uppdatera referensen ”%s”: %s"
#, c-format
msgid "failed to commit ref transaction: %s"
msgstr "misslyckades checka in referenstransaktionen: %s"
#, c-format
msgid "key '%s' not found"
msgstr "nyckeln ”%s” hittades inte"
@ -12287,9 +12349,15 @@ msgstr "utdataformat"
msgid "synonym for --format=nul"
msgstr "synonym till --format=nul"
msgid "print all keys/values"
msgstr "visa alla nycklar/värden"
msgid "unsupported output format"
msgstr "utdataformatet stöds ej"
msgid "--all and <key> cannot be used together"
msgstr "--all och <nyckel> kan inte användas samtidigt"
msgid "References"
msgstr "Referenser"
@ -12320,6 +12388,12 @@ msgstr "Träd"
msgid "Blobs"
msgstr "Blob:ar"
msgid "Inflated size"
msgstr "Uppackad storlek"
msgid "Disk size"
msgstr "Diskstorlek"
msgid "Repository structure"
msgstr "Arkivstruktur"
@ -14786,6 +14860,10 @@ msgstr "kunde inte tolka listnyckeln %s med värdet ”%s”"
msgid "bundle list at '%s' has no mode"
msgstr "buntlistan på ”%s” har inget läge"
#, c-format
msgid "bundle list at '%s': bundle '%s' has no uri"
msgstr "buntlistan på ”%s”: bunten ”%s” har ingen uri"
msgid "failed to create temporary file"
msgstr "misslyckades skapa temporär fil"
@ -14807,6 +14885,10 @@ msgstr "okänt buntläge från URI:en ”%s”"
msgid "exceeded bundle URI recursion limit (%d)"
msgstr "överskred buntens URI-rekursionsgräns (%d)"
#, c-format
msgid "bundle '%s' has no uri"
msgstr "buntlistan ”%s” har ingen uri"
#, c-format
msgid "failed to download bundle from URI '%s'"
msgstr "misslyckades hämta bunt från URI:en ”%s”"
@ -15302,8 +15384,8 @@ msgstr "Skapar en sammanfattning av väntande ändringar"
msgid "Reuse recorded resolution of conflicted merges"
msgstr "Återanvänd sparad lösning av sammanslagningskonflikter"
msgid "Reset current HEAD to the specified state"
msgstr "Återställ aktuell HEAD till angivet tillstånd"
msgid "Set `HEAD` or the index to a known state"
msgstr "Sätt ”HEAD” eller indexet till ett känt tillstånd"
msgid "Restore working tree files"
msgstr "Återställ filer i arbetskatalogen"
@ -16811,10 +16893,6 @@ msgstr ""
msgid "Unknown value for 'diff.submodule' config variable: '%s'"
msgstr "Okänt värde för konfigurationsvariabeln ”diff.submodule”: ”%s”"
#, c-format
msgid "unknown value for config '%s': %s"
msgstr "okänt värde för inställningen ”%s”: %s"
#, c-format
msgid ""
"Found errors in 'diff.dirstat' config variable:\n"
@ -18921,6 +18999,9 @@ msgstr "för lite lästes vid indexering av %s"
msgid "%s: failed to insert into database"
msgstr "%s: misslyckades lägga in i databasen"
msgid "cannot add a submodule of a different hash algorithm"
msgstr "kan inte lägga till submodul med annan hashningsalgoritm"
#, c-format
msgid "%s: unsupported file type"
msgstr "%s: filtypen stöds ej"
@ -20371,6 +20452,10 @@ msgstr "kommandot förkastar atom %%(%.*s)"
msgid "--format=%.*s cannot be used with --python, --shell, --tcl"
msgstr "--format=%.*s kan inte användas med --python, --shell, --tcl"
#, c-format
msgid "parse_object_buffer failed on %s for %s"
msgstr "parse_object_buffer misslyckades på %s för %s"
msgid "failed to run 'describe'"
msgstr "misslyckades att köra ”describe”"
@ -20401,10 +20486,6 @@ msgstr "(ingen gren)"
msgid "missing object %s for %s"
msgstr "objektet %s saknas för %s"
#, c-format
msgid "parse_object_buffer failed on %s for %s"
msgstr "parse_object_buffer misslyckades på %s för %s"
#, c-format
msgid "malformed object at '%s'"
msgstr "felformat objekt vid ”%s”"
@ -20699,6 +20780,18 @@ msgstr "referensnamnet %s hittades inte"
msgid "refname %s is a symbolic ref, copying it is not supported"
msgstr "referensnamnet %s är en symbolisk referens, kopiering stöds inte"
#, c-format
msgid "reftable stack for worktree '%s' is broken"
msgstr "referensstacken för arbetskatalogen ”%s” är trasig"
#, c-format
msgid "could not create iterator for worktree '%s'"
msgstr "kunde inte skapa iterator för arbetskatalogen ”%s”"
#, c-format
msgid "could not read record for worktree '%s'"
msgstr "kunde inte läsa posten för arbetskatalogen ”%s”"
#, c-format
msgid "pattern '%s' has no '*'"
msgstr "mönstret ”%s” innehåller ingen ”*”"
@ -21116,6 +21209,9 @@ msgstr ""
msgid "could not finish pack-objects to repack promisor objects"
msgstr "kunde inte avsluta pack-objects för att packa om kontraktsobjekt"
msgid "could not start pack-objects to repack promisor packs"
msgstr "kunde inte starta pack-objects för att packa om kontraktspaket"
#, c-format
msgid "pack prefix %s does not begin with objdir %s"
msgstr "paketprefixet %s börjar inte med objkat %s"
@ -21904,7 +22000,7 @@ msgid ""
msgstr ""
"”reword” tar inte en sammanslagningsincheckning. Om du\n"
"ville spela upp sammanslagningen på nytt och ändra texten\n"
"i incheckningsmeddelandet använder du ”merge -C” på\n"
"i incheckningsmeddelandet använder du ”merge -c” på\n"
"incheckningen"
#. TRANSLATORS: 'edit', 'merge -C' and 'break' should
@ -22114,10 +22210,6 @@ msgstr ""
msgid "illegal label name: '%.*s'"
msgstr "ogiltigt etikettnamn: ”%.*s”"
#, c-format
msgid "could not resolve '%s'"
msgstr "kunde inte upplösa ”%s”"
msgid "writing fake root commit"
msgstr "skriver fejkad rotincheckning"
@ -22592,49 +22684,68 @@ msgstr "felaktigt %s-format: elementet ”%s” slutar inte med ”)”"
msgid "bad %s format: %%%.*s"
msgstr "felaktigt %s-format: %%%.*s"
#. TRANSLATORS: IEC 80000-13:2008 gibibyte
#, c-format
msgid "%u.%2.2u GiB"
msgstr "%u,%2.2u GiB"
msgid "%u.%2.2u"
msgstr "%u,%2.2u"
#. TRANSLATORS: IEC 80000-13:2008 gibibyte/second
#, c-format
msgid "%u.%2.2u GiB/s"
msgstr "%u,%2.2u GiB/s"
#. TRANSLATORS: SI decimal prefix symbol for 10^9
msgid "G"
msgstr "G"
#. TRANSLATORS: IEC 80000-13:2008 mebibyte
#, c-format
msgid "%u.%2.2u MiB"
msgstr "%u,%2.2u MiB"
#. TRANSLATORS: SI decimal prefix symbol for 10^6
msgid "M"
msgstr "M"
#. TRANSLATORS: IEC 80000-13:2008 mebibyte/second
#, c-format
msgid "%u.%2.2u MiB/s"
msgstr "%u,%2.2u MiB/s"
#. TRANSLATORS: SI decimal prefix symbol for 10^3
msgid "k"
msgstr "k"
#. TRANSLATORS: IEC 80000-13:2008 kibibyte
#, c-format
msgid "%u.%2.2u KiB"
msgstr "%u,%2.2u KiB"
#. TRANSLATORS: IEC 80000-13:2008 gibibyte/second and gibibyte
msgid "GiB/s"
msgstr "GiB/s"
#. TRANSLATORS: IEC 80000-13:2008 kibibyte/second
#, c-format
msgid "%u.%2.2u KiB/s"
msgstr "%u,%2.2u KiB/s"
msgid "GiB"
msgstr "GiB"
#. TRANSLATORS: IEC 80000-13:2008 byte
#, c-format
msgid "%u byte"
msgid_plural "%u bytes"
msgstr[0] "%u byte"
msgstr[1] "%u bytes"
#. TRANSLATORS: IEC 80000-13:2008 mebibyte/second and mebibyte
msgid "MiB/s"
msgstr "MiB/s"
msgid "MiB"
msgstr "MiB"
#. TRANSLATORS: IEC 80000-13:2008 kibibyte/second and kibibyte
msgid "KiB/s"
msgstr "KiB/s"
msgid "KiB"
msgstr "KiB"
#. TRANSLATORS: IEC 80000-13:2008 byte/second and byte
msgid "B/s"
msgstr "B/s"
msgid "B"
msgstr "B"
#. TRANSLATORS: IEC 80000-13:2008 byte/second
msgid "byte/s"
msgid_plural "bytes/s"
msgstr[0] "byte/s"
msgstr[1] "byte/s"
#. TRANSLATORS: IEC 80000-13:2008 byte
msgid "byte"
msgid_plural "bytes"
msgstr[0] "byte"
msgstr[1] "byte"
#. TRANSLATORS: The first argument is the number string. The second
#. argument is the unit string (i.e. "12.34 MiB/s").
#.
#, c-format
msgid "%u byte/s"
msgid_plural "%u bytes/s"
msgstr[0] "%u byte/s"
msgstr[1] "%u bytes/s"
msgid "%s %s"
msgstr "%s %s"
#, c-format
msgid "ignoring suspicious submodule name: %s"
@ -22926,9 +23037,6 @@ msgstr "antal byte"
msgid "number of requests per thread"
msgstr "antal frågor per tråd"
msgid "byte"
msgstr "byte"
msgid "ballast character"
msgstr "ballasttecken"

499
po/tr.po
View File

@ -97,8 +97,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Git Turkish Localization Project\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
"POT-Creation-Date: 2025-11-15 01:30+0300\n"
"PO-Revision-Date: 2025-11-15 02:00+0300\n"
"POT-Creation-Date: 2026-01-27 22:54+0300\n"
"PO-Revision-Date: 2026-01-27 22:00+0300\n"
"Last-Translator: Emir SARI <emir_sari@icloud.com>\n"
"Language-Team: Turkish <kde-i18n-doc@kde.org>\n"
"Language: tr\n"
@ -642,16 +642,16 @@ msgid ""
"P - print the current hunk using the pager\n"
"? - print help\n"
msgstr ""
"j - bu parça için sonra karar ver, bir sonraki karar verilmemiş parçayı gör\n"
"J - bu parça için sonra karar ver, bir sonraki parçayı gör\n"
"k - bu parça için sonra karar ver, bir önceki karar verilmemiş parçayı gör\n"
"K - bu parça için sonra karar ver, bir önceki parçayı gör\n"
"j - sonraki karar verilmemiş parçaya git, bitince başa dön\n"
"J - sonraki parçaya git, bitince başa dön\n"
"k - önceki karar verilmemiş parçaya git, bitince sona dön\n"
"K - önceki parçaya git, bitince sona dön\n"
"g - gidilecek bir parça seç\n"
"/ - verilen düzenli ifade ile eşleşen bir parça ara\n"
"s - geçerli parçayı daha ufak parçalara böl\n"
"e - geçerli parçayı elle düzenle\n"
"p - geçerli parçayı yazdır\n"
"P - geçerli sayfayı sayfalayıcı kullanarak yazdır\n"
"P - geçerli sayfayı sayfalayıcıyı kullanarak yazdır\n"
"? - yardımı yazdır\n"
#, c-format
@ -1821,26 +1821,26 @@ msgstr ""
msgid "'%s' is not a valid branch name"
msgstr "'%s' geçerli bir dal adı değil"
msgid "See `man git check-ref-format`"
msgstr "'man git check-ref-format' kılavuz sayfasına bakın"
msgid "See 'git help check-ref-format'"
msgstr "\"git help check-ref-format\" bölümüne bakın"
#, c-format
msgid "a branch named '%s' already exists"
msgstr "'%s' adında bir dal halihazırda var"
msgstr "\"%s\" adında bir dal halihazırda var"
#, c-format
msgid "cannot force update the branch '%s' used by worktree at '%s'"
msgstr ""
"şuradaki çalışma ağacı tarafından kullanılan '%s' dalı zorla "
"güncellenemiyor: '%s'"
"\"%2$s\" konumundaki çalışma ağacı tarafından kullanılan \"%1$s\" dalı zorla "
"güncellenemiyor"
#, c-format
msgid "cannot set up tracking information; starting point '%s' is not a branch"
msgstr "izleme bilgisi ayarlanamıyor; başlangıç noktası '%s' bir dal değil"
msgstr "izleme bilgisi ayarlanamıyor; başlangıç noktası \"%s\" bir dal değil"
#, c-format
msgid "the requested upstream branch '%s' does not exist"
msgstr "istenen üstkaynak dalı '%s' yok"
msgstr "istenen üstkaynak dalı \"%s\" yok"
msgid ""
"\n"
@ -2719,6 +2719,17 @@ msgstr "bir renk bekleniyor: %s"
msgid "must end with a color"
msgstr "bir renk ile bitmeli"
#, c-format
msgid "unknown value for config '%s': %s"
msgstr "'%s' yapılandırması için bilinmeyen değer: %s"
msgid ""
"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
"\"histogram\""
msgstr ""
"diff-algorithm seçeneği şunları kabul eder: \"myers\", \"minimal\", "
"\"patience\" ve \"histogram\""
#, c-format
msgid "cannot find revision %s to ignore"
msgstr "yok saymak için %s revizyonu bulunamıyor"
@ -2771,6 +2782,12 @@ msgstr "yazar adı yerine e-postasını göster (Öntanımlı: Kapalı)"
msgid "ignore whitespace differences"
msgstr "boşluk ayrımlarını yok say"
msgid "<algorithm>"
msgstr "<algoritma>"
msgid "choose a diff algorithm"
msgstr "bir diff algoritması seç"
msgid "rev"
msgstr "revizyon"
@ -2786,7 +2803,7 @@ msgstr "bir önceki dosyadan gereksiz üstveriyi başka biçimde renklendir"
msgid "color lines by age"
msgstr "satırları yaşına göre renklendir"
msgid "spend extra cycles to find better match"
msgid "spend extra cycles to find a better match"
msgstr "daha iyi eşleşme bulmak için ek döngüler harca"
msgid "use revisions from <file> instead of calling git-rev-list"
@ -3971,8 +3988,8 @@ msgid "missing branch name; try -%c"
msgstr "eksik dal adı; -%c deneyin"
#, c-format
msgid "could not resolve %s"
msgstr "%s çözülemedi"
msgid "could not resolve '%s'"
msgstr "'%s' çözülemedi"
msgid "invalid path specification"
msgstr "geçersiz yol belirtimi"
@ -5452,11 +5469,16 @@ msgstr "--append, --value=<dizgi> ile kullanılamaz"
#, c-format
msgid ""
"cannot overwrite multiple values with a single value\n"
" Use a regexp, --add or --replace-all to change %s."
" Use --value=<pattern>, --append or --all to change %s."
msgstr ""
"Tek bir değer ile birden çok değerin üzerine yazılamıyor.\n"
" %s değerini değiştirmek için bir düzenli ifade, --add veya --replace-"
"all kullanın."
" %s değişikliği için --value=<dizgi>, --append veya --all kullanın."
msgid "unset all multi-valued config options"
msgstr "birden çok değerli yapılandırma seçeneklerinin tüm değerlerini kaldır"
msgid "unset multi-valued config options with matching values"
msgstr "birden çok değerli yapılandırma seçeneğini eşleşen değerlerle değiştir"
#, c-format
msgid "no such section: %s"
@ -5542,6 +5564,15 @@ msgstr "--default yalnızca --get için uygulanabilir"
msgid "--comment is only applicable to add/set/replace operations"
msgstr "--comment yalnızca ekle/ayarla/değiştir işlemlerine uygulanabilir"
#, c-format
msgid ""
"cannot overwrite multiple values with a single value\n"
" Use a regexp, --add or --replace-all to change %s."
msgstr ""
"Tek bir değer ile birden çok değerin üzerine yazılamıyor.\n"
" %s değerini değiştirmek için bir düzenli ifade, --add veya --replace-"
"all kullanın."
msgid "print sizes in human readable format"
msgstr "yazdırma boyutları kişi tarafından okunabilir biçimde"
@ -5944,12 +5975,6 @@ msgstr ""
"şu işlemede, işlemeye özel %.*s kodlamasına denk gelindi; işlemek için --"
"reencode[yes|no] kullanın: %s"
#, c-format
msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
msgstr ""
"imzalanmış %s işlemesine denk gelindi; işlemek için --signed-commits=<kip> "
"kullanın"
#, c-format
msgid "exporting %<PRIuMAX> signature(s) for commit %s"
msgstr "şu işleme için %<PRIuMAX> imza dışa aktarılıyor: %s"
@ -5958,6 +5983,19 @@ msgstr "şu işleme için %<PRIuMAX> imza dışa aktarılıyor: %s"
msgid "stripping signature(s) from commit %s"
msgstr "%s işlemesinden imzalar soyuluyor"
#, c-format
msgid "encountered signed commit %s; use --signed-commits=<mode> to handle it"
msgstr ""
"imzalanmış %s işlemesine denk gelindi; işlemek için --signed-commits=<kip> "
"kullanın"
msgid ""
"'strip-if-invalid' is not a valid mode for git fast-export with --signed-"
"commits=<mode>"
msgstr ""
"\"strip-if-invalid\", git fast-export için --signed-commits=<kip> ile "
"geçerli bir kip değil"
#, c-format
msgid ""
"omitting tag %s,\n"
@ -5970,12 +6008,6 @@ msgstr ""
msgid "could not read tag %s"
msgstr "%s etiketi okunamadı"
#, c-format
msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
msgstr ""
"imzalanmış %s etiketinee denk gelindi; işlemek için --signed-tags=<kip> "
"kullanın"
#, c-format
msgid "exporting signed tag %s"
msgstr "imzalanmış %s etiketi dışa aktarılıyor"
@ -5984,6 +6016,19 @@ msgstr "imzalanmış %s etiketi dışa aktarılıyor"
msgid "stripping signature from tag %s"
msgstr "%s etiketinden imza soyuluyor"
#, c-format
msgid "encountered signed tag %s; use --signed-tags=<mode> to handle it"
msgstr ""
"imzalanmış %s etiketinee denk gelindi; işlemek için --signed-tags=<kip> "
"kullanın"
msgid ""
"'strip-if-invalid' is not a valid mode for git fast-export with --signed-"
"tags=<mode>"
msgstr ""
"\"strip-if-invalid\", git fast-export için --signed-tags=<kip> ile geçerli "
"bir kip değil"
#, c-format
msgid ""
"tag %s tags unexported object; use --tag-of-filtered-object=<mode> to handle "
@ -6374,6 +6419,33 @@ msgstr "birden çok %s imzası bulundu, ek imzalar yok sayılıyor"
msgid "parse_one_signature() returned unknown hash algo"
msgstr "parse_one_signature(), bilinmeyen bir sağlama algoritması döndürdü"
msgid "unknown"
msgstr "bilinmeyen"
#, c-format
msgid ""
"stripping invalid signature for commit '%.100s...'\n"
" allegedly by %s"
msgstr ""
"\"%.100s...\" işlemesi için olan geçersiz imzalar soyuluyor;\n"
" görünüşe göre %s tarafından"
#, c-format
msgid ""
"stripping invalid signature for commit '%.*s'\n"
" allegedly by %s"
msgstr ""
"\"%.*s...\" işlemesi için olan geçersiz imza soyuluyor;\n"
" görünüşe göre %s tarafından"
#, c-format
msgid ""
"stripping invalid signature for commit\n"
" allegedly by %s"
msgstr ""
"işleme için olan geçersiz imza soyuluyor;\n"
" görünüşe göre %s tarafından"
msgid "expected committer but didn't get one"
msgstr "işlemeci bekleniyordu; ancak bir tane bulunamadı"
@ -6387,10 +6459,6 @@ msgstr "bir işleme imzası soyuluyor"
msgid "importing a commit signature verbatim"
msgstr "bir işleme imzası olduğu gibi içe aktarılıyor"
msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
msgstr ""
"imzalanmış etikete denk gelindi; işlemek için --signed-tags=<kip> kullanın"
#, c-format
msgid "importing a tag signature verbatim for tag '%s'"
msgstr "\"%s\" etiketi için bir etiket imzası olduğu gibi içe aktarılıyor"
@ -6399,6 +6467,17 @@ msgstr "\"%s\" etiketi için bir etiket imzası olduğu gibi içe aktarılıyor"
msgid "stripping a tag signature for tag '%s'"
msgstr "\"%s\" etiketi için bir etiket imzası soyuluyor"
msgid "encountered signed tag; use --signed-tags=<mode> to handle it"
msgstr ""
"imzalanmış etikete denk gelindi; işlemek için --signed-tags=<kip> kullanın"
msgid ""
"'strip-if-invalid' is not a valid mode for git fast-import with --signed-"
"tags=<mode>"
msgstr ""
"\"strip-if-invalid\", git fast-import için --signed-tags=<kip> ile geçerli "
"bir kip değil"
#, c-format
msgid "expected 'from' command, got '%s'"
msgstr "\"from\" komutu bekleniyordu, \"%s\" alındı"
@ -6555,8 +6634,8 @@ msgstr "git fetch [<seçenekler>] [<depo> [<bşvr-blrtç>...]]"
msgid "git fetch [<options>] <group>"
msgstr "git fetch [<seçenekler>] <grup>"
msgid "git fetch --multiple [<options>] [(<repository> | <group>)...]"
msgstr "git fetch --multiple [<seçenekler>] [(<depo> | <grup>)...]"
msgid "git fetch --multiple [<options>] [(<repository>|<group>)...]"
msgstr "git fetch --multiple [<seçenekler>] [(<depo>|<grup>)...]"
msgid "git fetch --all [<options>]"
msgstr "git fetch --all [<seçenekler>]"
@ -7031,9 +7110,6 @@ msgstr "--config=<yapılandırma> eksik"
msgid "got bad config --config=%s"
msgstr "hatayı yapılandırma alındı, --config=%s"
msgid "unknown"
msgstr "bilinmeyen"
#. TRANSLATORS: e.g. error in tree 01bfda: <more explanation>
#, c-format
msgid "error in %s %s: %s"
@ -7128,6 +7204,10 @@ msgstr "%s: geçersiz sha1 işaretçisi %s"
msgid "%s: not a commit"
msgstr "%s: bir işleme değil"
#, c-format
msgid "invalid parameter: expected sha1, got '%s'"
msgstr "geçersiz parametre: sha1 bekleniyordu, '%s' alındı"
msgid "notice: No default references"
msgstr "Uyarı: Öntanımlı başvurular yok"
@ -7153,26 +7233,6 @@ msgstr "Nesne dizini denetleniyor"
msgid "Checking object directories"
msgstr "Nesne dizinleri denetleniyor"
#, c-format
msgid "Checking %s link"
msgstr "%s bağ denetleniyor"
#, c-format
msgid "invalid %s"
msgstr "geçersiz %s"
#, c-format
msgid "%s points to something strange (%s)"
msgstr "%s garip bir şeye işaret ediyor (%s)"
#, c-format
msgid "%s: detached HEAD points at nothing"
msgstr "%s: ayrık HEAD bir şeye işaret etmiyor"
#, c-format
msgid "notice: %s points to an unborn branch (%s)"
msgstr "Uyarı: %s henüz doğmamış bir dala işaret ediyor (%s)"
#, c-format
msgid "Checking cache tree of %s"
msgstr "%s ögesinin önbellek ağacı denetleniyor"
@ -7252,14 +7312,6 @@ msgstr "başvuru veritabanı tutarlılığını denetle"
msgid "Checking objects"
msgstr "Nesneler denetleniyor"
#, c-format
msgid "%s: object missing"
msgstr "%s: nesne kayıp"
#, c-format
msgid "invalid parameter: expected sha1, got '%s'"
msgstr "geçersiz parametre: sha1 bekleniyordu, '%s' alındı"
msgid "git fsmonitor--daemon start [<options>]"
msgstr "git fsmonitor--daemon start [<seçenekler>]"
@ -7637,6 +7689,9 @@ msgstr "bakım programı ayarlanamadı"
msgid "failed to add repo to global config"
msgstr "depo, global yapılandırmaya eklenemedi"
msgid "check a specific task"
msgstr "belirli bir görevi denetle"
msgid "git maintenance <subcommand> [<options>]"
msgstr "git maintenance <altkomut> [<seçenekler>]"
@ -8091,6 +8146,10 @@ msgstr "geçersiz %s ikili nesnesi"
msgid "fsck error in packed object"
msgstr "paketlenmiş nesne içinde fsck hatası"
#, c-format
msgid "invalid %s"
msgstr "geçersiz %s"
#, c-format
msgid "Not all child objects of %s are reachable"
msgstr "%s ögesinin tüm alt ögeleri ulaşılabilir değil"
@ -8231,6 +8290,9 @@ msgstr "--stdin bir git dizini gerektirir"
msgid "--verify with no packfile name given"
msgstr "--verify ile bir paket dosyası adı verilmedi"
msgid "cannot perform queued object checks outside of a repository"
msgstr "depo dışında kuyruğa alınmış nesne denetimleri gerçekleştirilemez"
msgid "fsck error in pack objects"
msgstr "paket nesnelerinde fsck hatası"
@ -8978,13 +9040,6 @@ msgstr ""
"git merge-file [<seçenekler>] [-L <ad1> [-L <orij> [-L <ad2>]]] <dosya1> "
"<orij-dosya> <dosya2>"
msgid ""
"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
"\"histogram\""
msgstr ""
"diff-algorithm seçeneği şunları kabul eder: \"myers\", \"minimal\", "
"\"patience\" ve \"histogram\""
msgid "send results to standard output"
msgstr "sonuçları standart çıktıya gönder"
@ -8997,12 +9052,6 @@ msgstr "diff3 tabanlı birleştirme kullan"
msgid "use a zealous diff3 based merge"
msgstr "gayretli bir diff3 tabanlı birleştirme kullan"
msgid "<algorithm>"
msgstr "<algoritma>"
msgid "choose a diff algorithm"
msgstr "bir diff algoritması seç"
msgid "for conflicts, use this marker size"
msgstr "çakışmalarda bu imleyici boyutunu kullan"
@ -10066,6 +10115,10 @@ msgstr ""
msgid "could not get type of object %s in pack %s"
msgstr "%s nesnesinin türü alınamıyor (%s paketinde)"
#, c-format
msgid "packfile %s is a promisor but --exclude-promisor-objects was given"
msgstr "paket dosyası %s bir vaatçi; ancak --exclude-promisor-objects verildi"
#, c-format
msgid "could not find pack '%s'"
msgstr "'%s' paketi bulunamadı"
@ -10323,10 +10376,10 @@ msgstr "git pack-refs "
msgid "git patch-id [--stable | --unstable | --verbatim]"
msgstr "git patch-id [--stable | --unstable | --verbatim]"
msgid "use the unstable patch-id algorithm"
msgstr "kararlı olmayan yama kimliği algoritmasını kullan"
msgid "use the unstable patch ID algorithm"
msgstr "kararsız yama kimliği algoritmasını kullan"
msgid "use the stable patch-id algorithm"
msgid "use the stable patch ID algorithm"
msgstr "kararlı yama kimliği algoritmasını kullan"
msgid "don't strip whitespace from the patch"
@ -10351,39 +10404,6 @@ msgstr "bir precious-objects deposu içinde budama yapılamıyor"
msgid "git pull [<options>] [<repository> [<refspec>...]]"
msgstr "git pull [<seçenekler>] [<depo> [<bşvr-blrtç>...]]"
msgid "control for recursive fetching of submodules"
msgstr "altmodüllerin özyineli getirilmesi için denetleme"
msgid "Options related to merging"
msgstr "Birleştirme ile ilgili seçenekler"
msgid "incorporate changes by rebasing rather than merging"
msgstr "değişiklikleri birleştirme yerine yeniden temellendirme ile kat"
msgid "allow fast-forward"
msgstr "ileri sarıma izin ver"
msgid "control use of pre-merge-commit and commit-msg hooks"
msgstr "pre-merge-commit ve commit-msg kancalarının kullanımını denetle"
msgid "automatically stash/stash pop before and after"
msgstr "öncesinde ve sonrasında kendiliğinden zulala/zulaları patlat"
msgid "Options related to fetching"
msgstr "Getirme ile ilgili seçenekler"
msgid "force overwrite of local branch"
msgstr "zorla yerel dalın üzerine yaz"
msgid "number of submodules pulled in parallel"
msgstr "paralelde çekilen altmodüllerin sayısı"
msgid "use IPv4 addresses only"
msgstr "yalnızca IPv4 adresleri kullan"
msgid "use IPv6 addresses only"
msgstr "yalnızca IPv6 adresleri kullan"
msgid ""
"There is no candidate for rebasing against among the refs that you just "
"fetched."
@ -10485,6 +10505,39 @@ msgstr ""
"yapılandırmayı yürütme sırasında --rebase, --no-rebase veya\n"
"--ff-only ile bir kerelik geçersiz kılabilirsiniz.\n"
msgid "control for recursive fetching of submodules"
msgstr "altmodüllerin özyineli getirilmesi için denetleme"
msgid "Options related to merging"
msgstr "Birleştirme ile ilgili seçenekler"
msgid "incorporate changes by rebasing rather than merging"
msgstr "değişiklikleri birleştirme yerine yeniden temellendirme ile kat"
msgid "allow fast-forward"
msgstr "ileri sarıma izin ver"
msgid "control use of pre-merge-commit and commit-msg hooks"
msgstr "pre-merge-commit ve commit-msg kancalarının kullanımını denetle"
msgid "automatically stash/stash pop before and after"
msgstr "öncesinde ve sonrasında kendiliğinden zulala/zulaları patlat"
msgid "Options related to fetching"
msgstr "Getirme ile ilgili seçenekler"
msgid "force overwrite of local branch"
msgstr "zorla yerel dalın üzerine yaz"
msgid "number of submodules pulled in parallel"
msgstr "paralelde çekilen altmodüllerin sayısı"
msgid "use IPv4 addresses only"
msgstr "yalnızca IPv4 adresleri kullan"
msgid "use IPv6 addresses only"
msgstr "yalnızca IPv6 adresleri kullan"
msgid "Updating an unborn branch with changes added to the index."
msgstr "İndekse eklenen değişikliklerle henüz doğmamış bir dal güncelleniyor."
@ -12346,6 +12399,10 @@ msgstr "--convert-graft-file argüman almaz"
msgid "only one pattern can be given with -l"
msgstr "-l ile yalnızca bir dizgi verilebilir"
#, c-format
msgid "'%s' is not a valid commit-ish for %s"
msgstr "\"%s\", %s için geçerli bir işlememsi değil"
msgid "need some commits to replay"
msgstr "yeniden oynatmak için birkaç işleme gerekli"
@ -12362,27 +12419,16 @@ msgstr ""
"birden çok kaynaklı hedef ilerletilemiyor; çünkü sıralama hatalı tanımlanmış "
"olurdu"
msgid ""
"cannot implicitly determine whether this is an --advance or --onto operation"
msgstr ""
"bunun --advance veya --onto işlemi olup olmadığı örtük olarak algılanamıyor"
msgid ""
"cannot advance target with multiple source branches because ordering would "
"be ill-defined"
msgstr ""
"birden çok kaynak dallı hedef ilerletilemiyor; çünkü sıralama hatalı "
"tanımlanmış olurdu"
msgid "cannot implicitly determine correct base for --onto"
msgstr "--onto için olan doğru temel örtük olarak algılanamıyor"
#, c-format
msgid "invalid %s value: '%s'"
msgstr "geçersiz %s değeri: \"%s\""
msgid ""
"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
"<branch>) <revision-range>..."
"<branch>) [--ref-action[=<mode>]] <revision-range>"
msgstr ""
"(DENEYSEL!) git replay ([--contained] --onto <yeni-temel> | --advance <dal>) "
"<revizyon-erimi>..."
"[--ref-action[=<kip>]] <revizyon-erimi>..."
msgid "make replay advance given branch"
msgstr "verilen dalı önceden yeniden oynat"
@ -12390,8 +12436,11 @@ msgstr "verilen dalı önceden yeniden oynat"
msgid "replay onto given commit"
msgstr "verilen işlemeye yeniden oynat"
msgid "advance all branches contained in revision-range"
msgstr "revizyon eriminde içerilen tüm dalları ilerlet"
msgid "update all branches that point at commits in <revision-range>"
msgstr "<revizyon-erimi>'ndeki işlemelere işaret eden tüm dalları güncelle"
msgid "control ref update behavior (update|print)"
msgstr "başvuru güncelleme davranışını denetle (update|print)"
msgid "option --onto or --advance is mandatory"
msgstr "--onto veya --advance seçeneğinin kullanımı zorunlu"
@ -12404,15 +12453,27 @@ msgstr ""
"'struct rev_info' içindeki '%s' biti zorlanacağından kimi revizyon yürütme "
"seçenekleri geçersiz kılınacak"
#, c-format
msgid "failed to begin ref transaction: %s"
msgstr "başvuru işlemine başlanılamadı: %s"
msgid "error preparing revisions"
msgstr "revizyonlar hazırlanırken hata"
msgid "replaying down to root commit is not supported yet!"
msgstr "kök işlemeye kadar yeniden oynatma henüz desteklenmiyor!"
msgid "replaying down from root commit is not supported yet!"
msgstr "kök işlemeden aşağı yeniden oynatma henüz desteklenmiyor!"
msgid "replaying merge commits is not supported yet!"
msgstr "birleştirme işlemelerini yeniden oynatma henüz desteklenmiyor!"
#, c-format
msgid "failed to update ref '%s': %s"
msgstr "\"%s\" başvurusu güncellenemedi: %s"
#, c-format
msgid "failed to commit ref transaction: %s"
msgstr "başvuru işlemi işlenemedi: %s"
#, c-format
msgid "key '%s' not found"
msgstr "'%s' anahtarı bulunamadı"
@ -12427,9 +12488,15 @@ msgstr "çıktı biçimi"
msgid "synonym for --format=nul"
msgstr "--format=nul eşanlamlısı"
msgid "print all keys/values"
msgstr "tüm anahtarları/değerleri yazdır"
msgid "unsupported output format"
msgstr "desteklenmeyen çıktı biçimi"
msgid "--all and <key> cannot be used together"
msgstr "--all ve <anahtar> birlikte kullanılamaz"
msgid "References"
msgstr "Başvurular"
@ -12460,6 +12527,12 @@ msgstr "Ağaçlar"
msgid "Blobs"
msgstr "İkili geniş nesneler"
msgid "Inflated size"
msgstr "Şişirilmiş boyut"
msgid "Disk size"
msgstr "Disk boyutu"
msgid "Repository structure"
msgstr "Depo yapısı"
@ -14920,11 +14993,15 @@ msgstr "yalnızca hata ayıklama için yararlı"
#, c-format
msgid "could not parse bundle list key %s with value '%s'"
msgstr "demet liste anahtarı %s ile '%s' değeri ayrıştırılamıyor"
msgstr "demet liste anahtarı %s ile \"%s\" değeri ayrıştırılamıyor"
#, c-format
msgid "bundle list at '%s' has no mode"
msgstr "'%s' konumundaki demet listesinin kipi yok"
msgstr "\"%s\" konumundaki demet listesinin kipi yok"
#, c-format
msgid "bundle list at '%s': bundle '%s' has no uri"
msgstr "\"%s\" konumundaki demet: \"%s\" demetinde URI yok"
msgid "failed to create temporary file"
msgstr "geçici dosya oluşturulamadı"
@ -14947,17 +15024,21 @@ msgstr "'%s' URI'sinden tanımlanamayan demet kipi"
msgid "exceeded bundle URI recursion limit (%d)"
msgstr "demet URI özyineleme sınırııldı (%d)"
#, c-format
msgid "bundle '%s' has no uri"
msgstr "\"%s\" demetinde URI yok"
#, c-format
msgid "failed to download bundle from URI '%s'"
msgstr "'%s' URI'sinden demet indirilemedi"
msgstr "\"%s\" URI'sinden demet indirilemedi"
#, c-format
msgid "file at URI '%s' is not a bundle or bundle list"
msgstr "'%s' URI'sindeki dosya bir demet veya demet listesi değil"
msgstr "\"%s\" URI'sindeki dosya bir demet veya demet listesi değil"
#, c-format
msgid "bundle-uri: unexpected argument: '%s'"
msgstr "bundle-uri: beklenmedik argüman: '%s'"
msgstr "bundle-uri: beklenmedik argüman: \"%s\""
msgid "bundle-uri: expected flush after arguments"
msgstr "bundle-uri: argümanlardan sonra floş bekleniyordu"
@ -15439,8 +15520,8 @@ msgstr "Bekleyen değişikliklerin bir özetini çıkart"
msgid "Reuse recorded resolution of conflicted merges"
msgstr "Çakışmaların kayıtlı çözümlerini yeniden kullan"
msgid "Reset current HEAD to the specified state"
msgstr "Geçerli HEAD'i belirtilen duruma sıfırla"
msgid "Set `HEAD` or the index to a known state"
msgstr "\"HEAD\"i veya indeksi bilinen bir duruma ayarla"
msgid "Restore working tree files"
msgstr "Çalışma ağacı dosyalarını eski durumuna getir"
@ -16950,10 +17031,6 @@ msgstr ""
msgid "Unknown value for 'diff.submodule' config variable: '%s'"
msgstr "'diff.submodule' yapılandırma değişkeni için bilinmeyen değer: '%s'"
#, c-format
msgid "unknown value for config '%s': %s"
msgstr "'%s' yapılandırması için bilinmeyen değer: %s"
#, c-format
msgid ""
"Found errors in 'diff.dirstat' config variable:\n"
@ -19065,6 +19142,9 @@ msgstr "%s indekslenirken kısa read"
msgid "%s: failed to insert into database"
msgstr "%s: veritabanına ekleme başarısız"
msgid "cannot add a submodule of a different hash algorithm"
msgstr "başka bir sağlama algoritmalı altmodül eklenemiyor"
#, c-format
msgid "%s: unsupported file type"
msgstr "%s: desteklenmeyen dosya türü"
@ -20510,6 +20590,10 @@ msgstr "bu komut atom %%(%.*s) reddediyor"
msgid "--format=%.*s cannot be used with --python, --shell, --tcl"
msgstr "--format=%.*s, --python, --shell ve --tcl ile kullanılamaz"
#, c-format
msgid "parse_object_buffer failed on %s for %s"
msgstr "parse_object_buffer %s üzerinde başarısız oldu (%s için)"
msgid "failed to run 'describe'"
msgstr "'describe' çalıştırılamadı"
@ -20540,10 +20624,6 @@ msgstr "(dal yok)"
msgid "missing object %s for %s"
msgstr "eksik nesne %s (%s için)"
#, c-format
msgid "parse_object_buffer failed on %s for %s"
msgstr "parse_object_buffer %s üzerinde başarısız oldu (%s için)"
#, c-format
msgid "malformed object at '%s'"
msgstr "'%s' konumunda hatalı oluşturulmuş nesne"
@ -20844,17 +20924,29 @@ msgstr "başvuru adı %s bulunamadı"
msgid "refname %s is a symbolic ref, copying it is not supported"
msgstr "başvuru adı %s bir sembolik bağ, onu kopyalamak desteklenmiyor"
#, c-format
msgid "reftable stack for worktree '%s' is broken"
msgstr "\"%s\" çalışma ağacı için başvuru tablosu yığını bozuk"
#, c-format
msgid "could not create iterator for worktree '%s'"
msgstr "\"%s\" çalışma ağacı için yineleyici oluşturulamadı"
#, c-format
msgid "could not read record for worktree '%s'"
msgstr "\"%s\" çalışma ağacı için kayıt okunamadı"
#, c-format
msgid "pattern '%s' has no '*'"
msgstr "'%s' dizgisinde '*' yok"
msgstr "\"%s\" dizgisinde \"*\" yok"
#, c-format
msgid "replacement '%s' has no '*'"
msgstr "'%s' yedeğinde '*' yok"
msgstr "\"%s\" ikamesinde \"*\" yok"
#, c-format
msgid "invalid quoting in push-option value: '%s'"
msgstr "push-option değerinde geçersiz tırnak içine alım: '%s'"
msgstr "push-option değerinde geçersiz tırnak içine alım: \"%s\""
#, c-format
msgid "unknown value for object-format: %s"
@ -21267,6 +21359,9 @@ msgstr ""
msgid "could not finish pack-objects to repack promisor objects"
msgstr "vaatçi nesneleri yeniden paketleme için pack-objects bitirilemedi"
msgid "could not start pack-objects to repack promisor packs"
msgstr "vaatçi paketleri yeniden paketlemek üzere pack-objects başlatılamadı"
#, c-format
msgid "pack prefix %s does not begin with objdir %s"
msgstr "paket öneki %s, nesne dizini %s ile başlamıyor"
@ -22261,10 +22356,6 @@ msgstr ""
msgid "illegal label name: '%.*s'"
msgstr "izin verilmeyen etiket adı: '%.*s'"
#, c-format
msgid "could not resolve '%s'"
msgstr "'%s' çözülemedi"
msgid "writing fake root commit"
msgstr "sahte kök işlemesi yazılıyor"
@ -22739,49 +22830,68 @@ msgstr "hatalı %s biçimi: '%s' ögesi ')' ile sonlanmıyor"
msgid "bad %s format: %%%.*s"
msgstr "hatalı %s biçimi: %%%.*s"
#. TRANSLATORS: IEC 80000-13:2008 gibibyte
#, c-format
msgid "%u.%2.2u GiB"
msgstr "%u.%2.2u GiB"
msgid "%u.%2.2u"
msgstr "%u.%2.2u"
#. TRANSLATORS: IEC 80000-13:2008 gibibyte/second
#, c-format
msgid "%u.%2.2u GiB/s"
msgstr "%u.%2.2u GiB/sn"
#. TRANSLATORS: SI decimal prefix symbol for 10^9
msgid "G"
msgstr "G"
#. TRANSLATORS: IEC 80000-13:2008 mebibyte
#, c-format
msgid "%u.%2.2u MiB"
msgstr "%u.%2.2u MiB"
#. TRANSLATORS: SI decimal prefix symbol for 10^6
msgid "M"
msgstr "M"
#. TRANSLATORS: IEC 80000-13:2008 mebibyte/second
#, c-format
msgid "%u.%2.2u MiB/s"
msgstr "%u.%2.2u MiB/sn"
#. TRANSLATORS: SI decimal prefix symbol for 10^3
msgid "k"
msgstr "k"
#. TRANSLATORS: IEC 80000-13:2008 kibibyte
#, c-format
msgid "%u.%2.2u KiB"
msgstr "%u.%2.2u KiB"
#. TRANSLATORS: IEC 80000-13:2008 gibibyte/second and gibibyte
msgid "GiB/s"
msgstr "GiB/sn"
#. TRANSLATORS: IEC 80000-13:2008 kibibyte/second
#, c-format
msgid "%u.%2.2u KiB/s"
msgstr "%u.%2.2u KiB/sn"
msgid "GiB"
msgstr "GiB"
#. TRANSLATORS: IEC 80000-13:2008 byte
#, c-format
msgid "%u byte"
msgid_plural "%u bytes"
msgstr[0] "%u bayt"
msgstr[1] "%u bayt"
#. TRANSLATORS: IEC 80000-13:2008 mebibyte/second and mebibyte
msgid "MiB/s"
msgstr "MiB/sn"
msgid "MiB"
msgstr "MiB"
#. TRANSLATORS: IEC 80000-13:2008 kibibyte/second and kibibyte
msgid "KiB/s"
msgstr "KiB/sn"
msgid "KiB"
msgstr "KiB"
#. TRANSLATORS: IEC 80000-13:2008 byte/second and byte
msgid "B/s"
msgstr "B/sn"
msgid "B"
msgstr "B"
#. TRANSLATORS: IEC 80000-13:2008 byte/second
msgid "byte/s"
msgid_plural "bytes/s"
msgstr[0] "bayt/sn"
msgstr[1] "bayt/sn"
#. TRANSLATORS: IEC 80000-13:2008 byte
msgid "byte"
msgid_plural "bytes"
msgstr[0] "bayt"
msgstr[1] "bayt"
#. TRANSLATORS: The first argument is the number string. The second
#. argument is the unit string (i.e. "12.34 MiB/s").
#.
#, c-format
msgid "%u byte/s"
msgid_plural "%u bytes/s"
msgstr[0] "%u bayt/sn"
msgstr[1] "%u bayt/sn"
msgid "%s %s"
msgstr "%s %s"
#, c-format
msgid "ignoring suspicious submodule name: %s"
@ -23072,9 +23182,6 @@ msgstr "bayt sayısı"
msgid "number of requests per thread"
msgstr "iş parçacığı başına düşen istek sayısı"
msgid "byte"
msgstr "bayt"
msgid "ballast character"
msgstr "dengeleyici karakter"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -479,7 +479,7 @@ int ie_modified(struct index_state *istate,
* So let's just special-case symlinks with a target path length
* (i.e. `sd_size`) of 4096 and force them to be re-checked.
*/
(!S_ISLNK(st->st_mode) || ce->ce_stat_data.sd_size != MAX_LONG_PATH) &&
(!S_ISLNK(st->st_mode) || ce->ce_stat_data.sd_size != MAX_PATH) &&
#endif
(S_ISGITLINK(ce->ce_mode) || ce->ce_stat_data.sd_size != 0))
return changed;
@ -3820,7 +3820,7 @@ void overlay_tree_on_index(struct index_state *istate,
if (repo_get_oid(the_repository, tree_name, &oid))
die("tree-ish %s not found.", tree_name);
tree = parse_tree_indirect(&oid);
tree = repo_parse_tree_indirect(the_repository, &oid);
if (!tree)
die("bad tree-ish %s", tree_name);

View File

@ -66,45 +66,54 @@ void pack_geometry_init(struct pack_geometry *geometry,
if (p->is_cruft)
continue;
ALLOC_GROW(geometry->pack,
geometry->pack_nr + 1,
geometry->pack_alloc);
if (p->pack_promisor) {
ALLOC_GROW(geometry->promisor_pack,
geometry->promisor_pack_nr + 1,
geometry->promisor_pack_alloc);
geometry->pack[geometry->pack_nr] = p;
geometry->pack_nr++;
geometry->promisor_pack[geometry->promisor_pack_nr] = p;
geometry->promisor_pack_nr++;
} else {
ALLOC_GROW(geometry->pack,
geometry->pack_nr + 1,
geometry->pack_alloc);
geometry->pack[geometry->pack_nr] = p;
geometry->pack_nr++;
}
}
QSORT(geometry->pack, geometry->pack_nr, pack_geometry_cmp);
QSORT(geometry->promisor_pack, geometry->promisor_pack_nr, pack_geometry_cmp);
strbuf_release(&buf);
}
void pack_geometry_split(struct pack_geometry *geometry)
static uint32_t compute_pack_geometry_split(struct packed_git **pack, size_t pack_nr,
int split_factor)
{
uint32_t i;
uint32_t split;
off_t total_size = 0;
if (!geometry->pack_nr) {
geometry->split = geometry->pack_nr;
return;
}
if (!pack_nr)
return 0;
/*
* First, count the number of packs (in descending order of size) which
* already form a geometric progression.
*/
for (i = geometry->pack_nr - 1; i > 0; i--) {
struct packed_git *ours = geometry->pack[i];
struct packed_git *prev = geometry->pack[i - 1];
for (i = pack_nr - 1; i > 0; i--) {
struct packed_git *ours = pack[i];
struct packed_git *prev = pack[i - 1];
if (unsigned_mult_overflows(geometry->split_factor,
if (unsigned_mult_overflows(split_factor,
pack_geometry_weight(prev)))
die(_("pack %s too large to consider in geometric "
"progression"),
prev->pack_name);
if (pack_geometry_weight(ours) <
geometry->split_factor * pack_geometry_weight(prev))
split_factor * pack_geometry_weight(prev))
break;
}
@ -130,21 +139,19 @@ void pack_geometry_split(struct pack_geometry *geometry)
* the geometric progression.
*/
for (i = 0; i < split; i++) {
struct packed_git *p = geometry->pack[i];
struct packed_git *p = pack[i];
if (unsigned_add_overflows(total_size, pack_geometry_weight(p)))
die(_("pack %s too large to roll up"), p->pack_name);
total_size += pack_geometry_weight(p);
}
for (i = split; i < geometry->pack_nr; i++) {
struct packed_git *ours = geometry->pack[i];
for (i = split; i < pack_nr; i++) {
struct packed_git *ours = pack[i];
if (unsigned_mult_overflows(geometry->split_factor,
total_size))
if (unsigned_mult_overflows(split_factor, total_size))
die(_("pack %s too large to roll up"), ours->pack_name);
if (pack_geometry_weight(ours) <
geometry->split_factor * total_size) {
if (pack_geometry_weight(ours) < split_factor * total_size) {
if (unsigned_add_overflows(total_size,
pack_geometry_weight(ours)))
die(_("pack %s too large to roll up"),
@ -156,7 +163,16 @@ void pack_geometry_split(struct pack_geometry *geometry)
break;
}
geometry->split = split;
return split;
}
void pack_geometry_split(struct pack_geometry *geometry)
{
geometry->split = compute_pack_geometry_split(geometry->pack, geometry->pack_nr,
geometry->split_factor);
geometry->promisor_split = compute_pack_geometry_split(geometry->promisor_pack,
geometry->promisor_pack_nr,
geometry->split_factor);
}
struct packed_git *pack_geometry_preferred_pack(struct pack_geometry *geometry)
@ -194,17 +210,18 @@ struct packed_git *pack_geometry_preferred_pack(struct pack_geometry *geometry)
return NULL;
}
void pack_geometry_remove_redundant(struct pack_geometry *geometry,
struct string_list *names,
struct existing_packs *existing,
const char *packdir)
static void remove_redundant_packs(struct packed_git **pack,
uint32_t pack_nr,
struct string_list *names,
struct existing_packs *existing,
const char *packdir)
{
const struct git_hash_algo *algop = existing->repo->hash_algo;
struct strbuf buf = STRBUF_INIT;
uint32_t i;
for (i = 0; i < geometry->split; i++) {
struct packed_git *p = geometry->pack[i];
for (i = 0; i < pack_nr; i++) {
struct packed_git *p = pack[i];
if (string_list_has_string(names, hash_to_hex_algop(p->hash,
algop)))
continue;
@ -223,10 +240,22 @@ void pack_geometry_remove_redundant(struct pack_geometry *geometry,
strbuf_release(&buf);
}
void pack_geometry_remove_redundant(struct pack_geometry *geometry,
struct string_list *names,
struct existing_packs *existing,
const char *packdir)
{
remove_redundant_packs(geometry->pack, geometry->split,
names, existing, packdir);
remove_redundant_packs(geometry->promisor_pack, geometry->promisor_split,
names, existing, packdir);
}
void pack_geometry_release(struct pack_geometry *geometry)
{
if (!geometry)
return;
free(geometry->pack);
free(geometry->promisor_pack);
}

View File

@ -34,39 +34,17 @@ static int write_oid(const struct object_id *oid,
return 0;
}
void repack_promisor_objects(struct repository *repo,
const struct pack_objects_args *args,
struct string_list *names, const char *packtmp)
static void finish_repacking_promisor_objects(struct repository *repo,
struct child_process *cmd,
struct string_list *names,
const char *packtmp)
{
struct write_oid_context ctx;
struct child_process cmd = CHILD_PROCESS_INIT;
FILE *out;
struct strbuf line = STRBUF_INIT;
FILE *out;
prepare_pack_objects(&cmd, args, packtmp);
cmd.in = -1;
close(cmd->in);
/*
* NEEDSWORK: Giving pack-objects only the OIDs without any ordering
* hints may result in suboptimal deltas in the resulting pack. See if
* the OIDs can be sent with fake paths such that pack-objects can use a
* {type -> existing pack order} ordering when computing deltas instead
* of a {type -> size} ordering, which may produce better deltas.
*/
ctx.cmd = &cmd;
ctx.algop = repo->hash_algo;
for_each_packed_object(repo, write_oid, &ctx,
FOR_EACH_OBJECT_PROMISOR_ONLY);
if (cmd.in == -1) {
/* No packed objects; cmd was never started */
child_process_clear(&cmd);
return;
}
close(cmd.in);
out = xfdopen(cmd.out, "r");
out = xfdopen(cmd->out, "r");
while (strbuf_getline_lf(&line, out) != EOF) {
struct string_list_item *item;
char *promisor_name;
@ -96,7 +74,66 @@ void repack_promisor_objects(struct repository *repo,
}
fclose(out);
if (finish_command(&cmd))
if (finish_command(cmd))
die(_("could not finish pack-objects to repack promisor objects"));
strbuf_release(&line);
}
void repack_promisor_objects(struct repository *repo,
const struct pack_objects_args *args,
struct string_list *names, const char *packtmp)
{
struct write_oid_context ctx;
struct child_process cmd = CHILD_PROCESS_INIT;
prepare_pack_objects(&cmd, args, packtmp);
cmd.in = -1;
/*
* NEEDSWORK: Giving pack-objects only the OIDs without any ordering
* hints may result in suboptimal deltas in the resulting pack. See if
* the OIDs can be sent with fake paths such that pack-objects can use a
* {type -> existing pack order} ordering when computing deltas instead
* of a {type -> size} ordering, which may produce better deltas.
*/
ctx.cmd = &cmd;
ctx.algop = repo->hash_algo;
for_each_packed_object(repo, write_oid, &ctx,
FOR_EACH_OBJECT_PROMISOR_ONLY);
if (cmd.in == -1) {
/* No packed objects; cmd was never started */
child_process_clear(&cmd);
return;
}
finish_repacking_promisor_objects(repo, &cmd, names, packtmp);
}
void pack_geometry_repack_promisors(struct repository *repo,
const struct pack_objects_args *args,
const struct pack_geometry *geometry,
struct string_list *names,
const char *packtmp)
{
struct child_process cmd = CHILD_PROCESS_INIT;
FILE *in;
if (!geometry->promisor_split)
return;
prepare_pack_objects(&cmd, args, packtmp);
strvec_push(&cmd.args, "--stdin-packs");
cmd.in = -1;
if (start_command(&cmd))
die(_("could not start pack-objects to repack promisor packs"));
in = xfdopen(cmd.in, "w");
for (size_t i = 0; i < geometry->promisor_split; i++)
fprintf(in, "%s\n", pack_basename(geometry->promisor_pack[i]));
for (size_t i = geometry->promisor_split; i < geometry->promisor_pack_nr; i++)
fprintf(in, "^%s\n", pack_basename(geometry->promisor_pack[i]));
fclose(in);
finish_repacking_promisor_objects(repo, &cmd, names, packtmp);
}

View File

@ -103,9 +103,19 @@ struct pack_geometry {
uint32_t pack_nr, pack_alloc;
uint32_t split;
struct packed_git **promisor_pack;
uint32_t promisor_pack_nr, promisor_pack_alloc;
uint32_t promisor_split;
int split_factor;
};
void pack_geometry_repack_promisors(struct repository *repo,
const struct pack_objects_args *args,
const struct pack_geometry *geometry,
struct string_list *names,
const char *packtmp);
void pack_geometry_init(struct pack_geometry *geometry,
struct existing_packs *existing,
const struct pack_objects_args *args);

View File

@ -100,6 +100,9 @@ void prepare_repo_settings(struct repository *r)
*/
if (!repo_config_get_int(r, "index.version", &value))
r->settings.index_version = value;
repo_cfg_int(r, "core.maxtreedepth",
&r->settings.max_allowed_tree_depth,
DEFAULT_MAX_ALLOWED_TREE_DEPTH);
if (!repo_config_get_string_tmp(r, "core.untrackedcache", &strval)) {
int v = git_parse_maybe_bool(strval);

View File

@ -67,6 +67,8 @@ struct repo_settings {
size_t packed_git_limit;
unsigned long big_file_threshold;
int max_allowed_tree_depth;
char *hooks_path;
};
#define REPO_SETTINGS_INIT { \
@ -78,6 +80,7 @@ struct repo_settings {
.delta_base_cache_limit = DEFAULT_DELTA_BASE_CACHE_LIMIT, \
.packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE, \
.packed_git_limit = DEFAULT_PACKED_GIT_LIMIT, \
.max_allowed_tree_depth = DEFAULT_MAX_ALLOWED_TREE_DEPTH, \
}
void prepare_repo_settings(struct repository *r);

View File

@ -163,7 +163,7 @@ int reset_head(struct repository *r, const struct reset_head_opts *opts)
goto leave_reset_head;
}
tree = parse_tree_indirect(oid);
tree = repo_parse_tree_indirect(the_repository, oid);
if (!tree) {
ret = error(_("unable to read tree (%s)"), oid_to_hex(oid));
goto leave_reset_head;

View File

@ -72,7 +72,7 @@ static void mark_tree_contents_uninteresting(struct repository *r,
struct tree_desc desc;
struct name_entry entry;
if (parse_tree_gently(tree, 1) < 0)
if (repo_parse_tree_gently(the_repository, tree, 1) < 0)
return;
init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);
@ -179,7 +179,7 @@ static void add_children_by_path(struct repository *r,
if (!tree)
return;
if (parse_tree_gently(tree, 1) < 0)
if (repo_parse_tree_gently(the_repository, tree, 1) < 0)
return;
init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);

View File

@ -767,7 +767,7 @@ static int do_recursive_merge(struct repository *r,
o.buffer_output = 2;
o.show_rename_progress = 1;
head_tree = parse_tree_indirect(head);
head_tree = repo_parse_tree_indirect(the_repository, head);
if (!head_tree)
return error(_("unable to read tree (%s)"), oid_to_hex(head));
next_tree = next ? repo_get_commit_tree(r, next) : empty_tree(r);
@ -4044,7 +4044,7 @@ static int do_reset(struct repository *r,
goto cleanup;
}
tree = parse_tree_indirect(&oid);
tree = repo_parse_tree_indirect(the_repository, &oid);
if (!tree)
return error(_("unable to read tree (%s)"), oid_to_hex(&oid));
prime_cache_tree(r, r->index, tree);

View File

@ -41,7 +41,7 @@ int cmd__cache_tree(int argc, const char **argv)
die(_("unable to read index file"));
oidcpy(&oid, &the_repository->index->cache_tree->oid);
tree = parse_tree_indirect(&oid);
tree = repo_parse_tree_indirect(the_repository, &oid);
if (!tree)
die(_("not a tree object: %s"), oid_to_hex(&oid));

View File

@ -19,10 +19,10 @@ int cmd__match_trees(int ac UNUSED, const char **av)
die("cannot parse %s as an object name", av[1]);
if (repo_get_oid(the_repository, av[2], &hash2))
die("cannot parse %s as an object name", av[2]);
one = parse_tree_indirect(&hash1);
one = repo_parse_tree_indirect(the_repository, &hash1);
if (!one)
die("not a tree-ish %s", av[1]);
two = parse_tree_indirect(&hash2);
two = repo_parse_tree_indirect(the_repository, &hash2);
if (!two)
die("not a tree-ish %s", av[2]);

View File

@ -2,6 +2,12 @@
. ./test-lib.sh
if test -n "$NO_CVS_TESTS"
then
skip_all='skipping git cvs tests, NO_CVS_TESTS defined'
test_done
fi
unset CVS_SERVER
if ! type cvs >/dev/null 2>&1

View File

@ -16,6 +16,11 @@ P4D_TIMEOUT=300
. ./test-lib.sh
if test -n "$NO_P4_TESTS"
then
skip_all='skipping git p4 tests, NO_P4_TESTS defined'
test_done
fi
if ! test_have_prereq PYTHON
then
skip_all='skipping git p4 tests; python not available'

View File

@ -207,7 +207,7 @@ test_expect_success 'ref transaction: corrupted tables cause failure' '
test_commit file1 &&
for f in .git/reftable/*.ref
do
: >"$f" || return 1
test-tool truncate "$f" 0 || return 1
done &&
test_must_fail git update-ref refs/heads/main HEAD
)

View File

@ -40,7 +40,7 @@ test_expect_success 'reset should remove remnants from a failed merge' '
git ls-files -s &&
read_tree_u_must_succeed --reset -u HEAD &&
git ls-files -s >actual &&
! test -f old &&
test_path_is_missing old &&
test_cmp expect actual
'
@ -56,7 +56,7 @@ test_expect_success 'two-way reset should remove remnants too' '
git ls-files -s &&
read_tree_u_must_succeed --reset -u HEAD HEAD &&
git ls-files -s >actual &&
! test -f old &&
test_path_is_missing old &&
test_cmp expect actual
'
@ -72,7 +72,7 @@ test_expect_success 'Porcelain reset should remove remnants too' '
git ls-files -s &&
git reset --hard &&
git ls-files -s >actual &&
! test -f old &&
test_path_is_missing old &&
test_cmp expect actual
'
@ -88,7 +88,7 @@ test_expect_success 'Porcelain checkout -f should remove remnants too' '
git ls-files -s &&
git checkout -f &&
git ls-files -s >actual &&
! test -f old &&
test_path_is_missing old &&
test_cmp expect actual
'
@ -104,7 +104,7 @@ test_expect_success 'Porcelain checkout -f HEAD should remove remnants too' '
git ls-files -s &&
git checkout -f HEAD &&
git ls-files -s >actual &&
! test -f old &&
test_path_is_missing old &&
test_cmp expect actual
'

View File

@ -415,8 +415,6 @@ test_expect_success 'up-to-date multi-pack-index is retained' '
)
'
test_done
test_expect_success 'verify multi-pack-index success' '
git multi-pack-index verify --object-dir=$objdir
'

View File

@ -319,6 +319,45 @@ test_expect_success '--stdin-packs=follow walks into unknown packs' '
)
'
test_expect_success '--stdin-packs with promisors' '
test_when_finished "rm -fr repo" &&
git init repo &&
(
cd repo &&
git config set maintenance.auto false &&
git remote add promisor garbage &&
git config set remote.promisor.promisor true &&
for c in A B C D
do
echo "$c" >file &&
git add file &&
git commit --message "$c" &&
git tag "$c" || return 1
done &&
A="$(echo A | git pack-objects --revs $packdir/pack)" &&
B="$(echo A..B | git pack-objects --revs $packdir/pack --filter=blob:none)" &&
C="$(echo B..C | git pack-objects --revs $packdir/pack)" &&
D="$(echo C..D | git pack-objects --revs $packdir/pack)" &&
touch $packdir/pack-$B.promisor &&
test_must_fail git pack-objects --stdin-packs --exclude-promisor-objects pack- 2>err <<-EOF &&
pack-$B.pack
EOF
test_grep "is a promisor but --exclude-promisor-objects was given" err &&
PACK=$(git pack-objects --stdin-packs=follow --exclude-promisor-objects $packdir/pack <<-EOF
pack-$D.pack
EOF
) &&
objects_in_packs $C $D >expect &&
objects_in_packs $PACK >actual &&
test_cmp expect actual &&
rm -f $packdir/pack-$PACK.*
)
'
stdin_packs__follow_with_only () {
rm -fr stdin_packs__follow_with_only &&
git init stdin_packs__follow_with_only &&

View File

@ -138,4 +138,16 @@ test_expect_success 'sigpipe does not cause pre-push hook failure' '
git push parent1 "refs/heads/b/*:refs/heads/b/*"
'
test_expect_success 'can write to stderr' '
test_hook --clobber pre-push <<-\EOF &&
echo foo >/dev/stderr &&
exit 0
EOF
test_commit third &&
echo foo >expect &&
git push --quiet parent1 HEAD 2>actual &&
test_cmp expect actual
'
test_done

View File

@ -480,4 +480,65 @@ test_expect_success '--geometric -l disables writing bitmaps with non-local pack
test_path_is_file member/.git/objects/pack/multi-pack-index-*.bitmap
'
write_packfile () {
NR="$1"
PREFIX="$2"
printf "blob\ndata <<EOB\n$PREFIX %s\nEOB\n" $(test_seq $NR) |
git fast-import &&
git pack-objects --pack-loose-unreachable .git/objects/pack/pack &&
git prune-packed
}
write_promisor_packfile () {
PACKFILE=$(write_packfile "$@") &&
touch .git/objects/pack/pack-$PACKFILE.promisor &&
echo "$PACKFILE"
}
test_expect_success 'geometric repack works with promisor packs' '
test_when_finished "rm -fr repo" &&
git init repo &&
(
cd repo &&
git config set maintenance.auto false &&
git remote add promisor garbage &&
git config set remote.promisor.promisor true &&
# Packs A and B need to be merged.
NORMAL_A=$(write_packfile 2 normal-a) &&
NORMAL_B=$(write_packfile 2 normal-b) &&
NORMAL_C=$(write_packfile 14 normal-c) &&
# Packs A, B and C need to be merged.
PROMISOR_A=$(write_promisor_packfile 1 promisor-a) &&
PROMISOR_B=$(write_promisor_packfile 3 promisor-b) &&
PROMISOR_C=$(write_promisor_packfile 3 promisor-c) &&
PROMISOR_D=$(write_promisor_packfile 20 promisor-d) &&
PROMISOR_E=$(write_promisor_packfile 40 promisor-e) &&
git cat-file --batch-all-objects --batch-check="%(objectname)" >objects-expect &&
ls .git/objects/pack/*.pack >packs-before &&
test_line_count = 8 packs-before &&
git repack --geometric=2 -d &&
ls .git/objects/pack/*.pack >packs-after &&
test_line_count = 5 packs-after &&
test_grep ! "$NORMAL_A" packs-after &&
test_grep ! "$NORMAL_B" packs-after &&
test_grep "$NORMAL_C" packs-after &&
test_grep ! "$PROMISOR_A" packs-after &&
test_grep ! "$PROMISOR_B" packs-after &&
test_grep ! "$PROMISOR_C" packs-after &&
test_grep "$PROMISOR_D" packs-after &&
test_grep "$PROMISOR_E" packs-after &&
ls .git/objects/pack/*.promisor >promisors &&
test_line_count = 3 promisors &&
git cat-file --batch-all-objects --batch-check="%(objectname)" >objects-actual &&
test_cmp objects-expect objects-actual
)
'
test_done

View File

@ -118,7 +118,7 @@ unlink $tmpfile;
# paths
my $abs_git_dir = $abs_repo_dir . "/.git";
if ($^O eq 'msys' or $^O eq 'cygwin') {
if ($^O eq 'msys') {
$abs_git_dir = `cygpath -am "$abs_repo_dir/.git"`;
$abs_git_dir =~ s/\r?\n?$//;
}

View File

@ -439,7 +439,7 @@ static void ll_diff_tree_paths(
void *ttree, **tptree;
int i;
if (depth > max_allowed_tree_depth)
if (depth > opt->repo->settings.max_allowed_tree_depth)
die("exceeded maximum allowed tree depth");
FAST_ARRAY_ALLOC(tp, nparent);

View File

@ -12,6 +12,7 @@
#include "pathspec.h"
#include "json-writer.h"
#include "environment.h"
#include "read-cache-ll.h"
static int decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned long size, struct strbuf *err)
{
@ -441,8 +442,9 @@ int traverse_trees(struct index_state *istate,
struct strbuf base = STRBUF_INIT;
int interesting = 1;
char *traverse_path;
struct repository *r = istate ? istate->repo : the_repository;
if (traverse_trees_cur_depth > max_allowed_tree_depth)
if (traverse_trees_cur_depth > r->settings.max_allowed_tree_depth)
return error("exceeded maximum allowed tree depth");
traverse_trees_count++;

16
tree.c
View File

@ -1,5 +1,3 @@
#define USE_THE_REPOSITORY_VARIABLE
#include "git-compat-util.h"
#include "hex.h"
#include "tree.h"
@ -25,10 +23,10 @@ int read_tree_at(struct repository *r,
int len, oldlen = base->len;
enum interesting retval = entry_not_interesting;
if (depth > max_allowed_tree_depth)
if (depth > r->settings.max_allowed_tree_depth)
return error("exceeded maximum allowed tree depth");
if (parse_tree(tree))
if (repo_parse_tree(r, tree))
return -1;
init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);
@ -185,7 +183,8 @@ int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)
return 0;
}
int parse_tree_gently(struct tree *item, int quiet_on_missing)
int repo_parse_tree_gently(struct repository *r, struct tree *item,
int quiet_on_missing)
{
enum object_type type;
void *buffer;
@ -193,8 +192,7 @@ int parse_tree_gently(struct tree *item, int quiet_on_missing)
if (item->object.parsed)
return 0;
buffer = odb_read_object(the_repository->objects, &item->object.oid,
&type, &size);
buffer = odb_read_object(r->objects, &item->object.oid, &type, &size);
if (!buffer)
return quiet_on_missing ? -1 :
error("Could not read %s",
@ -214,9 +212,9 @@ void free_tree_buffer(struct tree *tree)
tree->object.parsed = 0;
}
struct tree *parse_tree_indirect(const struct object_id *oid)
struct tree *repo_parse_tree_indirect(struct repository *r,
const struct object_id *oid)
{
struct repository *r = the_repository;
struct object *obj = parse_object(r, oid);
return (struct tree *)repo_peel_to_type(r, NULL, 0, obj, OBJ_TREE);
}

13
tree.h
View File

@ -19,15 +19,20 @@ struct tree *lookup_tree(struct repository *r, const struct object_id *oid);
int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size);
int parse_tree_gently(struct tree *tree, int quiet_on_missing);
static inline int parse_tree(struct tree *tree)
#define parse_tree_gently(t, q) repo_parse_tree_gently(the_repository, t, q)
int repo_parse_tree_gently(struct repository *r, struct tree *item,
int quiet_on_missing);
#define parse_tree(t) repo_parse_tree(the_repository, t)
static inline int repo_parse_tree(struct repository *r, struct tree *item)
{
return parse_tree_gently(tree, 0);
return repo_parse_tree_gently(r, item, 0);
}
void free_tree_buffer(struct tree *tree);
/* Parses and returns the tree in the given ent, chasing tags and commits. */
struct tree *parse_tree_indirect(const struct object_id *oid);
#define parse_tree_indirect(o) repo_parse_tree_indirect(the_repository, o)
struct tree *repo_parse_tree_indirect(struct repository *r,
const struct object_id *oid);
/*
* Functions for comparing pathnames

View File

@ -45,7 +45,7 @@ static int process_tree(struct walker *walker, struct tree *tree)
struct tree_desc desc;
struct name_entry entry;
if (parse_tree(tree))
if (repo_parse_tree(the_repository, tree))
return -1;
init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);