summaryrefslogtreecommitdiff
path: root/builtin
AgeCommit message (Collapse)AuthorFilesLines
6 daysMerge branch 'jc/history-missing-tree-errorfix' into nextJunio C Hamano1-0/+4
Running "git history" in a corrupt repository can (unsurprisingly) segfault when a necessary tree object is not found. * jc/history-missing-tree-errorfix: history: do not dereference NULL when parent tree is missing
8 daysMerge branch 'sa/rev-list-missing-only' into nextJunio C Hamano1-5/+37
The git rev-list command has been augmented with a '--missing-only' option that filters the output to only show missing objects, stripping the leading '?' character and suppressing present objects, which is useful when used in combination with '--missing=print' or '--missing=print-info'. * sa/rev-list-missing-only: rev-list: add --missing-only option to filter output
8 daysMerge branch 'ps/tune-rerere-gc' into nextJunio C Hamano1-22/+6
"git maintenance" triggered "rerere gc" in unappropriate times and interfered with "git rebase" etc. too much. The conditions "rerere gc" gets triggered have been tweaked. * ps/tune-rerere-gc: builtin/maintenance: improve heuristic for "rerere gc" rerere: extract logic to determine whether entries are stale
8 daysMerge branch 'hn/checkout-m-autostash-refine' into nextJunio C Hamano2-15/+33
The autostash fallback in 'git checkout -m' has been refined to only retry when there are local changes. Additionally, a blank line now visually separates autostash conflict advice from the subsequent branch-switch message. * hn/checkout-m-autostash-refine: checkout: separate autostash conflict advice from branch-switch message stash: reserve exit status 1 for conflicts
9 daysMerge branch 'jk/submodule-error-leak' into nextJunio C Hamano1-3/+7
The error path in 'git submodule--helper' has been updated to plug a memory leak when a repository handle could not be obtained, leveraging an updated idempotent repo_clear(). * jk/submodule-error-leak: submodule--helper: free URL when repository setup fails repository: make repo_clear() idempotent
9 daysMerge branch 'en/no-amend-during-conflicts' into nextJunio C Hamano1-19/+46
Teach 'am', 'revert', and 'rebase' that running 'commit --amend' or a partial 'commit <paths>' makes no sense during operations that stop and return control to the user to resolve conflicts left in the working tree, just like 'cherry-pick' and 'merge' do. * en/no-amend-during-conflicts: commit: refuse partial commits during conflict resolution commit: refuse to amend during conflict resolution commit: reword the empty-commit rebase amend error commit: allow a partial commit when a rebase pick becomes empty commit: clarify FROM_REBASE_PICK and is_from_rebase() names
12 daysMerge branch 'en/midx-missing-pack-fallback' into nextJunio C Hamano2-2/+4
The object lookup machinery has been taught to gracefully recover when a multi-pack-index points to an owning pack that was removed during a concurrent geometric repack, and 'git replay' has been fixed to not segfault when reading such missing objects. * en/midx-missing-pack-fallback: packfile: recover when a multi-pack-index names a removed pack mktree: do not use OBJECT_INFO_QUICK when checking objects mktree: plug per-tree leak in --batch mode replay: fail gracefully when a merge input is unreadable
12 daysMerge branch 'tc/replay-linearize' into nextJunio C Hamano1-1/+5
The 'git replay' command has been taught the '--linearize' option to drop merge commits and linearize the replayed history, mimicking 'git rebase --no-rebase-merges'. * tc/replay-linearize: replay: offer an option to linearize the commit topology replay: resolve the replay base outside pick_regular_commit() replay: add helper to put entry into replayed_commits
12 daysbuiltin/maintenance: improve heuristic for "rerere gc"Patrick Steinhardt1-22/+6
The "rerere-gc" maintenance task is responsible for pruning rerere entries older than a certain configurable cutoff point. Whether or not the task gets run during auto-maintenance can be configured via "maintenance.rerere-gc.auto": - A negative value indicates that maintenance should always run. - A zero value indicates that maintenance should never run. - Otherwise, a positive value indicates that maintenance should always run in case we have at least a single rerere entry. While the first two conditions are sensible, the last one is less so as it does not account for whether we would even prune old entries in the first place. Instead, it effectively implies that we unconditionally spawn "git rerere gc" when rerere is enabled. Chances are high though that there is nothing to prune, as the default cutoff dates are 60 days for resolved rerere entries and 15 days for unresolved ones. Besides being a waste of compute, it also obstructs concurrent processes that want to write new resolutions as garbage collection takes a central lock file, as reported in [1]. That race is a longstanding one that existed even before we introduced fine-grained maintenance tasks, and the proper fix is to use a locking timeout in the writing processes. But the race is made worse by us performing garbage collection a lot more often. Refine the heuristic to take into account whether any entries can be pruned in the first place. This ensures that we'll only ever run this task in situations where it will do anything, and should thus result in a lot less frequent invocations of "git rerere gc". Furthermore, tweak the meaning of "maintenance.rerere-gc.auto" so that positive values allow the user to configure the number of prunable entries that need to exist before we run it and set the default value to 512. This number is pulled out of thin air, but it ensures that we know to batch-delete entries instead of pruning every single entry that is older than the cutoff point. Note that this now requires us to actually open the rerere-entry directories and stat the individual files in there, which does add a bit of overhead when one has lots of rerere entries. To counteract this overhead, we thus use the same sampling heuristic as we do for loose objects, where we only consider those entries that start with a "17". [1]: <pull.2214.git.1788337897490.gitgitgadget@gmail.com> Reported-by: Thomas Bachem <mail@thomasbachem.com> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 daysMerge branch 'rs/worktree-add-basename-fixes' into nextJunio C Hamano1-19/+14
The string extraction logic for the branch name and worktree name from the given path in 'git worktree add' has been corrected and simplified to avoid out-of-bounds reads and improper handling of trailing slashes. * rs/worktree-add-basename-fixes: worktree add: let worktree_basename() return string copy worktree add: trim slashes when deriving branch name from path worktree add: reject separator-only path worktree add: don't read out of bounds in worktree_basename()
12 daysrev-list: add --missing-only option to filter outputSiddharth Asthana1-5/+37
When working with partial clones, callers often need only the missing object IDs. Today that means post-processing --missing=print to drop present objects and strip the leading '?': git rev-list --objects --all --missing=print | perl -ne 'print if s/^[?]//' This is for a one-shot walk, not a fetch loop. Callers already have --missing=print and strip the leading '?'. Gitaly does that when packing a quarantine: '?' lines are objects that must already exist in the main repo. Tests do the same (is this blob still missing). --missing-only is just that list without the prefix. Add --missing-only. Use it with --missing=print or --missing=print-info to print only missing objects. --missing= still picks the format; --missing-only only filters. The leading '?' is omitted. With print-info, path= and type= are still shown. Require --missing=print or --missing=print-info. Reject --count and --disk-usage. Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 dayscheckout: separate autostash conflict advice from branch-switch messageHarald Nordgren1-6/+9
"git checkout -m" stashes the user's local changes when it cannot perform the checkout, and then applies the stash. When applying the stash results in conflicts, the advice on how to deal with them is printed directly on top of the branch-switch message ("Switched to branch ..."), making the two hard to tell apart. Print a blank line in between so that the advice and the branch-switch message are visually distinct. apply_autostash_ref() reports whether applying the stash resulted in conflicts via its enum stash_apply_result return value, so only print the blank line in the conflicted case. Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 daysstash: reserve exit status 1 for conflictsHarald Nordgren1-9/+24
"git stash apply", "pop" and "branch" exit with status 1 both when applying the stash entry resulted in conflicts and when they fail for other reasons, so callers cannot tell the two apart. Follow the convention of "git merge-tree" and the merge strategies, which exit with status 1 to indicate conflicts and with a different non-zero status for errors: those subcommands now exit with status 1 only when applying the stash entry resulted in conflicts, in which case the stash entry is left in place, and exit with status 128, the status die() uses, when they fail for other reasons. Document the exit statuses. The only subcommand implementations that can return a positive value are "apply", "pop" and "branch", which return the value of do_apply_stash(): "apply" returns it directly, and "pop" and "branch" drop the stash entry, via do_drop_stash(), which always returns 0, only when the application succeeded. do_apply_stash() only returns a positive value when the three-way merge was unclean. cmd_stash() now maps negative values to 128 and passes positive values through as the exit status, so exit status 1 unambiguously indicates conflicts. enum stash_apply_result makes the convention explicit, and the autostash helpers use it to tell users that their stashed changes were saved when applying them fails. Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 dayshistory: do not dereference NULL when parent tree is missingJinbao Chen1-0/+4
write_ondisk_index() dereferences the return value of repo_parse_tree_indirect() unconditionally. If the parent commit's tree object is missing from the object store (corrupt repository, object removed by tooling, or incomplete restore), the function returns NULL and "git history split" crashes with a SIGSEGV. Guard the parse result and error out gracefully, following the codebase convention for objects that cannot be loaded. Signed-off-by: Jinbao Chen <zkd18cjb@mail.ustc.edu.cn> Acked-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
14 daysMerge branch 'ty/repository-fetch-if-missing'Junio C Hamano6-33/+38
The global variable 'fetch_if_missing' has been moved to a member in 'struct repository', continuing the libification process and allowing per-repository control (such as for submodules). * ty/repository-fetch-if-missing: repository: move fetch_if_missing into struct repository
14 dayssubmodule--helper: free URL when repository setup failsJeff King1-3/+7
If repo setup fails, we'll return an error without freeing the allocated url string, leaking the memory. The test suite does trigger this error, but never with the leak. We only allocate a url if submodule_from_path() returned something, but our tests use other situations, like totally nonexistent submodules. We can cover this case by asking about a submodule that exists but which has not been initialized. The new test fails with SANITIZE=leak. The smallest fix would just be a call to free(url), but I think it's a little nicer to set up a dedicated out-path for cleanup here. The previous commit made it safe to call repo_clear() even if repo_submodule_init() fails. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-01commit: refuse partial commits during conflict resolutionElijah Newren1-5/+19
Similar to the previous commit, just as `git commit --amend` is a foot-gun during conflict resolution, so is a partial commit (`git commit <paths>`). Recording a conflict resolution is about capturing the state of the entire tree on top of HEAD, not a subset of paths. For many years we have rejected partial commits in the middle of - a merge - a cherry-pick but, just like amending, this was never extended to the other operations that can also leave conflicts to resolve: - an `am` operation - a revert - a rebase that stopped for conflict resolution Reuse sequencer_ongoing_operation(), introduced for the analogous `--amend` check, to detect these and refuse the partial commit. A rebase that stopped because a pick became empty is not conflict resolution and, as an earlier patch established, is deliberately left permitted. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-01commit: refuse to amend during conflict resolutionElijah Newren1-6/+21
Running `git commit --amend` during conflict resolution is an ugly foot-gun. For many years, we have rejected amending during conflict resolution in the middle of - a merge - a cherry-pick However, this was never extended to other operations that can also produce conflicts: - an `am` operation - a revert - a rebase Extend it to handle these other cases now. Extending to `am`, revert, and the apply backend of rebase are fairly straightforward. However, with the merge backend of rebase we have to be more careful, since it powers interactive rebases and - the interactive machinery internally uses `git commit --amend` for `squash` and `reword` directives - users are expected to `git commit --amend` after hitting an `edit` or `break` directive So, we need to be careful with rebase to only reject amending when doing conflict resolution. A few files under the rebase-merge/ directory provide us the necessary information: - stopped-sha is written only when the rebase stops and hands control back to the user, so its presence marks a genuine stop -- as opposed to the sequencer's own internal `git commit --amend` while applying a squash, fixup, or reword, during which no stopped-sha exists. - amend is written only when the rebase stops with HEAD already pointing at the commit the user is meant to amend: a clean `edit`, or a fast-forward `reword`. Its absence at a stop therefore means the commit did not apply, so HEAD is the previously-applied commit rather than the one being rebased -- exactly the case we refuse. So for the merge backend we die when stopped-sha exists and amend does not. This covers a plain conflicted pick as well as a conflicted `edit` (both leave HEAD on the previously-applied commit), while still allowing a clean `edit` or `reword` stop and a `break` stop (no stopped-sha). stopped-sha is unlinked at the start of the resume loop, so a resumed squash's internal amend is unaffected. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-01commit: reword the empty-commit rebase amend errorElijah Newren1-1/+1
When a rebase applies a commit that becomes empty, it stops and asks the user to decide whether to keep it or drop it. HEAD still points at the previously-applied commit at that point, so amending is refused, with: You are in the middle of a rebase -- cannot amend. That message would suggest that amending is not allowed during an 'edit' or 'break' stop, which is misleading, plus it lacks the specificity that might help the user know why their particular case is a problem: the commit they intended to amend became empty and was dropped, so amending would affect the wrong commit. Reword the error accordingly. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-01commit: allow a partial commit when a rebase pick becomes emptyElijah Newren1-2/+0
For years, we disallowed partial commits during merges or cherry-picks. In commit 430b75f7209c (commit: give correct advice for empty commit during a rebase, 2019-12-06) it was noted that the "cannot do a partial commit during a cherry-pick" message was also printed when rebasing a commit that became empty, and rather than drop the check in that case, that commit opted to make the message print the actual operation that was in progress. Since a commit that has become empty comes without conflicts, a new partial commit poses no problems; remove the error in that case. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-01commit: clarify FROM_REBASE_PICK and is_from_rebase() namesElijah Newren1-7/+7
Commit 430b75f7209c (commit: give correct advice for empty commit during a rebase, 2019-12-06) introduced a FROM_REBASE_PICK enum value and an is_from_rebase() function. Those names failed to convey that they were specifically about hitting a commit that becomes empty when rebasing. Clarify their names now. While at it, change `whence == FROM_REBASE_NOW_EMPTY` to use `is_from_rebase_now_empty(whence)`. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-31replay: offer an option to linearize the commit topologyToon Claes1-1/+5
One of the stated goals of git-replay(1) is to allow implementing the git-rebase(1) functionality on the server side. The default mode of git-rebase(1) is to act as if `--no-rebase-merges` was given. This mode drops merge commits instead of replaying them, and linearizes the history into a sequence of regular (single-parent) commits. Add option `--linearize` to git-replay(1) to do the same. Each replayed commit is stacked on top of the previously replayed one. When a merge is encountered, the commits reachable from all of its sides are replayed into the single line and the merge itself is dropped. If a ref was pointing to a merge commit, that ref is updated to the merge's last replayed ancestor. git-replay(1) accepts multiple branches, for example: $ git replay --onto main topic1 topic2 Without `--linearize` this replays 'topic1' and 'topic2' onto 'main' (keeping shared portions of history shared and divergent parts divergent) and updates both refs. Due to current implementation limitations, replaying multiple branches with `--linearize` is disallowed to avoid concatenating unrelated histories into a single line. For the same reason disallow the use of `--contained` with `--linearize`. Users who want to linearize multiple branches are advised to do this in separate git-replay(1) invocations. Linearizing multiple branches at once might be added later. Note that `--linearize` is not modeled after git-rebase(1)'s `--rebase-merges[=<mode>]` interface. Recreating merges, by preserving their topology, is a distinct operation that would be a separate mode. `--linearize` only drops merges and replays commits linearly. So git-replay(1) uses its own option rather than reusing that interface. Based-on-patches-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Toon Claes <toon@iotcl.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-31Merge branch 'gr/add-e-use-apply-api' into nextJunio C Hamano1-7/+12
The application of the edited patch in 'git add -e' has been refactored to use the internal apply API directly, avoiding the need to spawn a 'git apply' subprocess. * gr/add-e-use-apply-api: builtin/add.c: replace run_command() with direct apply_all_patches() call
2026-08-31Merge branch 'fr/pack-objects-trace-pack-bytes'Junio C Hamano1-0/+5
The pack-objects command has been updated to record the total bytes written to pack files in trace2 output, allowing performance analysis of different compression settings by comparing the resulting pack sizes. * fr/pack-objects-trace-pack-bytes: pack-objects: trace pack bytes written
2026-08-31Merge branch 'ps/odb-pluggable-pack-generation'Junio C Hamano1-21/+13
The mechanism to generate a packfile corresponding to the result of a fetch/push has been made pluggable through a set of object database callback functions, removing hardcoded references to 'pack-objects' and enabling alternative ODBs to serve packfiles themselves. * ps/odb-pluggable-pack-generation: bundle: generate packfiles via the object database bundle: get (mostly) rid of `the_repository` builtin/bundle: refactor option handling for progress meter send-pack: generate packfiles via the object database upload-pack: generate packfiles via the object database odb: introduce interface to generate packfiles
2026-08-31Merge branch 'jt/receive-pack-pluggable-writes'Junio C Hamano4-170/+51
The 'git receive-pack' command has been updated to use a new ODB transaction interface for writing incoming packfiles, making it more backend-agnostic. * jt/receive-pack-pluggable-writes: odb/transaction: add transaction interface to write packfiles odb: return temporary ODB source when set builtin/receive-pack: explicitly pass packfile fd builtin/receive-pack: report unpack errors via strbuf builtin/receive-pack: lift global state out of unpack() builtin/receive-pack: read unpack limit config lazily builtin/receive-pack: pass shallow file explicitly odb/transaction: add transaction finalize interface builtin/receive-pack: properly clean up keep files
2026-08-31Merge branch 'ps/odb-eagerly-load-alternates'Junio C Hamano2-6/+0
The object database layer has been simplified by eagerly loading alternate object directories upon initialization, instead of deferring it to the first object lookup. This eliminates the need for scattered lazy-loading calls throughout the codebase and paves the way for integrating alternates with the pluggable backends. * ps/odb-eagerly-load-alternates: odb: drop `alternates_db` field odb: drop `loaded_alternates` field odb: eagerly initialize alternates odb: decouple source path comparisons from `the_repository` setup: create ref and object databases after config is written
2026-08-31Merge branch 'ps/odb-generic-corrupt-objects'Junio C Hamano1-4/+4
The object database (odb) API has been refactored to distinguish between missing objects and corrupt ones by returning more descriptive error statuses. Both the packed and loose backends now faithfully propagate error details using a generic strbuf error mechanism, removing backend-specific leakage from central lookup paths. * ps/odb-generic-corrupt-objects: odb: handle `OBJECT_INFO_DIE_IF_CORRUPT` generically odb/source: allow `read_object_info()` to bubble up error messages odb/source: let callers discern missing and corrupt objects odb/source: introduce error status when reading objects odb/source-packed: flag known-bad objects as corrupt and not missing
2026-08-31Merge branch 'yn/worktree-add-no-dwim-with-b'Junio C Hamano1-0/+3
The DWIM logic in 'git worktree add' sometimes tried to infer a remote-tracking branch when an explicit '-b' or '-B' option was given to create a new branch, causing the explicit branch name to be ignored, which has been corrected. * yn/worktree-add-no-dwim-with-b: worktree add: shouldn't dwim if -b or -B is given
2026-08-30Merge branch 'yn/worktree-ambiguous-remote-advice' into nextJunio C Hamano2-36/+97
'git worktree add' did not prevent DWIM behavior when '-b' or '-B' was specified, which has been corrected. * yn/worktree-ambiguous-remote-advice: worktree add: treat multiple matches with --guess-remote as an error worktree add: improve message for ambiguous remote branch name checkout: improve message for ambiguous remote branch name checkout: extract function to display advice for ambiguous remotes
2026-08-30packfile: recover when a multi-pack-index names a removed packElijah Newren1-1/+1
A geometric repack writes a new pack and multi-pack-index and then deletes the packs the new one subsumes. A process still using the previous MIDX keeps seeing a removed pack listed as the owner of some objects. Since a MIDX attributes each object to exactly one pack, such an object is served only through its recorded owner; if that owner was just removed, find_pack_entry() cannot serve it -- the MIDX lookup routes to the missing pack, and the regular pack fallback deliberately skips every MIDX-covered pack, so a surviving copy in another covered pack (e.g. a kept base pack) is never consulted. Unlike the ordinary "a pack's .idx is mapped but its .pack is gone" race, the second read does not rescue us. Reloading the on-disk pack set does not reload the borrowed, cached MIDX (freeing it under the code that caches the "struct multi_pack_index *" would be a use-after-free), so the stale MIDX keeps routing to the removed pack and the surviving copy stays hidden behind the covered-pack skip. cat-file, rev-list and pack-objects can thus all spuriously fail with "unable to read object". Teach find_pack_entry() to recover. The MIDX lookup now returns a tri-state, distinguishing an object absent from the MIDX from one it owns via a pack that can no longer be opened; in the latter case, once the regular fallback has also missed, scan the MIDX's packs directly for a surviving copy. Because the return value is no longer a boolean, rename fill_midx_entry() to midx_fill_entry() so callers must reckon with the new enum rather than silently treat MIDX_FILL_OWNER_UNAVAILABLE as a hit. Do the scan only on the second read (OBJECT_INFO_SECOND_READ): by then the cheaper on-disk reload has run, so an object merely relocated into a new (uncovered) pack has already been found by the regular fallback, and only a genuine hidden duplicate reaches the rescan. A QUICK caller that skips the second read simply accepts the false negative, as QUICK is designed to. Reloading the stale MIDX would be a more complete fix but is much more involved (the borrowers above need proper invalidation), so leave that for later. Assisted-by: Claude Opus 4.8 & GPT-5.6 Sol Helped-by: Jeff King <peff@peff.net> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-30mktree: do not use OBJECT_INFO_QUICK when checking objectsElijah Newren1-1/+0
mktree_line() checks each referenced object's type with odb_read_object_info_extended() under OBJECT_INFO_QUICK. QUICK skips the reprepare-and-retry that reloads the on-disk pack set, so a resident "git mktree --batch" reader reports an object that a concurrent repack just relocated into a new pack as missing, and rejects the entry. QUICK entered this lookup in 817b0f602710 (mktree: do not check type of remote objects, 2022-06-21) only to avoid lazily fetching promisor objects; OBJECT_INFO_SKIP_FETCH_OBJECT already provides that. Drop OBJECT_INFO_QUICK and keep OBJECT_INFO_SKIP_FETCH_OBJECT, so mktree still avoids a promisor fetch but recovers an object that was merely repacked. Add a regression test driving a resident mktree --batch reader across a concurrent repack that retires a pack. Assisted-by: Claude Opus 4.8 & GPT-5.6 Sol Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-30mktree: plug per-tree leak in --batch modeElijah Newren1-0/+3
In --batch mode "git mktree" reuses its entry buffer across trees, resetting `used` to 0 after writing each tree. It never frees the `treeent` structures the previous tree appended, though, so once the next tree overwrites those slots the earlier allocations are leaked. A single-tree invocation hides this, as the entries stay reachable through the `entries` global until exit. Free each entry when resetting the buffer, and free the buffer itself before returning. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-27worktree add: treat multiple matches with --guess-remote as an errorYoichi NAKAYAMA1-3/+17
When 'git worktree add <path>' is invoked without <commit-ish> and with the --guess-remote option (or when worktree.guessRemote is set to true), it tries to find a remote-tracking branch matching the basename of <path>. Currently, the behavior when multiple matches are found is the same as when no match is found: it falls back to creating a branch from HEAD. This has been the behavior since 71d6682d8c (worktree: add --guess-remote option to add subcommand, 2017-11-29), when the option was first introduced. However, if the specified <path> matches any remote-tracking branch, we infer that the user intended to use one of the remote-tracking branches as the start-point rather than HEAD. So we abort the creation of the branch and worktree when there are multiple matches, and instruct the user to choose the start-point. Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-27worktree add: improve message for ambiguous remote branch nameYoichi NAKAYAMA1-3/+34
When the user runs 'git worktree add ../foo-dir bar-topic' without specifying a remote, and there is no local branch named bar-topic, we try to guess which remote branch bar-topic refers to, then create a new branch named bar-topic that tracks the remote branch. If multiple remotes have a branch named bar-topic, we silently gave up, leaving the variable 'branch' intact. We then entered the conditional clause 'if (!opts.orphan && !lookup_commit_reference_by_name(branch))' and triggered an "invalid reference" error. This error message did not provide enough information to resolve the ambiguity. When multiple matching branches are found, display a hint and a descriptive error message and die immediately. Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-27checkout: improve message for ambiguous remote branch nameYoichi NAKAYAMA2-10/+22
When the user runs 'git checkout bar-topic' without specifying a remote, and there is no local branch named bar-topic, we try to guess which remote branch bar-topic refers to, then create a new branch named bar-topic that tracks the remote branch. If multiple remotes have a branch named bar-topic, we cannot determine a single remote. To make it easier to resolve the ambiguity, provide the names of the matching remotes for the specified branch name. To achieve that, add an optional feature to the `unique_tracking_name()` function that allows the matching remote names to be exposed to the caller. Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-27checkout: extract function to display advice for ambiguous remotesYoichi NAKAYAMA1-28/+32
Fix incorrect indentation and reduce nesting. We are going to extend this function in subsequent commits. Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-26worktree add: let worktree_basename() return string copyRené Scharfe1-15/+10
worktree_basename() requires callers to do pointer arithmetic to get the actual basename. Simplify them by doing the calculations in the function and returning a copy of the basename directly. Remind programmers to free the result by renaming the function to worktree_basename_dup(). Among the three callers of the original function, two immediately make copies of the returned string before using and freeing it, which makes for an easy conversion. Convert the other one from resetting a shared strbuf to freeing the allocated string, which requires the same number of lines, but no arithmetic. The added allocation is negligible because it's small and there's only one per run of "git worktree add". Signed-off-by: René Scharfe <l.s.r@web.de> [jc: rephrased the second paragraph a bit.] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-25Merge branch 'ty/repository-fetch-if-missing' into nextJunio C Hamano6-33/+38
The global variable 'fetch_if_missing' has been moved to a member in 'struct repository', continuing the libification process and allowing per-repository control (such as for submodules). * ty/repository-fetch-if-missing: repository: move fetch_if_missing into struct repository
2026-08-25worktree add: trim slashes when deriving branch name from pathRené Scharfe1-2/+2
worktree_basename() sets `n` to the length of `path` without trailing path separators, not to the length of the basename. This matters when deriving a branch name from a path with more than one component. E.g.: path: /new/worktree/ s: ^ n: |-----------| So here xstrndup(s, n) copies up to 13 characters from "worktree/", effectively to the end of the string, including the trailing dash. Path separators are not allowed at the end of branch names, so strip them off by calculating the basename length and extracting just that part. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-25worktree add: reject separator-only pathRené Scharfe1-0/+2
worktree_basename() extracts an empty basename from a path consisting only of zero or more path separators. We can't use that as a worktree name. Properly report such a path as invalid instead of triggering a BUG that asks the user what just happened. Original-patch-by: Matthias Aßhauer <mha1993@live.de> Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-25worktree add: don't read out of bounds in worktree_basename()René Scharfe1-5/+3
When we search for the start of the basename and `len` is zero, `name` ends up being `path` - 1, out of bounds. Avoid that by checking before decrementing. Fixes https://github.com/git-for-windows/git/issues/6346. Original-patch-by: Matthias Aßhauer <mha1993@live.de> Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-25Merge branch 'ss/repack-drop-filtered'Junio C Hamano1-5/+149
'git repack' has been taught '--drop-filtered' to delete local promisor blobs exceeding a limit (currently 'blob:limit=') in partial clones, reclaiming space. Guards prevent running during other operations or if referenced by the index. * ss/repack-drop-filtered: builtin/repack: add guards for --drop-filtered builtin/repack: actually drop filtered promisor blobs builtin/repack: enumerate promisor blobs for --drop-filtered repack-promisor: allow excluding objects from the rebuilt promisor pack list-objects-filter: add list_objects_filter__filter_oidset() builtin/repack: add --drop-filtered and --dry-run options
2026-08-24Merge branch 'fr/pack-objects-trace-pack-bytes' into nextJunio C Hamano1-0/+5
The pack-objects command has been updated to record the total bytes written to pack files in trace2 output, allowing performance analysis of different compression settings by comparing the resulting pack sizes. * fr/pack-objects-trace-pack-bytes: pack-objects: trace pack bytes written
2026-08-24Merge branch 'ps/odb-pluggable-pack-generation' into nextJunio C Hamano1-21/+13
The mechanism to generate a packfile corresponding to the result of a fetch/push has been made pluggable through a set of object database callback functions, removing hardcoded references to 'pack-objects' and enabling alternative ODBs to serve packfiles themselves. * ps/odb-pluggable-pack-generation: bundle: generate packfiles via the object database bundle: get (mostly) rid of `the_repository` builtin/bundle: refactor option handling for progress meter send-pack: generate packfiles via the object database upload-pack: generate packfiles via the object database odb: introduce interface to generate packfiles
2026-08-24Merge branch 'jt/receive-pack-pluggable-writes' into nextJunio C Hamano4-170/+51
The 'git receive-pack' command has been updated to use a new ODB transaction interface for writing incoming packfiles, making it more backend-agnostic. * jt/receive-pack-pluggable-writes: odb/transaction: add transaction interface to write packfiles odb: return temporary ODB source when set builtin/receive-pack: explicitly pass packfile fd builtin/receive-pack: report unpack errors via strbuf builtin/receive-pack: lift global state out of unpack() builtin/receive-pack: read unpack limit config lazily builtin/receive-pack: pass shallow file explicitly odb/transaction: add transaction finalize interface builtin/receive-pack: properly clean up keep files
2026-08-24Merge branch 'ps/odb-eagerly-load-alternates' into nextJunio C Hamano2-6/+0
The object database layer has been simplified by eagerly loading alternate object directories upon initialization, instead of deferring it to the first object lookup. This eliminates the need for scattered lazy-loading calls throughout the codebase and paves the way for integrating alternates with the pluggable backends. * ps/odb-eagerly-load-alternates: odb: drop `alternates_db` field odb: drop `loaded_alternates` field odb: eagerly initialize alternates odb: decouple source path comparisons from `the_repository` setup: create ref and object databases after config is written
2026-08-24Merge branch 'js/pack-objects-delta-size-t'Junio C Hamano2-18/+20
The 'pack-objects' and delta-encoding code paths have been updated to use 'size_t' instead of 'unsigned long' for object sizes and offset limits, avoiding potential truncation issues on 64-bit Windows. * js/pack-objects-delta-size-t: packfile: widen `unpack_object_header_buffer()` to `size_t` git-zlib: widen `git_deflate_bound()` to `size_t` t/helper/test-pack-deltas: widen `do_compress()`'s maxsize local to `size_t` http-push: widen `start_put()`'s size local from `ssize_t` to `size_t` diff: widen `deflate_it()`'s bound local from int to `size_t` archive-zip: widen `zlib_deflate_raw()`'s maxsize local to `size_t` packfile, git-zlib: widen `use_pack()` and zstream avail fields to `size_t` delta: widen `create_delta()` and `diff_delta()` to `size_t` pack-objects: widen `mem_usage` and `try_delta()`'s out-param to `size_t` pack-objects: widen `free_unpacked()` return to `size_t` pack-objects: widen delta-cache accounting to `size_t` delta: widen `create_delta_index()` parameter to `size_t` diff-delta: widen `struct delta_index`' size fields to `size_t`
2026-08-24Merge branch 'js/coverity-unchecked-returns-fix'Junio C Hamano3-16/+42
A handful of code paths have been corrected to check return values from functions like curl_easy_duphandle(), deflateInit(), lseek(), dup(), and strbuf_getline_lf(), resolving several Coverity warnings about unchecked returns. * js/coverity-unchecked-returns-fix: bisect: handle dup() failure when redirecting stdout bisect: check get_terms return at all call sites bisect: check strbuf_getline_lf return when reading terms transport-helper: warn when export-marks file cannot be finalized transport-helper: check dup() return in get_exporter compat/pread: check initial lseek for errors last-modified: handle repo_parse_commit() failures reftable tests: check reftable_table_init_ref_iterator() return reftable/block: check deflateInit() return value reftable: handle block-writer initialization errors config: propagate launch_editor() failure in show_editor() http: die on curl_easy_duphandle failure in get_active_slot
2026-08-23Merge branch 'ps/odb-generic-corrupt-objects' into nextJunio C Hamano1-4/+4
The object database (odb) API has been refactored to distinguish between missing objects and corrupt ones by returning more descriptive error statuses. Both the packed and loose backends now faithfully propagate error details using a generic strbuf error mechanism, removing backend-specific leakage from central lookup paths. * ps/odb-generic-corrupt-objects: odb: handle `OBJECT_INFO_DIE_IF_CORRUPT` generically odb/source: allow `read_object_info()` to bubble up error messages odb/source: let callers discern missing and corrupt objects odb/source: introduce error status when reading objects odb/source-packed: flag known-bad objects as corrupt and not missing