"git stash create/push" checked if there are checks that need to be
saved twice, which has been reduced to just once.
* pw/stash-change-check-only-once:
stash push: remove duplicate changes detection
stash create: remove duplicate changes detection
The output of 'git repo info' has been updated to use
'references.storageFormat' instead of 'references.format' for
consistency with recent ref-storage-format terminology updates.
* ps/repo-ref-storage-format-fix:
builtin/repo: rename "references.format" to "references.storageFormat"
When recreating a merge conflict using 'git checkout -m', the
original conflict labels (such as branch names) were lost and
replaced with generic ones. The merge machinery has been updated to
record the original labels in '.git/MERGE_LABELS', allowing 'git
checkout -m' to restore them.
* pw/checkout-m-conflict-labels:
merge: remember conflict labels
remove_branch_state: convert boolean argument to flags
A new 'uploadpack.lazyFetchTrusted' configuration variable has been
introduced to allow 'upload-pack' to lazily fetch missing objects from
configured promisor remotes when serving trusted repositories.
* cc/lazy-fetch-trusted-bit:
builtin/upload-pack: don't disable lazy fetching on trusted repo
promisor-remote: prevent infinite recursion when lazy fetching
upload-pack: read uploadpack.lazyFetchTrusted
setup: extract path_allowlist_apply()
promisor-remote: factor out lazy_fetch_objects()
The 'git range-diff' command has been augmented with a
'--matched-only' option to skip commits that are only present on
one side, allowing users to easily focus on only the commits that
have been retained.
* hn/range-diff-matched-only:
range-diff: add --matched-only to skip one-sided commits
The 'git config --global' read operations have been updated to
respect both '$HOME/.gitconfig' and '$XDG_CONFIG_HOME/git/config',
fixing an inconsistency where only the former was read when both
configuration files are present.
* dw/config-read-both-global:
config: read global scope via config_sequence
t1300: test list with missing global config
The --recurse-submodules option in 'git branch' has been fixed to
avoid a crash when the start point is not a reference (e.g., a raw
object ID). The creation path now skips setting up tracking and
properly forwards the absent tracking name to the submodule helper.
* vv/branch-recurse-no-start-ref:
branch: allow recursion with no tracking name
branch: do not track a start point with no ref
The '--dry-run' option of 'git repack --drop-filtered' used to
actually rebuild packs and delete redundant ones, which has been
corrected to only list the candidates without making changes.
* ss/repack-drop-filtered-dry-run:
repack: do not rebuild packs on --dry-run
The odb_source API has been refactored to make alternates an
implementation detail of the files backend instead of managing them
at the core object database layer.
* ps/odb-files-alternates:
odb/source: drop `read_alternates` callback
odb/source-files: move alternates into the backend
odb/source-files: extract reading alternates
odb/source: make `will_destroy` an implementation detail
tmp-objdir: replace primary source at creation time
tmp-objdir: manage quarantine as an object directory
tmp-objdir: absorb logic to set and restore primary sources
odb/source-files: add the ability to have multiple object dirs
odb: refactor `odb_find_source()` to yield dirs
odb: refactor `odb_for_each_alternate()` to yield dirs
odb/source-files: introduce `struct odb_files_dir`
commit-graph: stop depending on `struct odb_source`
commit-graph: require resolved packfile paths for `stdin_packs`
The fetch.writeCommitGraph behavior has been optimized to
incrementally update the commit graph using only the newly fetched
commits as seeds. This avoids a full reachability scan of all
references and drastically reduces the post-fetch commit-graph
update time for repositories with many references.
* kk/fetch-write-commit-graph-incremental:
fetch: write commit-graph using updated refs only
test-tool read-graph: add commit-info subcommand
Validation of the 'fetch.followRemoteHEAD' configuration variable
has been deferred to when it is actually used, preventing irrelevant
warnings during 'git fetch' invocations that do not consult it.
* ch/fetch-followremotehead-lazy-validation:
fetch.c: defer fetch.followRemoteHEAD validation
Fix definition for the "--all" option to use symbolic constant
in the options[] array passed to parse_options API.
* pw/stash-all-parseopt-fix:
stash: use named constant when parsing "--all"
The 'format-patch' command has been updated with options to
configure notes specifically for range-diff output, allowing them to
differ from the notes displayed on the patches themselves.
* kh/format-patch-range-diff-notes:
format-patch: learn --[no-]range-diff-notes
format-patch: simplify get_notes_arg parameters
The parse-options API has been updated to support grouping
subcommands, and the 'git refs' command has been updated to use this
new feature to categorize its subcommands in its help output.
* ps/parse-options-subcommand-groups:
builtin/refs: introduce subcommand groups
parse-options: allow grouping subcommands
parse-options: extract functions to print single option
parse-options: fix completion format when first option is skipped
The 'git var' command has been updated to output individual components
of the author and committer identities, take multiple keys on the
command-line, and support NUL-delimited output with the '-z' option.
* ap/var-broken-down-idents:
var: add broken-out identity variables
var: accept more than one variable
var: add "-z" output mode
var: represent multi-valued variables with a string_list
The handling of index conflicts in 'git stash apply --index' has
been optimized. Instead of relying on expensive external
subprocesses using 'git diff-tree' and 'git apply', the index is now
merged in-core using the merge-ort machinery, which fixes a
concurrent lock file issue with autostash.
* dk/stash-apply-index-incore:
builtin/stash: merge index in-core
t3903: test failed "stash apply --index"
stash: prepare merge options earlier
builtin/stash: remove unused header
The internal diff and merge machinery has been updated to use
standard size_t types rather than signed longs for buffer
allocations and offsets, preventing subtle overflow issues on LLP64
architectures, and plugging uninitialized memory leaks along error
paths.
* jk/xdiff-size_t:
merge-ll: report an error when reading external merge results fails
merge-ll: handle external driver status before reading result
merge-ll: use read_mmfile() to read external merge results
xdiff: NUL-terminate buffers read by read_mmfile()
xdiff: use size_t for buffer sizes
xdiff: replace mmbuffer_t with mmfile_t
xdiff: clean up read_mmfile() allocations on error
"git repack --drop-filtered --dry-run" is documented to list the
objects that would be dropped "without rebuilding any pack or
deleting anything", but it does both.
This is a bug in cmd_repack(): after printing the candidates, the
--dry-run block falls through into the regular repack code.
repack_promisor_objects() writes a new promisor pack, and with -d,
existing_packs_remove_redundant() deletes the old packs.
The existing guard only skips the implied "delete_redundant = 1", so
it does not stop an explicit -d, and it does not stop the new pack
from being written either.
This has been broken since --dry-run was introduced in 1e746b00aa
(builtin/repack: add --drop-filtered and --dry-run options,
2026-08-14). The --dry-run block never returned early, so a dry run
has always gone on to do a regular repack.
Fix it by returning right after the candidates are listed, and add a
test that checks the pack directory is unchanged with and without -d.
Reported-by: Coy Geek <coygeek@gmail.com>
Helped-by: D. Ben Knoble <ben.knoble@gmail.com>
Signed-off-by: Siddharth Shrimali <r.siddharth.shrimali@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When both `$HOME/.gitconfig` and `$XDG_CONFIG_HOME/git/config` exist,
`git config list --global` and `git config get --global` read the home
configuration file but ignore the XDG file. Bug reporters expected these
`--global` scoped commands to read both files [1][2], which would be
consistent with the documentation and the behaviour of the unscoped
variants. For example, `git config list` and `git config get` (without
`--global`) read from both files (in addition to system-wide and
repository-specific entries). We should address this inconsistency by
respecting both files during `--global` read operations.
The implementation assumes that each configuration scope corresponds to
a single file. So during `--global` read operations, Git selects one
file path to pass to `git_config_from_file_with_options(file)`. Because
the global scope can come from more than one file, we should use another
method to read the global configuration.
Since `git config list --show-scope --show-origin` reads both the home
and XDG files, there must be existing code that respects both locations,
namely `do_git_config_sequence()` which reads from all scopes. Introduce
an `ignore_system` flag and modify `git_config_system()` to respect it.
This makes `config_options` the primary way to disable parts of the
configuration sequence and allows callers of `do_git_config_sequence()`
to ignore all but the global scope (i.e. ignore system, local, worktree,
and cmdline). Reuse the function to read only the global scope when
`--global` is specified. This was the suggested solution [3] in the
original bug report [1].
The previous patch, "t1300: test list with missing global config",
recorded existing behaviour: when no global configuration file exists,
`git config list` should succeed whereas `git config list --global`
should fail. Since the configuration sequence gracefully ignores missing
global configuration files, track whether we successfully read at least
one of them and adjust the return code accordingly.
Keep populating `opts->source.file` in `builtin/config.c` as the
destination for write operations. Read operations use the configuration
sequence instead, which can be confusing. Add a comment to explain this
distinction.
Lastly, modify tests to check that both home and XDG configuration files
are respected during `--global` read operations.
[1] https://lore.kernel.org/git/CAFA9we-QLQRzJdGMMCPatmfrk1oHeiUu9msMRXXk1MLE5HRxBQ@mail.gmail.com/
[2] https://lore.kernel.org/git/CAAdFe9yhBk-WecVzCTsjQ-4Z3AZAbpP+w+B076ouM3qX6d1WAg@mail.gmail.com/
[3] https://lore.kernel.org/git/kl6ly1oze7wb.fsf@chooglen-macbookpro.roam.corp.google.com/
Reported-by: Jade Lovelace <lists@jade.fyi>
Reported-by: Nils Fahldieck <nils@fahldieck.de>
Suggested-by: Glen Choo <glencbz@gmail.com>
Helped-by: Derrick Stolee <stolee@gmail.com>
Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Delilah Ashley Wu <delilahwu@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When recreating merge conflicts with "git checkout -m <path>" the
original conflict labels are lost. For commands like "git merge" and
"git cherry-pick" we could use the presence of the related root
ref (MERGE_HEAD and CHERRY_PICK_HEAD respectively) to recreate the
labels. However, if the conflicts are from "git stash pop" or "git
checkout -m <branch>", then there is no ref to deduce the labels from. To
ensure the labels are always available, the merge machinery is updated to
write ".git/MERGE_LABELS" when it updates the worktree and
there are conflicts. The labels are then read from that file by "git
checkout -m <path>" when recreating the conflicts.
As "git checkout -m <branch>" calls remove_branch_state() which
ordinarily removes the labels file, we need to pass a flag down
to optionally prevent that so that the labels are available for any
subsequent "git checkout -m <path>". Note that merge_switch_to_result()
we assign "result->priv" to "opt->priv" and later clear "opt->priv" in
order to get a pointer to the private struct as result->priv is void*.
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Convert the "verbose" boolean argument to a flag so that we can add
more flags in a future commit.
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Originally, when designing pluggable object databases the goal was that
the object database can have multiple sources, and every source attached
to it could use a different backend. This would have allowed for quite a
lot of flexibility, as you could trivially mix and match different kinds
of object storages in whatever way you like.
But while well-intentioned, this design led to a bunch of conceptual
problems:
- We're now trying to read objects in source order, whereas we
previously tried to read objects via packfiles before trying to read
them via loose objects. This led to a performance regression when
using alternates or when using a quarantine directory.
- Some data structures are supposed to only ever exist once, like for
example bitmaps and commit graphs. At the same time, those data
structures also span across the union of all objects, so they may
cross sources.
- It is unclear how we can extend GIT_OBJECT_DIRECTORY or
GIT_ALTERNATE_OBJECT_DIRECTORIES to become backend-agnostic in a
backwards-compatible way. In general, introducing an object storage
extension into the current status quo where alternates may have to
be extended to become generic was proving to be painful.
- Some mechanisms of alternates assume way too much about how exactly
their backends work. Alternate refs for example assume that the
alternate is backed by a filesystem path, and that this filesystem
path may also allow us to read references. This is not a given
though, as backends may not even have local data at all.
In short, there are a bunch of conceptual mismatches when we have
alternates and pluggable object databases coexist. So while the original
idea was nice, it does not result in a system that is easy to reason
about.
Correct course by moving alternates into the "files" source itself so
that it becomes an implementation detail thereof so that we can avoid
all of these shortcomings. While it's unfortunate that we cannot easily
mix and match sources now, that ability doesn't go away. It's still very
much feasible to introduce a new backend that allows for exactly that
use case, and such a backend may also be a lot more flexible as we can
now add new logic to determine which objects should be stored where. So
the original motivation for having per-source backends can still be
realized with the new architecture.
Note that as part of this move, we also handle the GIT_OBJECT_DIRECTORY
and GIT_ALTERNATE_OBJECT_DIRECTORIES environment variables in the
"files" backend. This may be surprising at first, but object directories
are very much a concept of that backend, too. So these variables would
have bad interactions with other backends, and they create a bit of a
mismatch with the eventual object storage extension that we plan to
introduce.
Note that this commit is way larger than I'd like it to be. I'm sorry, I
couldn't find a way to split it up further. That being said, most of the
changes are straight-forward conversions that go from iterating over
sources to iterating over object directories. The more involved changes
are moving the infrastructure to track individual sources from "odb.c"
and moving them into "odb/source-files.c".
This also serves to show a bit of a who's-who of commands that don't
work properly with pluggable object databases. Almost all of these
commands are related to housekeeping though -- some of them will be
converted eventually, like for example commit graphs or MIDXs. But many
of them will stay incompatible going forward as they are simply too
specific to the "files" backend.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Similar as in the preceding commit, `odb_find_source()` can be used to
yield a single source by its object directory. This function is also
specific to the "files" backend once alternates are an implementation
detail thereof.
Refactor it to be specific to the "files" backend and return an `struct
odb_files_dir` to prepare for moving alternates into the "files" source.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The function `odb_for_each_alternate()` iterates through all alternates
of an object database. This is becoming an implementation detail of the
"files" backend though, where each alternate will be represented by one
`struct odb_files_dir`.
Adapt `odb_for_each_alternate()` to already iterate through these
structs instead of iterating through sources.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The "files" object database source consists of two separate backends for
storing loose and packed objects. These are managed as somewhat separate
entities even though they derive from the same object directory, whether
it's the primary object directory or that one from an alternate.
In a subsequent commit we'll move the handling of alternates into the
"files" backend completely so that it becomes another implementation
detail thereof. As part of this, we'll want to keep track of both of
these sub-sources as a single entity derived from their respective
object directory.
Prepare for this change by introducing a new `struct odb_files_dir` that
encapsulates them. For now, every "files" source has exactly one such
directory. In a subsequent commit though, we'll make it a linked list of
directories so that we can manage multiple such directories in a single
"files" source.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
To read or write a commit graph we require access to the repository that
the graph should be read from or written for as well as the object
directory to derive its location. Instead of passing in these two bits
of information explicitly though, we pass in a `struct odb_source`,
which carries with it both of these pieces of information.
But ultimately, this is somewhat flawed as we now assume that the source
even has an on-disk representation, and furthermore we assume that the
commit graphs would live in ".git/objects/info". This is true for the
"files" backend, but it's not necessarily true for any other backend
that we may eventually want to introduce. So eventually, we'll want to
evolve the commit-graph subsystem to become agnostic of the backend's
layout and let the backend itself decide where to read a commit graph
from or where to write it to.
We're not there yet to do that switch, but the current design is already
causing issues for the intent of this patch series where we want to move
alternates into the "files" backend.
Convert the subsystem to take a repository plus an object directory path
instead. This unblocks moving around alternates, and it's also a step
in the right direction for moving commit graphs into the source in a
later series.
Note that we previously compared the `struct odb_source` pointers of two
commit graphs to figure out whether they were located in the same object
directory, whereas we now have to compare their paths. Callers may pass
in those paths in different forms though, for example relative to the
current working directory or as absolute paths. Convert the object
directory into an absolute path both when loading and when writing
commit graphs so that the comparisons become more robust.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Users can ask git-commit-graph(1) to write a commit graph specifically
for a set of packfiles via the "--stdin-packs" option. Those users are
expected to pass in relative paths, and those eventually get resolved in
`fill_oids_from_packs()`. This ties the logic in "commit-graph.c" to the
specific object database source, as the subsystem now needs to assume
where a specific packfile is located relative to the source itself.
Refactor the logic to instead require the caller to pass in resolved
packfiles to untangle that dependency. This also makes the next change
easier to implement, where we'll get rid of passing the source to the
commit-graph subsystem.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When fetch.writeCommitGraph was introduced in 50f26bd035 (fetch: add
fetch.writeCommitGraph config setting, 2019-09-02), the stated goal
was to stay updated with the latest commits after fetching new
objects. The implementation used write_commit_graph_reachable()
because it was the only API available, but two things have changed
since then:
1. write_commit_graph() was added, and it accepts an explicit set of
commits as seeds, enabling more targeted commit-graph updates.
2. The ref-scanning callback add_ref_to_set() became more expensive
in 630cd5194e (commit-graph.c: peel refs in 'add_ref_to_set',
2020-07-22) when it started to validate the refs against the odb
for correctness. On a repository with many refs, this makes the
full reachable scan unnecessarily costly for a targeted fetch.
Optimize the commit-graph write by using only the newly updated refs
as seeds instead of scanning all refs after every fetch. To keep
this change small, skip the optimization for multi-remote fetches
(since that would require propagating the set of refs across process
boundaries).
This relies on the commit-graph write being additive, keeping the
commits that are already in the graph. fetch already operates in
this mode (COMMIT_GRAPH_WRITE_SPLIT) and now that becomes
required for correctness. Without that mode, the write would
replace the commit-graph and lose other commits.
After fetch_one() returns, call prepare_commit_graph() (which is
made non-static by this commit) to determine the graph-write mode:
- If no commit-graph exists yet, fall back to the full reachable
scan so the first graph creation covers all refs.
- If a commit-graph exists and the fetch updated at least one ref,
write incrementally using only the new refs as seeds.
- If a commit-graph exists but the fetch is a no-op, skip the
commit-graph write entirely.
- For the multi-remote path (fetch --all), where child processes
do the actual fetching, fall back to the full reachable scan.
Full commit-graph coverage of all refs remains the responsibility
of "git maintenance", "git gc" and "git commit-graph write".
Regular Git operations may trigger "git maintenance run --auto",
which periodically rebuilds the commit-graph from all reachable
refs.
The effect was measured on a synthetic setup: git.git with 200K
extra packed refs (~206K total), a local file:// remote, an existing
split commit-graph and a warm page cache. The times below are the
median of 9 runs of the trace2 region fetch/write-commit-graph:
scenario before after
no-op fetch 380 ms (skipped)
1 ref updated 357 ms 9.3 ms
10 refs updated 359 ms 8.9 ms
Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The value of the fetch.followRemoteHEAD configuration variable is
validated while the configuration file is being parsed, which
produces a warning even when this particular "git fetch" invocation
will never consult it.
Store the raw config string instead, and resolve/validate it lazily
at the one place in do_fetch() that actually uses it, so a mistyped
value only warns, and a missing value only dies, when this fetch
would have consulted it.
remote.c's handle_config() has the same problem for
remote.<name>.followRemoteHEAD, but is left unaddressed here since
it touches shared remote-parsing infrastructure used well beyond
fetch. Leave a NEEDSWORK comment at remote.c:handle_config()
that has a defect similar to what is fixed by this patch,
so the remaining scope is easy to find for a follow-up patch.
Signed-off-by: Colin Hinton <colinlewishinton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The sequencer machinery (used by 'git rebase', 'git cherry-pick', and
'git revert') has been updated to defer automatic maintenance tasks
until the end of the operation, preventing nested 'git commit', 'git
merge', and 'exec' commands from triggering GC operations that could
contend for locks or delete open packs while the sequence is in
progress.
* tb/rerere-lock-grace:
sequencer: disable auto maintenance in spawned commands
rebase, cherry-pick, revert: run auto maintenance when done
config: add git_config_append_parameter()
Before it creates a stash, git checks if there are any unstaged,
or uncommitted changes. If there isn't anything to stash it bails
out. "git stash push" checks for changes twice, once in do_push_stash()
and then again in do_create_stash(). Avoid that by removing the call
to check_changes() from do_push_stash() and checking the return value
of do_create_stash() to see if there were any changes to stash. If
check_changes() finds there are no changes do_create_stash() now
returns 2 rather than 1. This enables us to distinguish between there
being no changes and there being nothing stashed so that "git stash
push --patch" when nothing is select, and "git stash push --staged"
when the index matches HEAD still exit 1 rather than 0.
There is still one small change in behavior as, if there is nothing
to stash, we'll try now to create the reflog for stashes before we
realize that there is nothing to stash. I don't think that should
matter in practice.
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Before it creates a stash, git checks if there are any unstaged,
or uncommitted changes. If there isn't anything to stash it bails
out. Since ef0f0b4509 (stash: optimize `get_untracked_files()`
and `check_changes()`, 2019-02-25) "git stash store" has checked
for changes twice, once in create_stash() before we refresh the
index and then again in do_create_stash() after the index has been
refreshed. That commit claims it is an optimization but it is not
clear what it is trying to optimize by checking for changes twice,
especially as checking for changes before refreshing the index is
unreliable (the scripted version of "git stash store", called "git
update-index -q --refresh" before looking for any changes).
Avoid checking for changes twice by removing the call to
check_changes_tracked_files() from store_stash() and restore the return
code handling in store_stash() that was removed by ef0f0b4509 so that
we continue to exit 0 when there are no changes to stash. In principle
we could remove the call to check_changes() from do_store_stash()
instead, but then we'd need to pass in the list of untracked files.
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
As part of 2f28db44d5 (Merge branch 'ps/ref-storage-format', 2026-10-01)
we have adapt all sites that used to say "reference format" to instead
say "reference storage format".
One missed spot though was in git-repo(1), where we still print the
"references.format" key. Fix that oversight by renaming the key to
"references.storageFormat".
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
git-format-patch(1) passes on the notes behavior that it is using for
the patches to git-range-diff(1). In turn you get the same Git notes
displayed in the range diff as the ones you used to generate the
patches. And that makes sense in most cases.
However, I often make notes between series versions that mostly prepend
to the original. They end up looking like this:
v3:
[desc.]
v2:
[descr.]
v1:
[descr.]
These notes are meant for the git-format-patch(1) output since they
document the iterations. But including them also includes them in the
range diff. And they have nothing useful to say there.
Let’s teach git-format-patch(1) `--[no-]range-diff-notes` so that we
can pass in different notes refs to the range diff, or just turn them
off entirely.
In addition to storing the list of notes, we also need a boolean
`override` to distinguish these two cases:
1. No such options were given and empty list (use `--notes`)
2. Options were given and empty list (`--no-...` given; don’t use notes)
Unlike `--creation-factor`, `--[no-]range-diff-notes` does not error out
when used without `--range-diff`. This flexibility accommodates
workflows where users might configure default options in aliases or
wrapper scripts, allowing `--range-diff` to be toggled independently.
Add two tests here for the single-patch case, i.e. the case where the
range diff is on the patch and not in the cover letter. These are meant
as regression tests based on my encounter with single-patch range diff
notes handling bug.[1]
† 1: 155986b4 (format-patch: handle range-diff on notes correctly for
single patches, 2025-09-25)
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
85bd88a7 (revision: add rdiff_log_arg to rev_info, 2025-09-25) added
`rdiff_log_arg` to `struct rev_info`. `get_notes_arg` was changed to
take a second parameter, namely that member:
get_notes_args(&(rev.rdiff_log_arg), &rev);
But this is obviously unnecessary; we can just use `&rev`.
Now is also a good time to format this `for_each...` line since it’s
gotten quite long.
Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The code that stashes all untracked files compares the value of the
"include_untracked" variable to the constant "INCLUDE_ALL_FILES",
however the option parsing code for "--all" uses a hard coded integer
instead. Replace the integer with the named constant.
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
'git pull' has been taught to fail more gracefully instead of
segfaulting when lookup_commit_reference() fails on unparseable
objects.
* jk/pull-null-merge-head:
pull: avoid segfault when commit lookup fails
The git-refs(1) command nowadays has a bunch of different subcommands,
which makes it hard to figure out what's what at a glance. Now that the
parse-options subsystem supports grouping subcommands though we can do
better. The commands roughly fall into the following categories:
- Operations that span across the whole reference database.
- Operations that read references.
- Operations that write references.
Introduce these groups accordingly, which results in the following help
output:
Reference database
migrate migrate the reference database to a different format
verify verify the consistency of the reference database
optimize optimize the reference database
Reading references
list list references
exists check whether a reference exists
Writing references
create create a new reference
delete delete a reference
update update an existing reference
rename rename a reference
Reorder the usage strings to match the new grouping.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The `OPT_GROUP()` macro can be used to create a new group. These groups
can only be used to group options though, they do not have any effect
when used in combination with subcommands. As our use of subcommands
grows though it can be quite useful to group these, as well.
Extend `OPT_SUBCOMMAND_F()` to take an optional help string. If given,
such subcommands will be considered as part of `OPT_GROUP()` and printed
with that help string.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
A previous commit added a new "uploadpack.lazyFetchTrusted" protected
config variable that can contain an allowlist of repos, as well as
functions to check if the current repo is in that list. But when the
current repo is in that list, we currently do nothing.
Since 7b70e9efb1 (upload-pack: disable lazy-fetching by default,
2024-04-16), `upload-pack` sets `GIT_NO_LAZY_FETCH` to 1 itself,
unconditionally, because by default it shouldn't trust the repositories
it serves. Lazily fetching runs `git fetch`, which may execute
arbitrary commands specified in the configuration and hooks of the
served repo.
The new "uploadpack.lazyFetchTrusted" protected config variable is not
about overriding an environment variable. It's rather about teaching
the code that automatically sets `GIT_NO_LAZY_FETCH` (because it had no
way to know if the served repo could be trusted) to look at the new
config variable to find out if a server operator actually vouched for
that repo.
Let's implement that, so we now have the following cases:
- if `GIT_NO_LAZY_FETCH` is already set, we honor it and leave it
alone, as it comes from the server operator,
- otherwise, if the served repo is in the
"uploadpack.lazyFetchTrusted" allowlist, we don't disable lazy
fetching,
- otherwise, we disable lazy fetching, as we used to.
This allows `upload-pack` and its `pack-objects` child process to
lazily fetch the objects they need to serve a client, for example when
the filter used by the client and the one used by the server don't
match.
Note that what a server operator vouches for by listing a repo there
is that the promisor remotes this repo is configured to lazily fetch
from, as well as its configuration and hooks, are trustworthy. Whether
a client trusts the repo it fetches from is a separate matter, and up
to the client.
As `pack-objects`, which performs the lazy fetch when serving a
client, is a child process of `upload-pack`, not setting
`GIT_NO_LAZY_FETCH` in `upload-pack` is enough for it to be allowed to
lazily fetch, without any further plumbing.
On the other hand, as we leave `GIT_NO_LAZY_FETCH` unset for a trusted
repo instead of setting it to 0, the trust doesn't propagate: if a
trusted repo lazily fetches from a promisor remote that is itself
served by `upload-pack` on the same machine, that nested `upload-pack`
decides for its own repo. This is unlike when a server operator sets
`GIT_NO_LAZY_FETCH` to 0, as that is inherited by all child processes.
Now that "uploadpack.lazyFetchTrusted" is actually doing something,
let's document it (including this difference with `GIT_NO_LAZY_FETCH`),
let's reference it from `GIT_NO_LAZY_FETCH`'s docs, and let's add tests
for it.
Signed-off-by: Christian Couder <christian.couder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The build-time knob 'USE_NSEC' for nanosecond stat precision has been
converted to a runtime configuration 'core.useNanosec', allowing
distributions to bundle one binary that adapts to filesystem
capabilities dynamically.
* dk/use-nsec-runtime:
core: convert build-time USE_NSEC into runtime core.useNanosec
environment: align repo_config_values_init with struct declaration
meson: expose knob for xmlto relative links in manuals
The terminology regarding reference storage formats has been unified
across command-line options, environment variables, configuration
variables, and source code, standardizing on the phrase "ref storage
format" (e.g., `--ref-storage-format`, `'GIT_REF_STORAGE_FORMAT'`).
Additionally, the `--ref-storage-format` option has been updated to
accept payloads in the form `<format>://<payload>`.
* ps/ref-storage-format:
setup: allow "--ref-storage-format=" to specify a payload
setup: rename "init.defaultRefFormat" to "init.defaultRefStorageFormat"
t: rename GIT_TEST_DEFAULT_REF_FORMAT
setup: rename ref storage format environment variables
setup: refactor how we configure the ref storage format
refs: expose function to parse reference URIs
help: rename "default-ref-format" to "default-ref-storage-format"
builtin/rev-parse: rename "--show-ref-format" to "--show-ref-storage-format"
builtin/submodule: rename "--ref-format=" to "--ref-storage-format="
builtin/refs: rename "--ref-format=" to "--ref-storage-format="
builtin/clone: rename "--ref-format=" to "--ref-storage-format="
builtin/init: rename "--ref-format=" to "--ref-storage-format="
parse-options: allow for hidden aliases
A new hook 'report' is added to 'git receive-pack', which runs after
reference updates and allows the server to filter or modify the
packet-line status report sent back to the client.
* kn/receive-report-hook:
receive-pack: coccinelle fix
hook: introduce the receive-report hook
receive-pack: move message generation to separate function
receive-pack: drop static variables to track report status version
doc: add proc-receive hook info in 'git-receive-pack.adoc'
The experimental 'git history' command has been taught a new 'squash'
subcommand to fold a range of commits into a single commit, with any
descendants replayed on top.
* hn/history-squash:
history: support editing squashed commit messages
history: create squashed commits without editing
history: protect branches when squashing a range
history: validate squash revision ranges
history: add skeleton for squash subcommand
sequencer: share the squash message marker helpers and flags
history: give commit_tree_ext a message template
history: extract helper for a commit's parent tree
The setup of alternates has been deferred to object database
creation time during clone, which drops the unused ad-hoc alternate
writing API, simplifying the object database backend interface.
* ps/odb-alternates-at-creation:
odb/source: remove the ability to write alternates
builtin/clone: write alternates via `odb_create_on_disk()`
odb/source: support writing alternates when creating the database
builtin/clone: move setup of alternates for non-shared local clones
builtin/clone: move setup of alternates for shared local clones
builtin/clone: refactor handling of "--reference{,-if-able}"
builtin/clone: move around `setup_reference()`
builtin/clone: defer setup of the object database
setup: split up concerns of `init_db()`
"git stash apply --index" does a 2-step dance to report index conflicts
before carrying out the main unstash: first, attempt to merge the index
(and remember the name of the resulting tree). If that succeeds, reset
the index and carry on unstashing the working tree, then use the
remembered index tree to unstash the index.
The "merge the index" step is performed on the actual index by a
combination of git-diff-tree(1) and git-apply(1), which incurs an extra
cost to git-reset(1) to cleanup. This also introduces an autostash bug
when stash.index is true: "git reset" eventually wants to
remove_merge_branch_state(), which calls save_autostash() due to
a03b55530a (merge: teach --autostash option, 2020-04-07). This can
happen from a "git merge --autostash", which itself calls
save_autostash(). Operating on the file-system in this way is not
re-entrant, so we end up trying to lock a now-deleted MERGE_AUTOSTASH
ref [1]. This bug has lurked for a while, but it would have been
impossible to trigger without the availability of stash.index to force
the autostash apply into index mode.
[1]: https://lore.kernel.org/git/CALO-guvbk2TcrVwzdNQ3yRpzHr0HHZ3h1wite0Xp0sUyAT4otA@mail.gmail.com/
Fortunately, we can achieve 2 goals at once: avoid round-tripping to the
file-system (and invoking expensive subprocesses) by performing the
merge in-core. If there are conflicts, we discard the resulting tree, so
we don't see the usual branch and ancestor labels, but the merge
subroutines insist on their presence, so use something simple.
We need to take care to get the order of trees right when merging. Add a
test that covers this case.
We *could* swap just the git-reset(1) subprocess with our internal
reset_tree() and refresh_index(), which would fix the bug. We'd much
prefer to clean up these vestiges of the shell-based git-stash, though.
Reported-by: Eli Barzilay <eli@barzilay.org>
Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
In a future commit, we will reuse these options for the index merge of
"apply --index", not just for the worktree.
Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Clang complains that oid-array.h is unused. Certainly none of the
oid_array* functions, types, etc., are used, and the
transitively-included hash.h declarations are used but covered by a
pre-existing direct #include of hash.h.
Signed-off-by: D. Ben Knoble <ben.knoble@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Our import of xdiff has two identical buffer structures: mmfile_t and
mmbuffer_t. In upstream xdiff these were actually different, but the
import in 3443546f6e (Use a *real* built-in diff generator, 2006-03-24)
simplified mmfile_t to a simple buffer.
In xdiff we usually use mmfile_t for input and mmbuffer_t for output,
but they are really both just a ptr/len pair. I don't think that having
different types is buying us anything in terms of type safety or
semantics, and having two makes it awkward to use the same helpers for
both. In particular, an external merge driver's output is read from a
file, but we can't easily use read_mmfile(), since we want the result in
an mmbuffer_t.
Let's use mmfile_t for both cases and drop mmbuffer_t. The latter is
probably a more descriptive name, but we have many more uses of
mmfile_t (and helpers like read_mmfile). So let's consolidate using that
name; we can always change it to something more sensible later.
There should be no behavior change here; this is just consolidating the
types.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When read_mmfile() returns an error, it may or may not have allocated a
buffer in the passed-in mmfile_t. So callers must initialize the pointer
to NULL and free it even on error.
Most callers do this already, but rerere's diff_two() does not, and
would leak the buffer after a read error. We could fix it directly, but
let's instead try to make the interface less error-prone by freeing the
memory when returning failure from read_mmfile().
This fixes (part of) the leak in diff_two(). In theory it also lets us
simplify other callers to skip initializing the mmfile. But in practice
most still need zero-initialization because they may jump to free()
before even calling read_mmfile (e.g., in try_merge()). But we can at
least simplify rerere_forget_one_path() a bit.
I said "part of" earlier. There's a related leak in diff_two(): if
reading the first file succeeds but reading the second fails, we return
early and leak the first buffer. We can fix that by checking each
individually.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>