When processing the incoming packfile in git-receive-pack(1), `unpack()`
assumes it should always read it from stdin. In preparation for
`unpack()` logic being moved behind a generic ODB transaction interface,
update the function signature to take the an explicit fd provided by
callers to read the incoming packfile from instead. Call sites are
updated accordingly.
Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When writing packfiles via `unpack()`, error messages are returned
directly by the function. In preparation for `unpack()` logic being
moved behind a generic ODB transaction interface, update the function to
instead write any error messages to a caller provided strbuf and return
a negative value on error. Call sites are updated to use the error
strbuf accordingly.
Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
In git-receive-pack(1), writing the packfile to the transaction is
handled via `unpack()` which relies on global variables to decide how to
invoke the underlying git-index-pack(1) or git-unpack-objects(1) child
processes. In a subsequent commit, the `unpack()` logic is moved behind
a generic ODB transaction interface to handle writing packfiles and thus
can no longer rely on these globals.
Lift the global state out of `unpack()` by instead storing this state in
a `struct unpack_opts` that gets passed to the function explicitly.
Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
In git-receive-pack(1), the `receive.unpackLimit` and
`transfer.unpackLimit` configuration decides whether an incoming
packfile should be exploded into loose objects or kept as a packfile
on-disk. In a subsequent commit, the logic to write the incoming
packfile is made ODB backend agnostic and moved behind a pluggable ODB
transaction interface. Consequently, whether to explode a packfile is a
detail of how a particular backend stores objects and should not be a
part of the generic interface itself.
In preparation for this, instead resolve the unpack limit lazily inside
`unpack()` by reading the configuration directly. The now-unused unpack
limit globals are dropped accordingly.
Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
If shallow information is provided during `unpack()`, a temporary
shallow file is created and stored in global state. In a subsequent
commit, the `unpack()` logic is moved behind a generic ODB transaction
interface to handle writing packfiles and thus can no longer rely on
such global state. Lift the setup of the temporary shallow file out of
`unpack()` and wire it through to its call sites explicitly.
Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When committing an ODB transaction via `odb_transaction_commit()`, the
staged objects are made visible and the underlying transaction is freed
at the same time. Coupling these two steps does not leave room for any
post-commit transaction operations to be introduced though. Such a
capability is useful if an ODB transaction backend needs to hold on to
lockfiles after transaction commit until references are updated, as is
the case with the existing "files" backend in git-receive-pack(1).
Stop freeing the transaction in `odb_transaction_commit()` and introduce
`odb_transaction_finalize()` to explicitly clean up the transaction
accordingly. Note that the finalize interface also provides an optional
callback for any backend-specific deferred cleanup. In a subsequent
commit, the "files" transaction backend will use this to remove ".keep"
files generated for packfiles received via git-receive-pack(1) after
references have been updated. In preparation for this, the
`odb_transaction_finalize()` call site in git-receive-pack(1) is made
after the reference updates are finished.
All other callers commit a transaction and immediately finalize it
without any work happening in between those two operations.
Consequently, they cannot meaningfully recover in case either of them
would fail, and spelling out these two separate steps with proper error
handling would be quite repetitive and pointless. Introduce a helper
`odb_transaction_commit_and_finalize_or_die()` for those call sites and
update them accordingly.
Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When git-receive-pack(1) stores an incoming packfile with
git-index-pack(1), a ".keep" file is written alongside it in the
transaction quarantine directory and also gets migrated to the main ODB
when the ODB transaction is committed. This keep lockfile ensures the
packfile remains in place until the references have been updated and is
removed afterwards. The path used to remove it is derived via
`index_pack_lockfile()` from the repository's primary object directory.
In bdee7b3013 (builtin/receive-pack: stage incoming objects via ODB
transactions, 2026-07-10), git-receive-pack(1) started using the ODB
transaction interfaces instead of managing a temporary directory
directly. When starting an ODB transaction, the sources list is
reordered to insert the newly created transaction source first as the
primary to ensure writes are routed to it accordingly.
Prior to using ODB transactions, git-receive-pack(1) would only set the
temporary directory as the primary source for the child
git-index-pack(1) and git-unpack-objects(1) processes it spawned and the
parent process would set the temporary directory set as an alternate
only. By using ODB transactions, the ODB source list is also reordered
for the parent process which results in `index_pack_lockfile()` deriving
the ".keep" path relative to the temporary directory instead of the
actual main ODB source path. Consequently, this prevents the ".keep"
file from being properly removed after being migrated into the main ODB
source post-commit.
Update `index_pack_lockfile()` to operate on an ODB source explicitly
provided to it and update call sites accordingly to pass the expected
ODB source.
Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Tests for 'git merge-base --is-ancestor' have been added to cover
exit codes (0 for success, 1 for non-ancestor, 128 for errors) and
to ensure it cannot be combined with '--all'.
* ns/merge-base-is-ancestor-tests:
merge-base: add tests for --is-ancestor
'git mv' has been updated to check for a missing destination
leading directory during the checking phase, allowing 'git mv -n'
to report the failure. The error message when the rename(2)
syscall fails has also been improved to name both the source and
the destination.
* lo/mv-missing-dest-dir-check:
mv: reject a destination whose leading path is missing or a symlink
mv: name both source and destination when rename fails
Documentation for 'git replay' has been updated to refer to its
configuration variables.
* kh/doc-replay-config:
doc: replay: move “default” to the right-hand side
doc: replay: use a nested description list
doc: replay: improve config description
doc: link to config for git-replay(1)
A new test helper commit_body() has been introduced to print the
message body of a commit, and various tests have been updated to use
it instead of spelling out the command pipeline manually and losing
the exit status of the 'git cat-file' command on the upstream of the
pipe.
* sk/test-commit-body-helper:
t: use commit_body to extract commit message bodies
test-lib-functions: add commit_body helper
Synopsis and options in the documentation for 'git format-patch',
'git imap-send', 'git send-email', and 'git request-pull' have been
updated to the modern style.
* ja/doc-synopsis-style-yet-more:
doc: convert git-request-pull synopsis and options to new style
doc: convert git-send-email synopsis and options to new style
doc: convert git-format-patch synopsis and options to new style
doc: convert git-imap-send synopsis and options to new style
A crash in the 'sparse-index' collapse code when encountering an
invalidated cache-tree node (due to an intent-to-add path) has been
fixed by avoiding collapsing such subtrees.
* ds/sparse-index-ita-crash:
sparse-index: avoid crash on intent-to-add entry outside the cone
A boundary case check in reachability bitmap traversal has been
corrected to properly handle the object at position zero, which was
previously skipped, leading to redundant bitmap loading.
* dl/pack-bitmap-position-zero:
pack-bitmap: handle objects at bitmap position zero
A memory leak in 'git merge' when run without arguments (which
triggers the default-to-upstream path) has been fixed. A test has
been added to cover this case.
* tc/merge-default-to-upstream-leakfix:
merge: fix leak with merge.defaultToUpstream
'git cat-file --batch-command' that asked for 'contents' without
'type' segfaults, which has been corrected.
* jk/cat-file-batch-wo-type-fix:
cat-file: handle content request for --batch-command without type
The get_commit_action() function has been refactored to be a pure
predicate by moving the side-effecting line-level log range folding to
simplify_commit(). This ensures that evaluating a commit's action
before the walk reaches it does not prematurely mutate its tracked
line ranges, making it safer for potential lookahead evaluations.
* mm/revision-pure-get-commit-action:
revision: make get_commit_action() a pure predicate
The code path that deals with relative paths in the 'diff-lib' has
been cleaned up.
* jk/diff-relative-cached-unmerged-more:
diff-lib: skip paths outside prefix in oneway_diff()
diff-lib: drop stale comment about advancing o->pos
Git for Windows has been updated to avoid auto-detecting the symlink
type if the target path starts with a slash, preventing NTLM
credential leaks when checking out repositories with crafted
symbolic links pointing to network shares.
* js/mingw-symlink-net-share-leak:
mingw: skip symlink type auto-detection for network share targets
The alias tests in 't/t0014-alias.sh' have been updated to dynamically
query the list of deprecated commands using 'git
--list-cmds=deprecated' to avoid test failures when running with
'WITH_BREAKING_CHANGES' in a build directory that contains stale
executables of formerly deprecated commands.
* jk/t0014-dynamic-deprecated-cmds:
t0014: generate deprecated command names dynamically
t0014: factor out choice of deprecated commands
The image version used by the static-analysis CI job has been bumped
to ubuntu-latest (Ubuntu 24.04), which brings in a newer Coccinelle
version that resolves a severe performance regression. A false
positive warning from the 'CHECK_ASSERTION_SIDE_EFFECTS' build with
GCC 15 in the Bloom filter code has also been silenced to facilitate
the image upgrade.
* jk/ci-static-analysis-image-bump:
ci: bump ubuntu image version for static-analysis job
bloom: silence CHECK_ASSERTION_SIDE_EFFECTS false positive
'git branch -d' has been taught to report when a branch cannot be
deleted because it is being used in an active bisect run.
* rs/branch-delete-bisect-warning:
branch: report active bisect run when rejecting delete
Object database housekeeping in 'git gc' and 'git maintenance' has
been refactored to be pluggable. The files-backend-specific logic,
including incremental and geometric repacking as well as object
pruning, has been moved out of the command implementation and into the
files object database source, enabling future alternative object
database backends to implement their own housekeeping services.
* ps/odb-pluggable-housekeeping:
odb: make optimizations pluggable
builtin/gc: fix signedness issues in ODB-related functionality
builtin/gc: refactor ODB optimizations to operate on "files" source
builtin/gc: introduce `odb_optimize_required()`
builtin/gc: move geometric repacking into `odb_optimize()`
builtin/gc: introduce object database optimization options
builtin/gc: inline config values specific to the "files" backend
builtin/gc: make repack arguments self-contained
builtin/gc: extract object database optimizations into separate function
builtin/gc: move worktree and rerere tasks before object optimizations
odb: run "pre-auto-gc" hook for all maintenance tasks
t7900: simplify how we check for maintenance tasks
Two bugs in how 'git rebase' handles skipped 'fixup' and 'squash'
commands have been fixed. One bug caused an incorrect commit count to
be shown in the template message when multiple commands were skipped,
and another prevented the editor from opening when the final command
in a chain containing 'fixup -c' was skipped.
* pw/rebase-fixup-fixes:
rebase: remember fixup -c after skipping fixup/squash
rebase -i: fix counting of fixups after rebase --skip
'git diff --relative' running with '--cached' has been corrected to
avoid a segfault when encountering unmerged paths outside the
prefix.
* jk/diff-relative-cached-unmerged:
diff-lib: add idx/tree sanity check to oneway_diff
diff: ignore unmerged paths outside prefix with --relative --cached
Ben uses the +github GMail trick to identify emails sent to him by folks
that found his GitHub profile. At the time, that also meant he had to
commit under the same email for GitHub to recognize his commits. He has
since found out that GitHub can be configured with more than one email
for identification, and he would prefer his canonical email to omit
mention of GitHub (where it's not relevant) going forward.
Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The `chriscool@tuxfamily.org` address is an old one that I don't use
anymore, while `christian.couder@gmail.com` is the address I have been
sending patches from for a long time.
Let's swap the two addresses in the existing entry, so that the Gmail
address becomes the primary one and the old tuxfamily.org address is
mapped to it. This way both addresses still resolve to the same person,
and the address I actually use is the canonical one.
Signed-off-by: Christian Couder <christian.couder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The remote-matching logic for submodules has been corrected to resolve
'url.*.insteadOf' aliases before comparing the inventoried URL from
'.gitmodules' with the URLs of configured remotes.
* en/submodule-insteadof-remote-match:
submodule: resolve insteadOf aliases when matching remote
rewrites_release() in 'remote.c' has been updated to free 'struct
rewrite' instances, their '.instead_of' arrays, and their contents.
* jc/remote-insteadof-leakfix:
remote: plug memory leaks
A segfault when 'git clone --revision' talks to a server that does not
support protocol v2 (falling back to protocol v0) has been corrected.
* af/clone-revision-v0-segfault-fix:
builtin/clone: fix segfault when using --revision with protocol v0
Traversals with '--exclude-first-parent-only' have been corrected
to properly stop after the first parent even when it has already
been marked as 'SEEN'.
* jc/exclude-first-parent-seen:
revision: honor --exclude-first-parent-only with SEEN first parent
When the push remote is specified as a URL, the fetch refspec of a
uniquely matching configured remote is now used to find and update
the remote-tracking branch (e.g., '@{push}').
* hn/url-push-tracking:
remote: find tracking branches for URL push destinations
remote: pass repository to push tracking helper
The logic to write loose objects has been refactored and moved from
'object-file.c' to the loose backend source file 'odb/source-loose.c',
making the loose backend more self-contained. This is achieved by
first refactoring force_object_loose() to use generic ODB write
interfaces instead of loose-backend internals.
* ps/odb-move-loose-object-writing:
object-file: move logic to write loose objects
object-file: move `force_object_loose()`
object-file: force objects loose via generic interface
object-file: fix memory leak in `force_object_loose()`
odb: support setting mtime when writing objects
odb: lift object existence check out of the "loose" backend
odb: compute object hash in `odb_write_object_ext()`
t/u-odb-inmemory: implement wrapper for writing objects
odb: compute compat object ID in `odb_write_object_ext()`
The object ID shortening and linking in the 'commitdiff' view of
'gitweb' has been corrected to work even when the index line carries
a trailing file mode.
* tl/gitweb-shorten-hashes-with-modes:
gitweb: shorten index hashes with trailing file modes
The 'remote-object-info' command has been added to 'git cat-file
--batch-command', allowing clients to request object metadata
(currently size) from a remote server via protocol v2 without
downloading the entire object. Format placeholders are dynamically
filtered on the client based on server-advertised capabilities,
returning empty strings for inapplicable or unsupported fields.
* ps/cat-file-remote-object-info:
cat-file: make remote-object-info allow-list adapt to the server
cat-file: add remote-object-info to batch-command
transport: add client support for object-info
serve: advertise object-info feature
protocol-caps: check object existence regardless of the attributes requested
fetch-pack: move fetch initialization
connect: make write_fetch_command_and_capabilities() more generic
fetch-pack: move write_fetch_command_and_capabilities() to connect.c
fetch-pack: use unsigned int for hash_algo variable
fetch-pack: drop the static advertise_sid variable
t1006: extract helper functions into new 'lib-cat-file.sh'
cat-file: declare loop counter inside for()
transport-helper: fix memory leak of helper on disconnect
Configuration file locking has been updated to retry for a short
period, avoiding failures when multiple processes attempt to update
the configuration simultaneously.
* jt/config-lock-timeout:
config: retry acquiring config.lock, configurable via core.configLockTimeout
The 'git stash push' command has been optimized to avoid unnecessary
sparse index expansion when pathspecs are wholly inside the
sparse-checkout cone. Also, a potential out-of-bounds read in the
sparse-index expansion check helper pathspec_needs_expanded_index()
has been fixed by consistently using the parsed, prefixed path.
* tn/stash-avoid-sparse-index-expansion:
stash: avoid sparse-index expansion for in-cone paths
pathspec: use match for sparse-index expansion checks
Userdiff patterns for Swift have been added, with support for
Swift-specific constructs such as attributes, modifiers, failable
initializers, and generics.
* sk/userdiff-swift:
userdiff: add support for Swift
The 'excludes_file' and various other global configuration variables
(including 'editor_program', 'pager_program', 'askpass_program', and
'push_default') have been migrated into the per-repository structure.
* ty/migrate-excludes-file:
repository: adjust the comment of config_values_private_
environment: move object_creation_mode into repo_config_values
environment: move autorebase into repo_config_values
environment: move push_default into repo_config_values
environment: migrate apply_default_whitespace and apply_default_ignorewhitespace
environment: move askpass_program into repo_config_values
environment: move pager_program into repo_config_values
environment: move editor_program into repo_config_values
environment: move excludes_file into repo_config_values
repository: introduce repo_config_values_clear()
The 'trust_executable_bit' (coming from the 'core.filemode'
configuration) has been migrated into 'struct repo_config_values' to
tie it to a specific repository instance.
* ty/migrate-trust-executable-bit:
environment: move has_symlinks into repo_config_values
environment: move trust_executable_bit into repo_config_values
read-cache: pass 'repo' to 'ce_mode_from_stat()'
read-cache: remove redundant extern declarations
The tempfile and lockfile APIs have been refactored to stop depending
on the 'the_repository' global variable, and their callers have been
updated to use the repository-aware variants.
* rs/tempfile-wo-the-repository:
use repo_hold_lock_file_for_update{,_mode,_timeout}() with custom repos
tempfile: stop using the_repository
lockfile: add repo_hold_lock_file_for_update{,_timeout}{,_mode}()
refs/packed: use repo_create_tempfile()
tempfile: add repo_create_tempfile{,_mode}()
When moving a file, if any leading directory in the destination path
is missing or is not a real directory, the problem is detected only
later when rename() is called. Furthermore, if a leading directory
component is a symbolic link, the issue is not detected at all.
Three cases reach rename(2) unchecked today:
- A leading directory is missing: rename(2) fails with ENOENT,
reported against the source (misleading), and "git mv -n" does not
detect it since the dry run never reaches the syscall.
- A leading component is a non-directory ("git mv x a/b" with 'a' a
file): rename(2) fails with ENOTDIR, again only at the syscall.
- A leading component is a symbolic link: "git mv" follows it. Since
Git tracks symlinks, the destination is really occupied by a
tracked object, and following it is wrong regardless of the link
target. The move is done on disk at the resolved location while the
index records the literal path, leaving the index describing a
worktree that does not exist. A later "git add" can reconcile it,
but "git mv" alone has already corrupted the state.
Detect all three in the checking phase. Reject a destination that goes
through a symlink with has_symlink_leading_path(), which uses lstat()
and never follows the link, so the refusal is independent of the
target. Then lstat() the leading directory: report "destination
directory does not exist" for ENOENT/ENOTDIR and "destination is not a
directory" for a non-directory. Other errors fall through to rename().
Guard the directory check with the same condition under which rename(2)
runs, so directory moves and sparse/out-of-cone destinations are not
flagged incorrectly.
This changes behavior: a move through a tracked symlink that previously
"succeeded" while corrupting the index is now refused. The other two
cases only change when the failure is diagnosed.
Signed-off-by: Lucas Zamboni Orioli <lucaszam0@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When "git mv" fails at the rename(2) syscall, the error is reported
with die_errno() using only the source path:
fatal: renaming 'src' failed: No such file or directory
rename(2) returns ENOENT both when the source does not exist and when
a directory component of the destination does not exist, and errno
does not distinguish the two. Reporting only the source therefore
misleads the user in the latter case: for
git mv a/file b/no-such-dir/file
the message blames 'a/file', which exists, and gives no hint that
'b/no-such-dir/' is the missing part.
Inspecting the paths again after the failure to determine which one is
at fault would be racy, since either could appear or disappear between
the rename(2) and the follow-up check. Instead, simply name both the
source and the destination in the message and let the reader see which
one is wrong:
fatal: renaming 'a/file' to 'b/no-such-dir/file' failed:
No such file or directory
Signed-off-by: Lucas Zamboni Orioli <lucaszam0@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This is now a description list (see previous commit) and parentheticals
like this do not go on the left-hand side. Moving it to the other side
makes it stand out just as much and is also more consistent with the
rest of the documentation.
Let’s also do the same for the `replay.refAction` description list.
That makes the two desc. lists identical in the first sentence. Let’s
add a comment about that for future editors.
Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This bullet list for `--ref-action` introduces a term with a colon.
This is exactly what a description list is, structurally. Let’s be
stylistically consistent and use the desc. list markup construct.
In short, just transform this unordered list in the same way that we
did for `replay.refAction` in the previous commit.
Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>