summaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorFilesLines
2025-03-21reftable: adapt write_object_record() to propagate block_writer_add() errorsMeet Soni1-0/+19
Previously, write_object_record() would flush the current block and retry appending the record whenever block_writer_add() returned any nonzero error. This forced an assumption that every failure meant the block was full, even when errors such as memory allocation or I/O failures occurred. Update the write_object_record() to inspect the error code returned by block_writer_add() and flush and reinitialize the writer iff the error is REFTABLE_ENTRY_TOO_BIG_ERROR. For any other error, immediately propagate it. If the flush and reinitialization still fail with REFTABLE_ENTRY_TOO_BIG_ERROR, reset the record's offset length to zero before a final attempt. All call sites now handle various error codes returned by block_writer_add(). Signed-off-by: Meet Soni <meetsoni3017@gmail.com> Acked-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-21reftable: adapt writer_add_record() to propagate block_writer_add() errorsMeet Soni1-10/+5
Previously, writer_add_record() would flush the current block and retry appending the record whenever block_writer_add() returned any nonzero error. This forced an assumption that every failure meant the block was full, even when errors such as memory allocation or I/O failures occurred. Update the writer_add_record() to inspect the error code returned by block_writer_add() and only flush and reinitialize the writer when the error is REFTABLE_ENTRY_TOO_BIG_ERROR. For any other error, immediately propagate it. Signed-off-by: Meet Soni <meetsoni3017@gmail.com> Acked-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-21reftable: propagate specific error codes in block_writer_add()Meet Soni3-36/+32
Previously, functions block_writer_add() and related functions returned -1 when the record did not fit, forcing the caller to assume that any failure meant the entry was too big. Replace these generic -1 returns with defined error codes. This prepares the codebase for finer-grained error handling so that callers can distinguish between a block-full condition and other errors. Signed-off-by: Meet Soni <meetsoni3017@gmail.com> Acked-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-21pseudo-merge.h: fix a typoTaylor Blau1-1/+1
The comment added in 7252d9a036 (pseudo-merge: implement support for finding existing merges, 2024-05-23) misspells 'bitmap' as 'bitamp'. Correct that so that we no longer have any stray "bitamps" lurking throughout the tree: $ git grep -ci bitamp | wc -l 0 Noticed-by: Jeff King <peff@peff.net> Signed-off-by: Taylor Blau <me@ttaylorr.com> Acked-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-21refspec: replace `refspec_item_init()` with fetch/push variantsTaylor Blau4-7/+23
For similar reasons as in the previous refactoring of `refspec_init()` into `refspec_init_fetch()` and `refspec_init_push()`, apply the same refactoring to `refspec_item_init()`. Signed-off-by: Taylor Blau <me@ttaylorr.com> Acked-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-21refspec: remove refspec_item_init_or_die()Taylor Blau3-11/+4
There are two callers of this function, which ensures that a dispatched call to refspec_item_init() does not fail. In the following commit, we're going to add fetch/push-specific variants of refspec_item_init(), which will turn one function into two. To avoid introducing yet another pair of new functions (such as refspec_item_init_push_or_die() and refspec_item_init_fetch_or_die()), let's remove the thin wrapper entirely. This duplicates a single line of code among two callers, but thins the refspec.h API by one function, and prevents introducing two more in the following commit. Note that we still have a trailing Boolean argument in the function `refspec_item_init()`. The following commit will address this. Signed-off-by: Taylor Blau <me@ttaylorr.com> Acked-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-21refspec: replace `refspec_init()` with fetch/push variantsTaylor Blau4-7/+14
To avoid having a Boolean argument in the refspec_init() function, replace it with two variants: - `refspec_init_fetch()` - `refspec_init_push()` to codify the meaning of that Boolean into the function's name itself. Signed-off-by: Taylor Blau <me@ttaylorr.com> Acked-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-21refspec: treat 'fetch' as a Boolean valueTaylor Blau5-12/+9
Since 6d4c057859 (refspec: introduce struct refspec, 2018-05-16), we have macros called REFSPEC_FETCH and REFSPEC_PUSH. This confusingly suggests that we might introduce other modes in the future, which, while possible, is highly unlikely. But these values are treated as a Boolean, and stored in a struct field called 'fetch'. So the following: if (refspec->fetch == REFSPEC_FETCH) { ... } , and if (refspec->fetch) { ... } are equivalent. Let's avoid renaming the Boolean values "true" and "false" here and remove the two REFSPEC_ macros mentioned above. Since this value is truly a Boolean and will only ever take on a value of 0 or 1, we can declare it as a single bit unsigned field. In practice this won't shrink the size of 'struct refspec', but it more clearly indicates the intent. Note that this introduces some awkwardness like: refspec_item_init_or_die(&spec, refspec, 1); , where it's unclear what the final "1" does. This will be addressed in the following commits. Signed-off-by: Taylor Blau <me@ttaylorr.com> Acked-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-21Merge branch 'jk/fetch-ref-prefix-cleanup' into tb/refspec-fetch-cleanupJunio C Hamano4-39/+85
* jk/fetch-ref-prefix-cleanup: fetch: use ref prefix list to skip ls-refs fetch: avoid ls-refs only to ask for HEAD symref update fetch: stop protecting additions to ref-prefix list fetch: ask server to advertise HEAD for config-less fetch refspec_ref_prefixes(): clean up refspec_item logic t5516: beef up exact-oid ref prefixes test t5516: drop NEEDSWORK about v2 reachability behavior t5516: prefer "oid" to "sha1" in some test titles t5702: fix typo in test name
2025-03-21http.c: allow custom TCP keepalive behavior via configTaylor Blau3-1/+57
curl supports a few options to control when and how often it should instruct the OS to send TCP keepalives, like KEEPIDLE, KEEPINTVL, and KEEPCNT. Until this point, there hasn't been a way for users to change what values are used for these options, forcing them to rely on curl's defaults. But we do unconditionally enable TCP keepalives without giving users an ability to tweak any fine-grained parameters. Ordinarily this isn't a problem, particularly for users that have fast-enough connections, and/or are talking to a server that has generous or nonexistent thresholds for killing a connection it hasn't heard from in a while. But it can present a problem when one or both of those assumptions fail. For instance, I can reliably get an in-progress clone to be killed from the remote end when cloning from some forges while using trickle to limit my clone's bandwidth. For those users and others who wish to more finely tune the OS's keepalive behavior, expose configuration and environment variables which allow setting curl's KEEPIDLE, KEEPINTVL, and KEEPCNT options. Note that while KEEPIDLE and KEEPINTVL were added in curl 7.25.0, KEEPCNT was added much more recently in curl 8.9.0. Per f7c094060c (git-curl-compat: remove check for curl 7.25.0, 2024-10-23), both KEEPIDLE and KEEPINTVL are set unconditionally. But since we may be compiled with a curl that isn't as new as 8.9.0, only set KEEPCNT when we have CURLOPT_TCP_KEEPCNT to begin with. Signed-off-by: Taylor Blau <me@ttaylorr.com> Acked-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-21http.c: inline `set_curl_keepalive()`Taylor Blau1-5/+1
At the end of `get_curl_handle()` we call `set_curl_keepalive()` to enable TCP keepalive probes on our CURL handle. `set_curl_keepalive()` dates back to 47ce115370 (http: use curl's tcp keepalive if available, 2013-10-14), which conditionally compiled different variants of `set_curl_keepalive()` depending on what version of curl we were compiled with[^1]. As of f7c094060c (git-curl-compat: remove check for curl 7.25.0, 2024-10-23), we no longer conditionally compile `set_curl_keepalive()` since we no longer support pre-7.25.0 versions of curl. But the version of that function that we kept is really just a thin wrapper around setting the TCP_KEEPALIVE option, so there's no reason to keep it in its own function. Inline the definition of `set_curl_keepalive()` to within `get_curl_handle()` so that the setup of our CURL handle is self-contained. [1]: The details are spelled out in 47ce115370, but the gist is curl 7.25.0 and newer use CURLOPT_TCP_KEEPALIVE, older versions use CURLOPT_SOCKOPTFUNCTION with a custom callback, and older versions that predate even that option do nothing. Signed-off-by: Taylor Blau <me@ttaylorr.com> Acked-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-21http.c: introduce `set_long_from_env()` for convenienceTaylor Blau1-8/+24
In 7059cd99fc (http_init(): Fix config file parsing, 2009-03-09), http.c gained a new "set_from_env()" function as a convenience function around conditionally assigning an environment variable to some variable if and only if the environment variable was set to begin with. But prior to 7059cd99fc, there were two spots which need to first strtol() whatever is set in the environment before assigning it to a long pointer. Both instances stored the result of getenv() in a temporary variable, and conditionally strtol() it depending on whether or not getenv() returned NULL. Replace those two instances with a new cousin of 'set_from_env()' called 'set_long_from_env()', which does what its name suggests. This allows us to remove the temporary variables and clean up some minor code duplication while also adding more robust error handling. More importantly, however, it prepares us for a future commit which will introduce more instances of assigning an environment variable to a long. Signed-off-by: Taylor Blau <me@ttaylorr.com> Acked-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-21http.c: remove unnecessary casts to longTaylor Blau1-2/+2
When parsing 'http.lowSpeedLimit' and 'http.lowSpeedTime', we explicitly cast the result of 'git_config_int()' to a long before assignment. This cast has been in place since all the way back in 58e60dd203 (Add support for pushing to a remote repository using HTTP/DAV, 2005-11-02). But that cast has always been unnecessary, since long is guaranteed to be at least as wide as int. Let's drop the cast accordingly. Noticed-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Taylor Blau <me@ttaylorr.com> Acked-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-20ci/github: add missing 'CI_JOB_IMAGE' env variableKarthik Nayak1-0/+4
The CI setups of GitLab and GitHub use a common dependency management script 'ci/install-dependencies.sh'. The script install the necessary packages based on a combination of the "$distro" and "$jobname" env variables. The "$distro" variable is derived from the "CI_JOB_IMAGE" env variable set by the CI configs. In the GitHub CI config, some of the jobs are missing this variable. For the 'Documentation' job which depends on 'meson' being installed, this raises an error since the 'meson' dependency is never installed. Fix this by adding the 'CI_JOB_IMAGE' variable to all missing jobs. We don't add it the windows jobs, since they manager their dependency as part of the CI config and no further dependency management is needed. Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-20doc: apply new format to git-branch man pageJean-Noël Avila2-196/+196
- Switch the synopsis to a synopsis block which automatically formats placeholders in italics and keywords in monospace - Use _<placeholder>_ instead of <placeholder> in the description - Use `backticks` for keywords and more complex option descriptions. The new rendering engine applies synopsis rules to these spans. Possible values for some variables, that were mentioned in the description prose, are now made into enumerated list. Signed-off-by: Jean-Noël Avila <jn.avila@free.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-20completion: take into account the formatting backticks for optionsJean-Noël Avila1-4/+12
With the modern formatting of the manpages, the options and commands are now backticked in their definition lists. This patch updates the generation of the completion list to take into account this new format. The script `generate-configlist.sh` is updated to get rid of extraneous commands and fit everything in a single sed script. Signed-off-by: Jean-Noël Avila <jn.avila@free.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18index-pack, unpack-objects: restore missing ->init_fnJensen Huang2-0/+2
Commit 0578f1e66a ("global: adapt callers to use generic hash context helpers") accidentally removed `->init_fn`, which is required for OpenSSL 3+ SHA1. This fixes the following error on fetch: fatal: fetch-pack: invalid index-pack output Signed-off-by: Jensen Huang <hmz007@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18promisor-remote: compare remote names case sensitivelyChristian Couder2-4/+4
Because the "[remote "nick"] fetch = ..." configuration variables have the nickname in the second part, the nicknames are case sensitive, unlike the first and the third component (i.e. "remote.origin.fetch" and "Remote.origin.FETCH" are the same thing, but "remote.Origin.fetch" and "remote.origin.fetch" are different). Let's follow the way Git works in general and compare the remote names case sensitively when processing advertised remotes. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18promisor-remote: fix possible issue when no URL is advertisedChristian Couder1-1/+6
In the 'KnownUrl' case, in should_accept_remote(), let's check that `remote_url` is not NULL before we use strcmp() to compare it with the local URL. This could avoid crashes if a server starts to not advertise any URL in the future. If `remote_url` is NULL, we should reject the URL. Let's also warn in this case because we warn otherwise when a remote is rejected to try to help diagnose things at the end of the function. And while we are checking that remote_url is not NULL and warning if it is, it makes sense to also help diagnose the case where remote_url is empty. Also while at it, let's spell "URL" with uppercase letters in all the warnings. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18promisor-remote: fix segfault when remote URL is missingChristian Couder2-8/+69
Using strvec_push() to push `NULL` into a 'strvec' results in a segfault, because `xstrdup(NULL)` crashes. So when an URL is missing from the config, let's not push the remote name and URL into the 'strvec's. While at it, let's also not push them in case the URL is empty. It's just not worth the trouble and it's consistent with how Git otherwise treats missing and empty URLs in the same way. Note that in case of missing or empty URL, Git uses the remote name to fetch, which can work if the remote is on the same filesystem. So configurations where the client, server and remote are all on the same filesystem may need URLs to be configured even if they are the same as the remote names. But this is a rare case, and the work around is easy enough. We leave improving the strvec API and/or xstrdup() for a future separate effort. While at it, let's also use git_config_get_string_tmp() instead of git_config_get_string() to simplify memory management. Helped-by: Jeff King <peff@peff.net> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18t5710: arrange to delete the client before cloningChristian Couder1-8/+8
If `test_when_finished "rm -rf client"` is run after we clone, it will not run if the clone failed, so the "client" directory might not be removed at the end of the test. `git clone` does try to remove the directory when it fails, but let's be safe and try to protect against possibly weird clone failures by moving `test_when_finished "rm -rf client"` before the clone. It just makes more sense this way around. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18fetch: don't ask for remote HEAD if followRemoteHEAD is "never"Jeff King2-5/+6
When we are going to consider updating the refs/remotes/*/HEAD symref, we have to ask the remote side where its HEAD points. But if we know that the feature is disabled by config, we don't need to bother! This saves a little bit of work and network communication for the server. And even a little bit of effort on the client, as our local set_head() function did a bit of work matching the remote HEAD before realizing that we're not going to do anything with it. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18fetch: only respect followRemoteHEAD with configured refspecsJeff King4-21/+23
The new followRemoteHEAD feature is triggered for almost every fetch, causing us to ask the server about the remote "HEAD" and to consider updating our local tracking HEAD symref. This patch limits the feature only to the case when we are fetching a remote using its configured refspecs (typically into its refs/remotes/ hierarchy). There are two reasons for this. One is efficiency. E.g., the fixes in 6c915c3f85 (fetch: do not ask for HEAD unnecessarily, 2024-12-06) and 20010b8c20 (fetch: avoid ls-refs only to ask for HEAD symref update, 2025-03-08) were aimed at reducing the work we do when we would not be able to update HEAD anyway. But they do not quite cover all cases. The remaining one is: git fetch origin refs/heads/foo:refs/remotes/origin/foo which _sometimes_ can update HEAD, but usually not. And that leads us to the second point, which is being simple and explainable. The code for updating the tracking HEAD symref requires both that we learned which ref the remote HEAD points at, and that the server advertised that ref to us. But because the v2 protocol narrows the server's advertisement, the command above would not typically update HEAD at all, unless it happened to point to the "foo" branch. Or even weirder, it probably _would_ update if the server is very old and supports only the v0 protocol, which always gives a full advertisement. This creates confusing behavior for the user: sometimes we may try to update HEAD and sometimes not, depending on vague rules. One option here would be to loosen the update code to accept the remote HEAD even if the server did not advertise that ref. I think that could work, but it may also lead to interesting corner cases (e.g., creating a dangling symref locally, even though the branch is not unborn on the server, if we happen not to have fetched it). So let's instead simplify the rules: we'll only consider updating the tracking HEAD symref when we're doing a full fetch of the remote's configured refs. This is easy to implement; we can just set a flag at the moment we realize we're using the configured refspecs. And we can drop the special case code added by 6c915c3f85 and 20010b8c20, since this covers those cases. The existing tests from those commits still pass. In t5505, an incidental call to "git fetch <remote> <refspec>" updated HEAD, which caused us to adjust the test in 3f763ddf28 (fetch: set remote/HEAD if it does not exist, 2024-11-22). We can now adjust that back to how it was before the feature was added. Even though t5505 is incidentally testing our new desired behavior, we'll add an explicit test in t5510 to make sure it is covered. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18Merge branch 'jk/fetch-ref-prefix-cleanup' into jk/fetch-follow-remote-head-fixJunio C Hamano4-39/+85
* jk/fetch-ref-prefix-cleanup: fetch: use ref prefix list to skip ls-refs fetch: avoid ls-refs only to ask for HEAD symref update fetch: stop protecting additions to ref-prefix list fetch: ask server to advertise HEAD for config-less fetch refspec_ref_prefixes(): clean up refspec_item logic t5516: beef up exact-oid ref prefixes test t5516: drop NEEDSWORK about v2 reachability behavior t5516: prefer "oid" to "sha1" in some test titles t5702: fix typo in test name
2025-03-18docs: add BreakingChanges to TECH_DOCS targetPhillip Wood2-0/+2
When BreakingChanges.txt was added in 57ec9254eb9 (docs: introduce document to announce breaking changes, 2024-06-14) there was no corresponding change to the Makefile to build it. Fix that by adding it to the TECH_DOCS target. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18pack-refs doc: fix indentation for --excludePhillip Wood1-2/+2
Separate the paragraphs in the description of `--exclude` with a `+` rather than an empty line to indent the whole description rather than just the first paragraph. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18am: switch from merge_recursive_generic() to merge_ort_generic()Elijah Newren4-5/+5
Switch from merge-recursive to merge-ort. Adjust the following testcases due to the switch: * t4151: This test left an untracked file in the way of the merge. merge-recursive could only sometimes tell when untracked files were in the way, and by the time it discovers others, it has already made too many changes to back out of the merge. So, instead of writing the results to e.g. 'file1' it would instead write them to 'file1~branch1'. This is confusing for users, because they might not notice 'file1~branch1' and accidentally add and commit 'file1'. In contrast, merge-ort correctly notices the file in the way before making any changes and aborts. Since this test didn't care about the file in the way, just remove it before calling git-am. * t4255: Usage of merge-ort allows us to change two known failures into successes. * t6427: As noted a few commits ago, the choice of conflict label for diff3 markers for the ancestor commit was previously handled by merge-recursive.c rather than by callers. Since that has now changed, `git am` needs to specify that label. Although the previous conflict label ("constructed merge base") was already fairly somewhat slanted towards `git am`, let's use wording more along the lines of the related command-line flag from `git apply` and function involved to tie it more closely to `git am`. Signed-off-by: Elijah Newren <newren@gmail.com> Reviewed-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18merge-ort: fix merge.directoryRenames=falseElijah Newren2-3/+30
There are two issues here. First, when merge.directoryRenames is set to false, there are a few code paths that should be turned off. I missed one; collect_renames() was still doing some directory rename detection logic unconditionally. It ended up not having much effect because get_provisional_directory_renames() was skipped earlier and not setting up renames->dir_renames, but the code should still be skipped. Second, the larger issue is that sometimes we get a cached_pair rename from a previous commit being replayed mapping A->B, but in a subsequent commit but collect_merge_info() doesn't even recurse into the directory containing B because there are no source pairings for that rename that are relevant; we can merge that commit fine without knowing the rename. But since the cached renames are added to the normal renames, when we go to process it and find that B is not part of opt->priv->paths, we hit the assertion error process_renames: Assertion `newinfo && ~newinfo->merged.clean` failed. I think we could fix this at the beginning of detect_regular_renames() by pruning from cached_pairs any entry whose destination isn't in opt->priv->paths, but it's suboptimal in that we'd kind of like the cached_pair to be restored afterwards so that it can help the subsequent commit, but more importantly since it sits at the intersection of the caching renames optimization and the relevant renames optimization, and the trivial directory resolution optimization, and I don't currently have Documentation/technical/remembering-renames.txt fully paged in, I'm not sure if that's a full solution or a bandaid for the current testcase. However, since the remembering renames optimization was the weakest of the set, and the optimization is far less important when directory rename detection is off (as that implies far fewer potential renames), let's just use a bigger hammer to ensure this special case is fixed: turn off the rename caching. We do the same thing already when we encounter rename/rename(1to1) cases (as per `git grep -3 disabling.the.optimization`, though it uses a slightly different triggering mechanism since it's trying to affect the next time that merge_check_renames_reusable() is called), and I think it makes sense to do the same here. Signed-off-by: Elijah Newren <newren@gmail.com> Reviewed-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18t3650: document bug when directory renames are turned offJohannes Schindelin1-0/+22
There is a bug in the way renames are cached that rears its head when `merge.directoryRenames` is set to false; it results in the following message: merge-ort.c:3002: process_renames: Assertion `newinfo && !newinfo->merged.clean' failed. Aborted It is quite a curious bug: the same test case will succeed, without any assertion, if instead run with `merge.directoryRenames=true`. Further, the assertion does not manifest while replaying the first commit, it manifests while replaying the _second_ commit of the commit range. But it does _not_ manifest when the second commit is replayed individually. This would indicate that there is an incomplete rename cache left-over from the first replayed commit which is being reused for the second commit, and if directory rename detection is enabled, the missing paths are somehow regenerated. Incidentally, the same bug can by triggered by modifying t6429 to switch from merge.directoryRenames=true to merge.directoryRenames=false. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> [en: tweaked the commit message slightly, including adjusting the line number of the assertion to the latest version, and the much later discovery that a simple t6429 tweak would also display the issue.] Signed-off-by: Elijah Newren <newren@gmail.com> Reviewed-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18merge-ort: support having merge verbosity be set to 0Elijah Newren1-2/+6
Various callers such as am & checkout set the merge verbosity to 0 to avoid having conflict messages printed. While this could be achieved by avoiding the wrappers from merge-ort-wrappers and instead passing 0 for display_update_msgs to merge_switch_to_result(), for simplicity of converting callers simply allow them to also achieve this with the merge-ort-wrappers by setting verbosity to 0. Signed-off-by: Elijah Newren <newren@gmail.com> Reviewed-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18merge-ort: allow rename detection to be disabledElijah Newren3-6/+17
When merge-ort was written, I did not at first allow rename detection to be disabled, because I suspected that most folks disabling rename detection were doing so solely for performance reasons. Since I put a lot of working into providing dramatic speedups for rename detection performance as used by the merge machinery, I wanted to know if there were still real world repositories where rename detection was problematic from a performance perspective. We have had years now to collect such information, and while we never received one, waiting longer with the option disabled seems unlikely to help surface such issues at this point. Also, there has been at least one request to allow rename detection to be disabled for behavioral rather than performance reasons (see the thread including https://lore.kernel.org/git/CABPp-BG-Nx6SCxxkGXn_Fwd2wseifMFND8eddvWxiZVZk0zRaA@mail.gmail.com/ ), so let's start heeding the config and command line settings. Signed-off-by: Elijah Newren <newren@gmail.com> Reviewed-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18merge-ort: add new merge_ort_generic() functionElijah Newren4-5/+93
merge-recursive.[ch] have three entry points: * merge_trees() * merge_recursive() * merge_recursive_generic() merge-ort*.[ch] only has equivalents for the first two. Add an equivalent for the final entry point, so we can switch callers to use it and remove merge-recursive.[ch]. While porting it over, finally fix the issue with the label for the ancestor (used when merge.conflictStyle=diff3 as a conflict label). merge-recursive.c has traditionally not allowed callers to set that label, but I have found that problematic for years. (Side note: This function was initially part of the merge-ort rewrite, but reviewers questioned the ancestor label funnyness which I was never really happy with anyway. It resulted in me jettisoning it and hoping at the time that I would eventually be able to force the existing callers to use some other API. That worked with `git stash`, as per 874cf2a60444 (stash: apply stash using 'merge_ort_nonrecursive()', 2022-05-10), but this API is the most reasonable one for `git am` and `git merge-recursive`, if we can just allow them some freedom over the ancestor label.) The merge_recursive_generic() function did not know whether it was being invoked by `git stash`, `git merge-recursive`, or `git am`, and the choice of meaningful ancestor label, when there is a unique ancestor, varies for these different callers: * git am: ancestor is a constructed "fake ancestor" that user knows nothing about and has no access to. (And is different than the normal thing we mean by a "virtual merge base" which is the merging of merge bases.) * git merge-recursive: ancestor might be a tree, but at least it was one specified by the user (if they invoked merge-recursive directly) * git stash: ancestor was the commit serving as the stash base Thus, using a label like "constructed merge base" (as merge_recursive_generic() does) presupposes that `git am` is the only caller; it is incorrect for other callers. This label has thrown me off more than once. Allow the caller to override when there is a unique merge base. Signed-off-by: Elijah Newren <newren@gmail.com> Reviewed-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18doc: add missing commit C to the graph for --ancestry-path=H D..MHan Jiang1-1/+1
The graph for `--ancestry-path=H D..M` should contain commit C. Signed-off-by: Han Jiang <jhcarl0814@gmail.com> Acked-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18doc: restore: remove note on --patch w/ pathspecsAdam Johnson1-3/+0
This note was added to the restore command docs in 46e91b663b (checkout: split part of it to new command 'restore', 2019-04-25), but it is now inaccurate. The underlying builtin `add -i` implementation, made default in 0527ccb1b5 (add -i: default to the built-in implementation, 2021-11-30), supports pathspecs, so `git restore -p <pathspec>...` has worked for all users since then. I bisected to verify this was the commit that added support. Signed-off-by: Adam Johnson <me@adamj.eu> Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17config.mak.dev: enable -Wunreachable-codeJeff King2-0/+2
Having the compiler point out unreachable code can help avoid bugs, like the one discussed in: https://lore.kernel.org/git/20250307195057.GA3675279@coredump.intra.peff.net/ In that case it was found by Coverity, but finding it earlier saves everybody time and effort. We can use -Wunreachable-code to get some help from the compiler here. Interestingly, this is a noop in gcc. It was a real warning up until gcc 4.x, when it was removed for being too flaky, but they left the command-line option to avoid breaking users. See: https://stackoverflow.com/questions/17249934/why-does-gcc-not-warn-for-unreachable-code However, clang does implement this option, and it finds the case mentioned above (and no other cases within the code base). And since we run clang in several of our CI jobs, that's enough to get an early warning of breakage. We could enable it only for clang, but since gcc is happy to ignore it, it's simpler to just turn it on for all developer builds. Signed-off-by: Jeff King <peff@peff.net> [jc: squashed meson.build change sent by Patrick] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17git-compat-util: add NOT_CONSTANT macro and use it in atfork_prepare()Junio C Hamano5-7/+18
Our hope is that the number of code paths that falsely trigger warnings with the -Wunreachable-code compilation option are small, and they can be worked around case-by-case basis, like we just did in the previous commit. If we need such a workaround a bit more often, however, we may benefit from a more generic and descriptive facility that helps document the cases we need such workarounds. Side note: if we need the workaround all over the place, it simply means -Wunreachable-code is not a good tool for us to save engineering effort to catch mistakes. We are still exploring if it helps us, so let's assume that it is not the case. Introduce NOT_CONSTANT() macro, with which, the developer can tell the compiler: Do not optimize this expression out, because, despite whatever you are told by the system headers, this expression should *not* be treated as a constant. and use it as a replacement for the workaround we used that was somewhat specific to the sigfillset case. If the compiler already knows that the call to sigfillset() cannot fail on a particular platform it is compiling for and declares that the if() condition would not hold, it is plausible that the next version of the compiler may learn that sigfillset() that never fails would not touch errno and decide that in this sequence: errno = 0; sigfillset(&all) if (errno) die_errno("sigfillset"); the if() statement will never trigger. Marking that the value returned by sigfillset() cannot be a constant would document our intention better and would not break with such a new version of compiler that is even more "clever". With the marco, the above sequence can be rewritten: if (NOT_CONSTANT(sigfillset(&all))) die_errno("sigfillset"); which looks almost like other innocuous annotations we have, e.g. UNUSED. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17Merge branch 'tb/multi-cruft-pack-refresh-fix' into tb/combine-cruft-below-sizeJunio C Hamano4-18/+171
* tb/multi-cruft-pack-refresh-fix: builtin/pack-objects.c: freshen objects from existing cruft packs
2025-03-17reflog: implement subcommand to drop reflogsKarthik Nayak3-5/+206
While 'git-reflog(1)' currently allows users to expire reflogs and delete individual entries, it lacks functionality to completely remove reflogs for specific references. This becomes problematic in repositories where reflogs are not needed but continue to accumulate entries despite setting 'core.logAllRefUpdates=false'. Add a new 'drop' subcommand to git-reflog that allows users to delete the entire reflog for a specified reference. Include an '--all' flag to enable dropping all reflogs from all worktrees and an addon flag '--single-worktree', to only drop all reflogs from the current worktree. While here, remove an extraneous newline in the file. Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17reflog: improve error for when reflog is not foundKarthik Nayak2-3/+3
The 'git reflog expire' prints the error message '<ref> points nowhere!' when used with a non-existent ref. This message is a bit confusing and vague. Modify the message to be more clear and direct. Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17run-command: use errno to check for sigfillset() errorJeff King1-1/+9
Since enabling -Wunreachable-code, builds with clang on macOS now fail, complaining that the die_errno() call in: if (sigfillset(&all)) die_errno("sigfillset"); is unreachable. On that platform the manpage documents that sigfillset() always returns success, and presumably the implementation is a macro or inline function that does so in a way that is transparent to the compiler. But we should continue to check on other platforms, since POSIX says it may return an error. We could solve this with a compile-time knob to split the two cases (assuming success on macOS and checking for the error elsewhere). But we can also work around it more directly by relying on errno to check the outcome (since POSIX dictates that errno will be set on error). And that works around the compiler's cleverness, since it doesn't know the semantics of errno (though I suppose if sigfillset() is simple enough, it could perhaps realize that no writes to errno are possible; however this does seem to work in practice). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17merge-ort: remove extraneous word in commentElijah Newren1-3/+3
"is was" -> "was" Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17merge-ort: fix accidental strset<->strintmapElijah Newren1-2/+2
Both strset_for_each_entry and strintmap_for_each_entry are macros that evaluate to the same thing, so they are technically interchangeable. However, the intent is that we use the one matching the variable type we are passing. Unfortunately, I somehow mistakenly got one of these wrong in 7bee6c100431 (merge-ort: avoid recursing into directories when we don't need to, 2021-07-16) -- possibly related to the fact that relevant_sources was initially a strset and later refactored into a strintmap. Correct which macro we use. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17t7615: be more explicit about diff algorithm usedElijah Newren1-2/+2
t7615 is entirely about testing the differences about different diff algorithms, but it doesn't specify any diff algorithm when it is testing myers. Given that we have discussed potentially switching defaults (https://lore.kernel.org/git/xmqqed873vgn.fsf@gitster.g/), it makes sense in tests that are about different diff algorithms to be explicitly about which one is intended to be used in each test. Add that specificity. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17t6423: fix a comment that accidentally reversed two commitsElijah Newren1-3/+3
The comment describing testcase 13b of t6423 somehow mixed up commits A and B in one paragraph. Fix the references. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17stash: remove merge-recursive.h includeElijah Newren1-1/+0
stash was modified to use merge_ort_nonrecursive() instead of merge_recursive_generic() back in commit 874cf2a60444 (stash: apply stash using 'merge_ort_nonrecursive()', 2022-05-10). That makes the inclusion of merge-recursive.h unnecessary. In preparation for the removal of merge-recursive.h, remove the unnecessary include. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17meson: fix perl detection when docs are enabled, but perl bindings aren'tEli Schwartz1-1/+1
The `perl` variable in meson.build is assigned to a program lookup, which may have the value "not-found object" if configuring with `-Dperl=disabled`. There is already a list of other cases where we do need a perl command, even when not building perl bindings. Building documentation should be one of those cases, but was missing from the list. Add it. Fixes: ``` $ meson setup builddir/ -Ddocs=man -Dperl=disabled -Dtests=false [...] Documentation/meson.build:308:22: ERROR: Tried to use not-found external program in "command" ``` Bug: https://bugs.gentoo.org/949247 Signed-off-by: Eli Schwartz <eschwartz@gentoo.org> Acked-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-16git-gui: heed core.commentChar/commentStringOswald Buddenhagen2-1/+11
This amends 1ae85ff6d (git-gui: strip comments and consecutive empty lines from commit messages, 2024-08-13) to deal with custom comment characters/strings. The magic commentString value "auto" is not handled, because the option makes no sense to me - it does not support comments in templates and hook output, and it seems far-fetched that someone would introduce comments during editing the message. Signed-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
2025-03-14diffcore-rename: fix BUG when break detection and --follow used togetherElijah Newren2-4/+37
Prior to commit 9db2ac56168e (diffcore-rename: accelerate rename_dst setup, 2020-12-11), the function add_rename_dst() resulted in quadratic runtime since each call inserted the new entry into the array in sorted order. The reason for the sorted order requirement was so that locate_rename_dst(), used when break detection is turned on, could find the appropriate entry in logarithmic time via bisection on string comparisons. (It's better to be quadratic in moving pointers than quadratic in string comparisons, so this made some sense.) However, since break detection always sticks the broken pairs adjacent to each other, that commit decided to simply append entries to rename_dst, and record the mapping of (filename) -> (index within rename_dst) via a strintmap. Doing this relied on the fact that when adding the source of a broken pair via register_rename_src(), that the next item we'd process was the other half of the same broken pair and would be added to rename_dst via add_rename_dst(). This assumption was fine under break detection alone, but the combination of break detection and single_follow violated that assumption because of this code: else if (options->single_follow && strcmp(options->single_follow, p->two->path)) continue; /* not interested */ which would end up skipping calling add_rename_dst() below that point. Since I knew I was assuming that the dst pair of a break would always be added right after the src pair of a break, I added a new BUG() directive as part of that commit later on at time of use that would check my assumptions held. That BUG() didn't trip for nearly 4 years...which sadly meant I had long since forgotten the related details. Anyway... When the dst half of a broken pair is skipped like this, it means that not only could my recorded index be invalid (just past the end of the array), it could also point to some unrelated dst that just happened to be the next one added to the array. So, to fix this, we need to add a little more safety around the checks for the recorded break_idx. It turns out that making a testcase to trigger this is quite the challenge. I actually added two testscases: * One testcase which uses --follow incorrectly (it uses its single pathspec to specifying something other than a single filename), and which triggers the same bug reported-by Olaf. This triggers a special case within locate_rename_dst() where idx evaluates to 0 and rename_dst is NULL, meaning that our return value of &rename_dst[idx] happens to evaluate to NULL as well. This addressing of an index into a NULL array hints at deeper problems, which are raised in the next testcase... * A second testcase which when run under valgrind shows that the code actually depends upon unintialized memory, in particular the entry just after the end of the rename_dst array. In short, when the two rare options -B and --follow are used together, fix the accidental find of the wrong dst entry (which would often be uninitialized memory just past the end of the array, but also could have just been a dst for an unrelated path if no dst was recorded for the expected path). Do so by adding a little more care around checking the recorded indices in break_idx. Reported-by: Olaf Hering <olaf@aepfle.de> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-14xdiff: avoid arithmetic overflow in xdl_get_hunk()René Scharfe2-1/+17
xdl_get_hunk() calculates the maximum number of common lines between two changes that would fit into the same hunk for the given context options. It involves doubling and addition and thus can overflow if the terms are huge. The type of ctxlen and interhunkctxlen in xdemitconf_t is long, while the type of the corresponding context and interhunkcontext in struct diff_options is int. On many platforms longs are bigger that ints, which prevents the overflow. On Windows they have the same range and the overflow manifests as hunks that are split erroneously and lines being repeated between them. Fix the overflow by checking and not going beyond LONG_MAX. This allows specifying a huge context line count and getting all lines of a changed files in a single hunk, as expected. Reported-by: Jason Cho <jason11choca@proton.me> Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-14Git 2.49v2.49.0Junio C Hamano1-1/+1
Signed-off-by: Junio C Hamano <gitster@pobox.com>