aboutsummaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2026-03-30receive-pack: use worktree HEAD for updateInsteadPablo Sabater
When a bare repo has linked worktrees, and its HEAD points to an unborn branch, pushing to a wt branch with updateInstead fails and rejects the push, even if the wt is clean. This happens because HEAD is checked only for the bare repo context, instead of the wt. Remove head_has_history and check for worktree->head_oid which does have the correct HEAD of the wt. Update the test added by Runxi's patch to expect success. Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-30t5516: clean up cloned and new-wt in denyCurrentBranch and worktrees testPablo Sabater
The 'denyCurrentBranch and worktrees' test creates a 'cloned' and a 'new-wt' but it doesn't clean them after the test. This makes other tests that use the same name after this one to fail. Add test_when_finished to clean them at the end. Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-30t5516: test updateInstead with worktree and unborn bare HEADRunxi Yu
This is a regression test which should presently fail, to demonstrate the behavior I encountered that looks like a bug. When a bare repository has a worktree checked out on a separate branch, receive.denyCurrentBranch=updateInstead should allow a push to that branch and update the linked worktree, as long as the linked worktree is clean. But, if the bare repository's own HEAD is repointed to an unborn branch, the push is rejected with "Working directory has staged changes", even though the linked worktree itself is clean. This test is essentially a minimal working example of what I encountered while actually using Git; it might not be the optimal way to demonstrate the underlying bug. I suspect builtin/receive-pack.c is using the bare repository's HEAD even when comparing it to the worktree's index. Signed-off-by: Runxi Yu <me@runxiyu.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-30docs: fix "git stash [push]" documentationQuentin Bernet
Both the synopsis and explanation are incorrect and contradict each other. The synopsis claims "push" can only be omitted when you do not give any options and arguments. The explanation correctly claims that non-option arguments are not allowed, except pathspec elements preceded by double hyphens. But it also adds "-p" to the list of exceptions, even though it is an option argument. Signed-off-by: Quentin Bernet <quentin.bernet@bluewin.ch> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-28doc: gitignore: clarify pattern base for info/exclude and core.excludesFileShreyansh Paliwal
The pattern format section describes how patterns are interpreted relative to the location of a .gitignore file, but does not mention the behavior for exclude sources outside the working tree. Clarify that patterns from $GIT_DIR/info/exclude and core.excludesFile are treated as if they are specified at the root of the working tree, so a leading '/' anchors matches at the repository root. Reported-by: Dan Drake <dan@dandrake.org> Signed-off-by: Shreyansh Paliwal <shreyanshpaliwalcmsmn@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-28t6101: avoid suppressing git's exit codeTrieu Huynh
Update t6101-rev-parse-parents.sh to redirect git-rev-parse output to a temporary file instead of piping it directly to not hide the exit code of git commands behind pipes, as a crash in git might go unnoticed. Signed-off-by: Trieu Huynh <vikingtc4@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-28t8003: modernise styleTrieu Huynh
Remove the blank lines at both ends of each test_expect_success body to match the modern style used elsewhere in the test suite. Signed-off-by: Trieu Huynh <vikingtc4@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-28t8003: avoid suppressing git's exit codeTrieu Huynh
Update t8003-blame-corner-cases.sh to redirect git-blame output to a temporary file instead of piping it directly to not hide the exit code of git commands behind pipes, as a crash in git might go unnoticed. Signed-off-by: Trieu Huynh <vikingtc4@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-28t2000: modernise overall structureZakariyah Ali
This test script that dates back to 2005 certainly shows its age and both its style and the way the tests are laid out do not match the modern standard. * Executables that prepare the data used to test the command should be inside the test_expect_success block in modern tests. * In modern tests, running a command that is being tested, making sure it succeeds, and inspecting other side effects that are expected, are all done in a single test_expect_success block. * A test_expect_success block in modern tests are laid out as test_expect_success 'title of the test' ' body of the test && ... body of the test ' not as test_expect_success \ 'title of the test' \ 'body of the test && ... body of the test' which is in a prehistoric style. * In modern tests, each &&-chained statement in the body of the test_expect_success block are indented with a horizontal tab, unlike prehistoric style that used 4-space indent. Signed-off-by: Zakariyah Ali <zakariyahali100@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-27repack: mark non-MIDX packs above the split as excluded-openTaylor Blau
In 5ee86c273bf (repack: exclude cruft pack(s) from the MIDX where possible, 2025-06-23), geometric repacking learned to exclude cruft packs from the MIDX when 'repack.midxMustContainCruft' is set to 'false'. This works because packs generated with '--stdin-packs=follow' rescue any once-unreachable objects that later become reachable, making the resulting packs closed under reachability without needing the cruft pack in the MIDX. However, packs above the geometric split that were not part of the previous MIDX may not have full object closure. When such packs are marked as excluded-closed ('^'), pack-objects treats them as a reachability boundary and does not traverse through them during the follow pass, potentially leaving the resulting pack without full closure. Fix this by marking packs above the geometric split that were not in the previous MIDX as excluded-open ('!') instead of excluded-closed ('^'). This causes pack-objects to walk through their commits during the follow pass, rescuing any reachable objects not present in the closed-excluded packs. Note that MIDXs which were generated prior to this change and are unlucky enough to not be closed under reachability may still exhibit this bug, as we treat all MIDX'd packs as closed. That is true in an overwhelming number of cases, since in order to have a non-closed MIDX you would have to: - Generate a pack via an earlier geometric repack that is not closed under reachability. - Store that pack in the MIDX. - Avoid picking any commits to receive reachability bitmaps which happen to reach objects from which the missing objects are reachable. In the extremely rare chance that all of the above should happen, an all-into-one repack will resolve the issue. Unfortunately, there is no perfect way to determine whether a MIDX'd pack is closed outside of ensuring that there is a '1' bit in at least one bitmap for every bit position corresponding to objects in that pack. While this is possible to do, this approach would treat MIDX'd packs as open in cases where there is at least one object that is not reachable from the subset of commits selected for bitmapping. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-27pack-objects: support excluded-open packs with --stdin-packsTaylor Blau
In cd846bacc7d (pack-objects: introduce '--stdin-packs=follow', 2025-06-23), pack-objects learned to traverse through commits in included packs when using '--stdin-packs=follow', rescuing reachable objects from unlisted packs into the output. When we encounter a commit in an excluded pack during this rescuing phase we will traverse through its parents. But because we set `revs.no_kept_objects = 1`, commit simplification will prevent us from showing it via `get_revision()`. (In practice, `--stdin-packs=follow` walks commits down to the roots, but only opens up trees for ones that do not appear in an excluded pack.) But there are certain cases where we *do* need to see the parents of an object in an excluded pack. Namely, if an object is rescue-able, but only reachable from object(s) which appear in excluded packs, then commit simplification will exclude those commits from the object traversal, and we will never see a copy of that object, and thus not rescue it. This is what causes the failure in the previous commit during repacking. When performing a geometric repack, packs above the geometric split that weren't part of the previous MIDX (e.g., packs pushed directly into `$GIT_DIR/objects/pack`) may not have full object closure. When those packs are listed as excluded via the '^' marker, the reachability traversal encounters the sequence described above, and may miss objects which we expect to rescue with `--stdin-packs=follow`. Introduce a new "excluded-open" pack prefix, '!'. Like '^'-prefixed packs, objects from '!'-prefixed packs are excluded from the resulting pack. But unlike '^', commits in '!'-prefixed packs *are* used as starting points for the follow traversal, and the traversal does not treat them as a closure boundary. In order to distinguish excluded-closed from excluded-open packs during the traversal, introduce a new `pack_keep_in_core_open` bit on `struct packed_git`, along with a corresponding `KEPT_PACK_IN_CORE_OPEN` flag for the kept-pack cache. In `add_object_entry_from_pack()`, move the `want_object_in_pack()` check to *after* `add_pending_oid()`. This is necessary so that commits from excluded-open packs are added as traversal tips even though their objects won't appear in the output. As a consequence, the caller `for_each_object_in_pack()` will always provide a non-NULL 'p', hence we are able to drop the "if (p)" conditional. The `include_check` and `include_check_obj` callbacks on `rev_info` are used to halt the walk at closed-excluded packs, since objects behind a '^' boundary are guaranteed to have closure and need not be rescued. The following commit will make use of this new functionality within the repack layer to resolve the test failure demonstrated in the previous commit. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-27t7704: demonstrate failure with once-cruft objects above the geometric splitTaylor Blau
Add a test demonstrating a case where geometric repacking fails to produce a pack with full object closure, thus making it impossible to write a reachability bitmap. Mark the test with 'test_expect_failure' for now. The subsequent commit will explain the precise failure mode, and implement a fix. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-27pack-objects: refactor `read_packs_list_from_stdin()` to use `strmap`Taylor Blau
The '--stdin-packs' mode of pack-objects maintains two separate string_lists: one for included packs, and one for excluded packs. Each list stores the pack basename as a string and the corresponding `packed_git` pointer in its `->util` field. This works, but makes it awkward to extend the set of pack "kinds" that pack-objects can accept via stdin, since each new kind would need its own string_list and duplicated handling. A future commit will want to do just this, so prepare for that change by handling the various "kinds" of packs specified over stdin in a more generic fashion. Namely, replace the two `string_list`s with a single `strmap` keyed on the pack basename, with values pointing to a new `struct stdin_pack_info`. This struct tracks both the `packed_git` pointer and a `kind` bitfield indicating whether the pack was specified as included or excluded. Extract the logic for sorting packs by mtime and adding their objects into a separate `stdin_packs_add_pack_entries()` helper. While we could have used a `string_list`, we must handle the case where the same pack is specified more than once. With a `string_list` only, we would have to pay a quadratic cost to either (a) insert elements into their sorted positions, or (b) a repeated linear search, which is accidentally quadratic. For that reason, use a strmap instead. This patch does not include any functional changes. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-27pack-objects: plug leak in `read_stdin_packs()`Taylor Blau
The `read_stdin_packs()` function added originally via 339bce27f4f (builtin/pack-objects.c: add '--stdin-packs' option, 2021-02-22) declares a `rev_info` struct but neglects to call `release_revisions()` on it before returning, creating the potential for a leak. The related change in 97ec43247c0 (pack-objects: declare 'rev_info' for '--stdin-packs' earlier, 2025-06-23) carried forward this oversight and did not address it. Ensure that we call `release_revisions()` appropriately to prevent a potential leak from this function. Note that in practice our `rev_info` here does not have a present leak, hence t5331 passes cleanly before this commit, even when built with SANITIZE=leak. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-27format-patch: removing unconditional wrappingMirko Faina
Using format-patch with --commit-list-format different than shortlog, causes the commit entry lines to wrap if they get longer than MAIL_DEFAULT_WRAP (72 characters). While this might be sensible for many when sending changes through email, it forces this decision of wrapping on the user, reducing the control granularity of --commit-list-format. Teach generate_commit_list_cover() to respect commit entry line lengths and place this wrapping rule on the "modern" preset format instead. Signed-off-by: Mirko Faina <mroik@delayed.space> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-27docs: fix --commit-list-format related entriesMirko Faina
Documentation specifies that "git format-patch" would default to format.commitListFormat if --commit-list-format is not given, but doesn't specify the default if the format.commitListFormat is not set. The text for --cover-letter is also obsolete as the commit list can now be something other than a shortlog. Document to reflect changes. Signed-off-by: Mirko Faina <mroik@delayed.space> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-27The 22nd batchJunio C Hamano
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-27Merge branch 'jc/rerere-modern-strbuf-handling'Junio C Hamano
Code clean-up overdue by 19 years. * jc/rerere-modern-strbuf-handling: cocci: strbuf.buf is never NULL rerere: update to modern representation of empty strbufs
2026-03-27Merge branch 'kh/doc-interpret-trailers-1'Junio C Hamano
Doc updates. * kh/doc-interpret-trailers-1: interpret-trailers: use placeholder instead of * doc: config: convert trailers section to synopsis style doc: interpret-trailers: normalize and fill out options doc: interpret-trailers: convert to synopsis style
2026-03-27Merge branch 'ej/ref-transaction-hook-preparing'Junio C Hamano
The reference-transaction hook was taught to be triggered before taking locks on references in the "preparing" phase. * ej/ref-transaction-hook-preparing: refs: add 'preparing' phase to the reference-transaction hook
2026-03-27Merge branch 'mf/apply-p-no-atoi'Junio C Hamano
"git apply -p<n>" parses <n> more carefully now. * mf/apply-p-no-atoi: apply.c: fix -p argument parsing
2026-03-27Merge branch 'gi/doc-boolean-config-typofix'Junio C Hamano
Doc typofix. * gi/doc-boolean-config-typofix: doc: add missing space on git-config page
2026-03-27Merge branch 'mr/merge-file-object-id-worktree-fix'Junio C Hamano
merge-file --object-id used to trigger a BUG when run in a linked worktree, which has been fixed. * mr/merge-file-object-id-worktree-fix: merge-file: fix BUG when --object-id is used in a worktree
2026-03-27Merge branch 'rs/prio-queue-to-commit-stack'Junio C Hamano
Uses of prio_queue as a LIFO stack of commits have been written with commit_stack. * rs/prio-queue-to-commit-stack: use commit_stack instead of prio_queue in LIFO mode
2026-03-27Merge branch 'ps/build-tweaks'Junio C Hamano
Tweak the build infrastructure by moving tools around. * ps/build-tweaks: meson: precompile "git-compat-util.h" meson: compile compatibility sources separately git-compat-util.h: move warning infra to prepare for PCHs builds: move build scripts into "tools/" contrib: move "update-unicode.sh" script into "tools/" contrib: move "coverage-diff.sh" script into "tools/" contrib: move "coccinelle/" directory into "tools/" Introduce new "tools/" directory
2026-03-27Merge branch 'jk/diff-highlight-identical-pairs'Junio C Hamano
The handling of the incomplete lines at the end by "git diff-highlight" has been fixed. * jk/diff-highlight-identical-pairs: contrib/diff-highlight: do not highlight identical pairs
2026-03-26Merge branch 'mf/format-patch-commit-list-format' into ↵Junio C Hamano
mf/format-patch-commit-list-format-doc * mf/format-patch-commit-list-format: format-patch: --commit-list-format without prefix format-patch: add preset for --commit-list-format format-patch: wrap generate_commit_list_cover() format.commitListFormat: strip meaning from empty docs/pretty-formats: add %(count) and %(total) format-patch: rename --cover-letter-format option format-patch: refactor generate_commit_list_cover pretty.c: better die message %(count) and %(total) docs: add usage for the cover-letter fmt feature format-patch: add commitListFormat config format-patch: add ability to use alt cover format format-patch: move cover letter summary generation pretty.c: add %(count) and %(total) placeholders
2026-03-26config: store allocated string in non-const pointerJeff King
When git-config matches a url, we copy the variable section name and store it in the "section" member of a urlmatch_config struct. That member is const, since the url-matcher will not touch it (and other callers really will have a const string). But that means that we have only a const pointer to our allocated string. We have to cast away the constness when we free it, and likewise when we assign NUL to tie off the "." separating the subsection and key. This latter happens implicitly via a strchr() call, but recent versions of glibc have added annotations that let the compiler detect that and complain. Let's keep our own "section" pointer for the non-const string, and then just point config.section at it. That avoids all of the casting, both explicit and implicit. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26rev-parse: avoid writing to const string for parent marksJeff King
The previous commit cleared up some const confusion in handling parent marks in revision.c, but we have roughly the same code duplicated in rev-parse. This one is much easier to fix, because the handling of the shortened string is all done in one place, after detecting any marks (but without shortening the string between marks). As a side note, I suspect this means that it behaves differently than the revision.c parser for weird stuff like "foo^!^@^-", but that is outside the scope of this patch. While we are here, let's also rename the variable "dotdot", which is totally misleading (and which we already fixed in revision.c long ago via f632dedd8d (handle_revision_arg: stop using "dotdot" as a generic pointer, 2017-05-19)). Doing that here makes the diff a little messier, but it also lets the compiler help us make sure we did not miss any stray mentions of the variable while we are changing its semantics. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26revision: avoid writing to const string for parent marksJeff King
We take in a "const char *", but may write a NUL into it when parsing parent marks like "foo^-", since we want to isolate "foo" as a string for further parsing. This is usually OK, as our "const" strings are often actually argv strings which are technically writeable, but we'd segfault with a string literal like: handle_revision_arg("HEAD^-", &revs, 0, 0); Similar to how we handled dotdot in a previous commit, we can avoid this by making a temporary copy of the left-hand side of the string. The cost should negligible compared to the rest of the parsing (like actually parsing commits to create their parent linked-lists). There is one slightly tricky thing, though. We parse some of the marks progressively, so that if we see "foo^!" for example, we'll strip that down to "foo" not just for calling add_parents_only(), but also for the rest of the function. That makes sense since we eventually want to pass "foo" to get_oid_with_context(). But it also means that we'll keep looking for other marks. In particular, "foo^-^!" is valid, though oddly "foo^!^-" would ignore the "^-". I'm not sure if this is a weird historical artifact of the implementation, or if there are important corner cases. So I've left the behavior unchanged. Each mark we find allocates a string with the mark stripped, which means we could allocate multiple times (and carry a free-able pointer for each to the end). But in practice we won't, because of the three marks, "^@" jumps immediately to the end without further parsing, and "^-^!" is nonsense that nobody would pass. So you'd get one allocation in general, and never more than two. Another obvious option would be to just copy "arg" up front and be OK with munging it. But that means we pay the cost even when we find no marks. We could make a single copy upon finding a mark and then munge, but that adds extra code to each site (checking whether somebody else allocated, and if not, adjusting our "mark" pointer to be relative to the copied string). I aimed for something that was clear and obvious, if a bit verbose. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26rev-parse: simplify dotdot parsingJeff King
The previous commit simplified the way that revision.c parses ".." and "..." range operators. But there's roughly similar code in rev-parse. This is less likely to trigger a segfault, as there is no library function which we'd pass a string literal to, but it still causes the compiler to complain about laundering away constness via strstr(). Let's give it the same treatment, copying the left-hand side of the range operator into its own string. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26revision: make handle_dotdot() interface less confusingJeff King
There are two very subtle bits to the way we parse ".." (and "...") range operators: 1. In handle_dotdot_1(), we assume that the incoming arguments "dotdot" and "arg" are part of the same string, with the first digit of the range-operator blanked to a NUL. Then when we want the full name (e.g., to report an error), we replace the NUL with a dot to restore the original string. 2. In handle_dotdot(), we take in a const string, but then we modify it by overwriting the range operator with a NUL. This has worked OK in practice since we tend to pass in buffers that are actually writeable (including argv), but segfaults with something like: handle_revision_arg("..HEAD", &revs, 0, 0); On top of that, building with recent versions of glibc causes the compiler to complain, because it notices when we use strchr() or strstr() to launder away constness (basically detecting the possibility of the segfault above via the type system). Instead of munging the buffer, let's instead make a temporary copy of the left-hand side of the range operator. That avoids any const violations, and lets us pass around the parsed elements independently: the left-hand side, the right-hand side, the number of dots (via the "symmetric" flag), and the original full string for error messages. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26fast-import: add 'abort-if-invalid' mode to '--signed-tags=<mode>'Justin Tobler
In git-fast-import(1), the 'abort-if-invalid' mode for the '--signed-commits' option verifies commit signatures during import and aborts the entire operation when verification fails. Extend the same behavior to signed tag objects by introducing an 'abort-if-invalid' mode for the '--signed-tags' option. Signed-off-by: Justin Tobler <jltobler@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26fast-import: add 'sign-if-invalid' mode to '--signed-tags=<mode>'Justin Tobler
With ee66c793f8 (fast-import: add mode to sign commits with invalid signatures, 2026-03-12), git-fast-import(1) learned to verify commit signatures during import and replace signatures that fail verification with a newly generated one. Extend the same behavior to signed tag objects by introducing a 'sign-if-invalid' mode for the '--signed-tags' option. Signed-off-by: Justin Tobler <jltobler@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26fast-import: add 'strip-if-invalid' mode to '--signed-tags=<mode>'Justin Tobler
With c20f112e51 (fast-import: add 'strip-if-invalid' mode to --signed-commits=<mode>, 2025-11-17), git-fast-import(1) learned to verify commit signatures during import and strip signatures that fail verification. Extend the same behavior to signed tag objects by introducing a 'strip-if-invalid' mode for the '--signed-tags' option. Signed-off-by: Justin Tobler <jltobler@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26fast-import: add 'abort-if-invalid' mode to '--signed-commits=<mode>'Justin Tobler
The '--signed-commits=<mode>' option for git-fast-import(1) configures how signed commits are handled when encountered. In cases where an invalid commit signature is encountered, a user may wish to abort the operation entirely. Introduce an 'abort-if-invalid' mode to do so. Signed-off-by: Justin Tobler <jltobler@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26fast-export: check for unsupported signing modes earlierJustin Tobler
The '--signed-{commits,tags}' options for git-fast-export(1) support only a subset of the modes accepted by git-fast-import(1). Unsupported modes such as 'strip-if-invalid' and 'sign-if-invalid' are accepted during option parsing, but cause the command to die later when a signed object is encountered. Instead, reject unsupported signing modes immediately after parsing the option. This treats them the same as other unknown modes and avoids deferring the error until object processing. This also removes duplicated checks in commit/tag handling code. Signed-off-by: Justin Tobler <jltobler@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26t5620: test backfill's unknown argument handlingDerrick Stolee
Before the recent changes to parse rev-list arguments inside of 'git backfill', the builtin would take arbitrary arguments without complaint (and ignore them). This was noticed and a patch was sent [1] which motivates this change. [1] https://lore.kernel.org/git/20260321031643.5185-1-r.siddharth.shrimali@gmail.com/ Note that the revision machinery can output an "ambiguous argument" warning if a value not starting with '--' is found and doesn't make sense as a reference or a pathspec. For unrecognized arguments starting with '--' we need to add logic into builtin/backfill.c to catch leftover arguments. Reported-by: Siddharth Shrimali <r.siddharth.shrimali@gmail.com> Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26path-walk: support wildcard pathspecs for blob filteringDerrick Stolee
Previously, walk_objects_by_path() silently ignored pathspecs containing wildcards or magic by clearing them. This caused all blobs to be downloaded regardless of the given pathspec. Wildcard pathspecs like "d/file.*.txt" are useful for narrowing which blobs to process (e.g., during 'git backfill'). Support wildcard pathspecs by making two changes: 1. Add an 'exact_pathspecs' flag to path_walk_context. When the pathspec has no wildcards or magic, set this flag and use the existing fast-path prefix matching in add_tree_entries(). When wildcards are present, skip that block since prefix matching cannot handle glob patterns. 2. Add a match_pathspec() check in walk_path() to filter out blobs whose full path does not match the pathspec. This provides the actual blob-level filtering for wildcard pathspecs. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26backfill: work with prefix pathspecsDerrick Stolee
The previous change allowed specifying revision arguments over the 'git backfill' command-line. This created the opportunity for restricting the initial commit set by filtering the revision walk through a pathspec. Other than filtering the commit set (and thereby the root trees), this did not restrict the path-walk implementation of 'git backfill' and did not restrict the blobs that were downloaded to only those matching the pathspec. Update the path-walk API to accept certain kinds of pathspecs and to silently ignore anything too complex, for now. We will update this in the next change to properly restrict to even complex pathspecs. The current behavior focuses on pathspecs that match paths exactly. This includes exact filenames, including directory names as prefixes. Pathspecs containing wildcards or magic are cleared so the path walk downloads all blobs, as before. The reason for this restriction is to allow for a faster execution by pruning the path walk to only trees that could contribute towards one of those paths as a parent directory. The test directory 'd/f/' (next to 'd/file*.txt') was prepared in a previous commit to exercise the subtlety in prefix matching. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26backfill: accept revision argumentsDerrick Stolee
The existing implementation of 'git backfill' only includes downloading missing blobs reachable from HEAD. Advanced uses may desire more general commit limiting options, such as '--all' for all references, specifying a commit range via negative references, or specifying a recency of use such as with '--since=<date>'. All of these options are available if we use setup_revisions() to parse the unknown arguments with the revision machinery. This opens up a large number of possibilities, only a small set of which are tested here. For documentation, we avoid duplicating the option documentation and instead link to the documentation of 'git rev-list'. Note that these arguments currently allow specifying a pathspec, which modifies the commit history checks but does not limit the paths used in the backfill logic. This will be updated in a future change. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26t5620: prepare branched repo for revision testsDerrick Stolee
Prepare the test infrastructure for upcoming changes that teach 'git backfill' to accept revision arguments and pathspecs. Add test_tick before each commit in the setup loop so that commit dates are deterministic. This enables reliable testing with '--since'. Rename the 'd/e/' directory to 'd/f/' so that the prefix 'd/f' is ambiguous with the files 'd/file.*.txt'. This exercises the subtlety in prefix pathspec matching that will be added in a later commit. Create a branched version of the test repository (src-revs) with: - A 'side' branch merged into main, adding s/file.{1,2}.txt with two versions (4 new blobs, 52 total from main HEAD). - An unmerged 'other' branch adding o/file.{1,2}.txt (2 more blobs, 54 total reachable from --all). This structure makes --all, --first-parent, and --since produce meaningfully different results when used with 'git backfill'. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26revision: include object-name.hDerrick Stolee
The REV_INFO_INIT macro includes a use of the DEFAULT_ABBREV macro, which is defined in object-name.h. Include it in revision.h so consumers of REV_INFO_INIT do not need to include this hidden dependency. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26worktree: reject NULL worktree in get_worktree_git_dir()Phillip Wood
This removes the final dependence on "the_repository" in get_worktree_git_dir(). The last commit removed only caller that passed a NULL worktree. get_worktree_git_dir() has the following callers: - branch.c:prepare_checked_out_branches() which loops over all worktrees. - builtin/fsck.c:cmd_fsck() which loops over all worktrees. - builtin/receive-pack.c:update_worktree() which is called from update() only when "worktree" is non-NULL. - builtin/worktree.c:validate_no_submodules() which is called from check_clean_worktree() and move_worktree(), both of which supply a non-NULL worktree. - reachable.c:add_rebase_files() which loops over all worktrees. - revision.c:add_index_objects_to_pending() which loops over all worktrees. - worktree.c:is_current_worktree() which expects a non-NULL worktree. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26worktree add: stop reading ".git/HEAD"Phillip Wood
The function can_use_local_refs() prints a warning if there are no local branches and HEAD is invalid or points to an unborn branch. As part of the warning it prints the contents of ".git/HEAD". In a repository using the reftable backend HEAD is not stored in the filesystem so reading that file is pointless. In a repository using the files backend it is unclear how useful printing it is - it would be better to diagnose the problem for the user. For now, simplify the warning by not printing the file contents and adjust the relevant test case accordingly. Also fixup the test case to use test_grep so that anyone trying to debug a test failure in the future is not met by a wall of silence. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-26worktree: remove "the_repository" from is_current_worktree()Phillip Wood
The "is_current" member of struct worktree was added in 750e8a60d69 (worktree.c: mark current worktree, 2016-04-22) and was used in 8d9fdd7087d (worktree.c: check whether branch is rebased in another worktree, 2016-04-22) to optionally skip the current worktree when seeing if a branch is already checked out in die_if_checked_out(). To determine if a worktree is "current" is_current_worktree() compares the gitdir of the worktree to the gitdir of "the_repository" and returns true when they match. To get the gitdir of the worktree it calls get_workree_git_dir() which also depends on "the_repository". This means that even if "wt->path" matches "wt->repo->worktree" is_current_worktree(wt) will return false when "wt->repo" is not "the_repository". Consequently die_if_checked_out() will fail to skip such a worktree when checking if a branch is already checked out and may die errounously. Fix this by using the worktree's repository instance instead of "the_repository" when comparing gitdirs. The use of "the_repository" in is_current_wortree() comes from replacing get_git_dir() with repo_get_git_dir() in 246deeac951 (environment: make `get_git_dir()` accept a repository, 2024-09-12). In get_worktree_git_dir() it comes from replacing git_common_path() with repo_common_path() in 07242c2a5af (path: drop `git_common_path()` in favor of `repo_common_path()`, 2025-02-07). In both cases the replacements appear to have been mechanical. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-25regexp: leave a pointer to resurrect workaround for HomebrewJunio C Hamano
Recently some GitHub CI jobs were broken by update on the platform side, which was eventually resolved by image rollback, but in the meantime Dscho invented a workaround patch to sidestep the broken part of the platform. Their future image update may contain the same bug, in which case the workaround may again become needed. As we do not want to be building with workaround that avoids system regexp library altogether unless the system is known to be broken, so short of an automated "detect broken system and apply workaround" mechanism, let's use the folks who are compiling the code to detect breakage on their system and cope with the breakage ;-) Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-25Merge branch 'sa/replay-revert' into tc/replay-refJunio C Hamano
* sa/replay-revert: replay: add --revert mode to reverse commit changes sequencer: extract revert message formatting into shared function
2026-03-25replay: add --revert mode to reverse commit changesSiddharth Asthana
Add a `--revert <branch>` mode to git replay that undoes the changes introduced by the specified commits. Like --onto and --advance, --revert is a standalone mode: it takes a branch argument and updates that branch with the newly created revert commits. At GitLab, we need this in Gitaly for reverting commits directly on bare repositories without requiring a working tree checkout. The approach is the same as sequencer.c's do_pick_commit() -- cherry-pick and revert are just the same three-way merge with swapped arguments: - Cherry-pick: merge(ancestor=parent, ours=current, theirs=commit) - Revert: merge(ancestor=commit, ours=current, theirs=parent) We swap the base and pickme trees passed to merge_incore_nonrecursive() to reverse the diff direction. Reverts are processed newest-first (matching git revert behavior) to reduce conflicts by peeling off changes from the top. Each revert builds on the result of the previous one via the last_commit fallback in the main replay loop, rather than relying on the parent-mapping used for cherry-pick. Revert commit messages follow the usual git revert conventions: prefixed with "Revert" (or "Reapply" when reverting a revert), and including "This reverts commit <hash>.". The author is set to the current user rather than preserving the original author, matching git revert behavior. Helped-by: Christian Couder <christian.couder@gmail.com> Helped-by: Patrick Steinhardt <ps@pks.im> Helped-by: Elijah Newren <newren@gmail.com> Helped-by: Phillip Wood <phillip.wood123@gmail.com> Helped-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Helped-by: Junio C Hamano <gitster@pobox.com> Helped-by: Toon Claes <toon@iotcl.com> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-25sequencer: extract revert message formatting into shared functionSiddharth Asthana
The logic for formatting revert commit messages (handling "Revert" and "Reapply" cases, appending "This reverts commit <ref>.", and handling merge-parent references) currently lives inline in do_pick_commit(). The upcoming replay --revert mode needs to reuse this logic. Extract all of this into a new sequencer_format_revert_message() function. The function takes a repository, the subject line, commit, parent, a use_commit_reference flag, and the output strbuf. It handles both regular reverts ("Revert "<subject>"") and revert-of-revert cases ("Reapply "<subject>""), and uses refer_to_commit() internally to format the commit reference. Update refer_to_commit() to take a struct repository parameter instead of relying on the_repository, and a bool instead of reading from replay_opts directly. This makes it usable from the new shared function without pulling in sequencer-specific state. Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>