aboutsummaryrefslogtreecommitdiffstats
AgeCommit message (Collapse)AuthorFilesLines
2025-09-08contrib/diff-highlight: mention interactive.diffFilterJeff King1-0/+8
When the README for diff-highlight was written, there was no way to trigger it for the `add -p` interactive patch mode. We've since grown a feature to support that, but it was documented only on the Git side. Let's also let people coming the other direction, from diff-highlight, know that it's an option. Suggested-by: Isaac Oscar Gariano <IsaacOscar@live.com.au> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-08add-interactive: manually fall back color config to color.uiJeff King2-0/+24
Color options like color.interactive and color.diff should fall back to the value of color.ui if they aren't set. In add-interactive, we check the specific options (e.g., color.diff) via repo_config_get_value(), which does not depend on the main command having loaded any color config via the git_config() callback mechanism. But then we call want_color() on the result; if our specific config is unset then that function uses the value of git_use_color_default. That variable is typically set from color.ui by the git_color_config() callback, which is called by the main command in its own git_config() callback function. This works fine for "add -p", whose add_config() callback calls into git_color_config(). But it doesn't work for other commands like "checkout -p", which is otherwise unaware of color at all. People tend not to notice because the default is "auto", and that's what they'd set color.ui to as well. But something like: git -c color.ui=false checkout -p should disable color, and it doesn't. This regression goes back to 0527ccb1b5 (add -i: default to the built-in implementation, 2021-11-30). In the perl version we got the color config from "git config --get-colorbool", which did the full lookup for us. The obvious fix is for git-checkout to add a call to git_color_config() to its own config callback. But we'd have to do so for every command with this problem, which is error-prone. Let's see if we can fix it more centrally. It is tempting to teach want_color() to look up the value of repo_config_get_value("color.ui") itself. But I think that would have disastrous consequences. Plumbing commands, especially older ones, avoid porcelain config like "color.*" by simply not parsing it in their config callbacks. Looking up the value of color.ui under the hood would undermine that. Instead, let's do that lookup in the add-interactive setup code. We're already demand-loading other color config there, which is probably fine (even in a plumbing command like "git reset", the interactive mode is inherently porcelain-ish). That catches all commands that use the interactive code, whether they were calling git_color_config() themselves or not. Reported-by: Isaac Oscar Gariano <isaacoscar@live.com.au> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-08add-interactive: respect color.diff for diff coloringJeff King4-41/+95
The old perl git-add--interactive.perl script used the color.diff config option to decide whether to color diffs (and if not set, it fell back to the value of color.ui via git-config's --get-colorbool option). When we switched to the builtin version, this was lost: we respect only color.ui. So for example: git -c color.diff=false add -p would color the diff, even when it should not. The culprit is this line in add-interactive.c's parse_diff(): if (want_color_fd(1, -1)) That "-1" means "no config has been set", which causes it to fall back to the color.ui setting. We should instead be passing the value of color.diff. But the problem is that we never even parse that config option! Instead the builtin interactive code parses only the value of color.interactive, which is used for prompts and other messages. One could perhaps argue that this should cover interactive diff coloring, too, but historically it did not. The perl script treated color.interactive and color.diff separately. So we should grab the values for both, keeping separate fields in our add_i_state variable, rather than a single use_color field. We also load individual color slots (e.g., color.interactive.prompt), leaving them as the empty string when color is disabled. This happens via the init_color() helper in add-interactive, which checks that use_color field. Now that there are two such fields, we need to pass the appropriate one for each color. The colors are mostly easy to divide up; color.interactive.* follows color.interactive, and color.diff.* follows color.diff. But the "reset" color is tricky. It is used for both types of coloring, but the two can be configured independently. So we introduce two separate reset colors, and use each in the appropriate spot. There are two new tests. The first enables interactive prompt colors but disables color.diff. We should see a colored prompt but not a colored diff, showing that we are now respecting color.diff (and not color.interactive or color.ui). The second does the opposite. We disable color.interactive but turn on color.diff with a custom fragment color. When we split a hunk, the interactive code has to re-color the hunk header, which lets us check that we correctly loaded the color.diff.frag config based on color.diff, not color.interactive. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-08stash: pass --no-color to diff plumbing child processesJeff King2-1/+23
After a partial stash, we may clear out the working tree by capturing the output of diff-tree and piping it into git-apply (and likewise we may use diff-index to restore the index). So we most definitely do not want color diff output from that diff-tree process. And it normally would not produce any, since its stdout is not going to a tty, and the default value of color.ui is "auto". However, if GIT_PAGER_IN_USE is set in the environment, that overrides the tty check, and we'll produce a colorized diff that chokes git-apply: $ echo y | GIT_PAGER_IN_USE=1 git stash -p [...] Saved working directory and index state WIP on main: 4f2e2bb foo error: No valid patches in input (allow with "--allow-empty") Cannot remove worktree changes Setting this variable is a relatively silly thing to do, and not something most users would run into. But we sometimes do it in our tests to stimulate color. And it is a user-visible bug, so let's fix it rather than work around it in the tests. The root issue here is that diff-tree (and other diff plumbing) should probably not ever produce color by default. It does so not by parsing color.ui, but because of the baked-in "auto" default from 4c7f1819b3 (make color.ui default to 'auto', 2013-06-10). But changing that is risky; we've had discussions back and forth on the topic over the years. E.g.: https://lore.kernel.org/git/86D0A377-8AFD-460D-A90E-6327C6934DFC@gmail.com/. So let's accept that as the status quo for now and protect ourselves by passing --no-color to the child processes. This is the same thing we did for add-interactive itself in 1c6ffb546b (add--interactive.perl: specify --no-color explicitly, 2020-09-07). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-05upload-pack: don't ACK non-commits repeatedly in protocol v2Patrick Steinhardt2-10/+48
When a client performs a fetch or clone they can optionally send "have" lines to tell the server which objects they already have available locally. These object IDs are stored by the server in an object array so that it can remember any objects it doesn't have to include in the pack sent to the client. While there isn't any reason to do so, clients are free to send the same "have" line repeatedly. git-upload-pack(1) already knows to handle this well: every commit it has seen via a "have" line gets marked with the `THEY_HAVE` flag, and if such a commit is seen repeatedly we know to not process it another time. This also has the effect that we only store the object ID once, only, in the `have_obj` array. There is an edge case though: if the client sends an object ID that does not refer to a commit we neither store nor check the `THEY_HAVE` flag. This means that we repeatedly store the same object ID in our `have_obj` array, with two consequences: - In protocol v2 we deduplicate ACKs for commits, but not for any other objects as we send ACKs for every object ID in the `have_obj` array. - The `have_obj` array can grow in size indefinitely with both protocols. The potentially-more-serious issue is the second one, as we basically have a way for an adversary to allocate arbitrarily large buffers now. Ultimately, this doesn't seem to be all that serious though: on my machine, the growth of that array is at around 4MB/s, and after roughly five minutes I was only at 1GB RSS. So this is concerning, but only mildly so. Fix this bug by storing the `THEY_HAVE` flag independent of the object type so that we don't store duplicate object IDs in `have_obj` anymore. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-05t5530: modernize testsPatrick Steinhardt1-28/+5
Refactor tests to follow modern best practices: - Merge together tests that set up and verify a single use case. - Drop empty newlines at the beginning and end of test bodies. - Don't change directories in the main test body. - Remove an unused `D` variable. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-05midx-write: simplify error casesDerrick Stolee1-17/+9
The write_midx_internal() method uses gotos to jump to a cleanup section to clear memory before returning 'result'. Since these jumps are more common for error conditions, initialize 'result' to -1 and then only set it to 0 before returning with success. There are a couple places where we return with success via a jump. This has the added benefit that the method now returns -1 on error instead of an inconsistent 1 or -1. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-05midx-write: reenable signed comparison errorsDerrick Stolee1-17/+18
Remove the remaining signed comparison warnings in midx-write.c so that they can be enforced as errors in the future. After the previous change, the remaining errors are due to iterator variables named 'i'. The strategy here involves defining the variable within the for loop syntax to make sure we use the appropriate bitness for the loop sentinel. This matters in at least one method where the variable was compared to uint32_t in some loops and size_t in others. While adjusting these loops, there were some where the loop boundary was checking against a uint32_t value _plus one_. These were replaced with non-strict comparisons, but also the value is checked to not be UINT32_MAX. Since the value is the number of incremental multi-pack- indexes, this is not a meaningful restriction. The new die() is about defensive programming more than it being realistically possible. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-05midx-write: use uint32_t for preferred_pack_idxDerrick Stolee1-11/+15
midx-write.c has the DISABLE_SIGN_COMPARE_WARNINGS macro defined for a few reasons, but the biggest one is the use of a signed preferred_pack_idx member inside the write_midx_context struct. The code currently uses -1 to indicate an unset preferred pack but pack int ids are normally handled as uint32_t. There are also a few loops that search for the preferred pack by name and those iterators will need updates to uint32_t in the next change. For now, replace the use of -1 with a 'NO_PREFERRED_PACK' macro and an equality check. The macro stores the max value of a uint32_t, so we cannot store a preferred pack that appears last in a list of 2^32 total packs, but that's expected to be unreasonable already. Furthermore, with this change we end up extending the range from 2^31 possible packs to 2^32-1. There are some careful things to worry about with initializing the preferred pack in the struct and using that value when searching for a preferred pack that was already incorrect but accidentally working when the index was initialized to zero. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-05midx-write: use cleanup when incremental midx failsDerrick Stolee1-6/+12
The incremental mode of writing a multi-pack-index has a few extra conditions that could lead to failure, but these are currently short-ciruiting with 'return -1' instead of setting the method's 'result' variable and going to the cleanup tag. Replace these returns with gotos to avoid memory issues when exiting early due to error conditions. Unfortunately, these error conditions are difficult to reproduce with test cases, which is perhaps one reason why the memory loss was not caught by existing test cases in memory tracking modes. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-05midx-write: put failing response value backDerrick Stolee2-1/+5
This instance of setting the result to 1 before going to cleanup was accidentally removed in fcb2205b77 (midx: implement support for writing incremental MIDX chains, 2024-08-06). Build upon a test that already deletes a packfile to verify that this error propagates to full command failure. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-05midx-write: only load initialized packsDerrick Stolee2-27/+36
The fill_packs_from_midx() method was refactored in fcb2205b77 (midx: implement support for writing incremental MIDX chains, 2024-08-06) to allow for preferred packfiles and incremental multi-pack-indexes. However, this led to some conditions that can cause improperly initialized memory in the context's list of packfiles. The conditions caring about the preferred pack name or the incremental flag are currently necessary to load a packfile. But the context is still being populated with pack_info structs based on the packfile array for the existing multi-pack-index even if prepare_midx_pack() isn't called. Add a new test that breaks under --stress when compiled with SANITIZE=address. The chosen number of 100 packfiles was selected to get the --stress output to fail about 50% of the time, while 50 packfiles could not get a failure in most --stress runs. The test case is marked as EXPENSIVE not only because of the number of packfiles it creates, but because some CI environments were reporting errors during the test that I could not reproduce, specifically around being unable to open the packfiles or their pack-indexes. When it fails under SANITIZE=address, it provides the following error: AddressSanitizer:DEADLYSIGNAL ================================================================= ==3263517==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000027 ==3263517==The signal is caused by a READ memory access. ==3263517==Hint: address points to the zero page. #0 0x562d5d82d1fb in close_pack_windows packfile.c:299 #1 0x562d5d82d3ab in close_pack packfile.c:354 #2 0x562d5d7bfdb4 in write_midx_internal midx-write.c:1490 #3 0x562d5d7c7aec in midx_repack midx-write.c:1795 #4 0x562d5d46fff6 in cmd_multi_pack_index builtin/multi-pack-index.c:305 ... This failure stack trace is disconnected from the real fix because the bad pointers are accessed later when closing the packfiles from the context. There are a few different aspects to this fix that are worth noting: 1. We return to the previous behavior of fill_packs_from_midx to not rely on the incremental flag or existence of a preferred pack. 2. The behavior to scan all layers of an incremental midx is kept, so this is not a full revert of the change. 3. We skip allocating more room in the pack_info array if the pack fails prepare_midx_pack(). 4. The method has always returned 0 for success and 1 for failure, but the condition checking for error added a check for a negative result for failure, so that is now updated. 5. The call to open_pack_index() is removed, but this is needed later in the case of a preferred pack. That call is moved to immediately before its result is needed (checking for the object count). Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-04object-name: declare pointer type of extend_abbrev_len()'s 2nd parameterRené Scharfe1-3/+2
Expose the expected type of the second parameter of extend_abbrev_len() instead of casting a void pointer internally. Just a single caller passes in a void pointer, the rest pass the correct type. Let the compiler help keeping it that way. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-03docs: fix typo in worktree.adoc 'extension'Mikhail Malinouski1-1/+1
The documentation incorrectly referred to the extension without an 's'. This fixes the typo for clarity. Signed-off-by: Mikhail Malinouski <m.l.malinouski@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-02doc: remove extra backtick for inline-verbatimKristoffer Haugsbakk1-1/+1
Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-02doc: add missing backtick for inline-verbatimKristoffer Haugsbakk2-2/+2
Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-02gitlab-ci: disable realtime monitoring to unbreak Windows jobsPatrick Steinhardt1-0/+3
The GitLab CI runners using Windows machines have realtime monitoring via Windows Defender enabled by default. This has just now started to cause issues in our CI jobs using Microsoft Visual Studio: Program 'meson.exe' failed to run: Operation did not complete successfully because the file contains a virus or potentially unwanted softwareAt line:356 char:1 + meson setup build --vsenv -Dperl=disabled -Dbackend_max_links=1 -Dcre ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~. At line:356 char:1 + meson setup build --vsenv -Dperl=disabled -Dbackend_max_links=1 -Dcre ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ResourceUnavailable: (:) [], ApplicationFailedException + FullyQualifiedErrorId : NativeCommandFailed The detected issue is more likely than not completely bogus, but it breaks the jobs. Fix the issue by disabling realtime monitoring. Besides unbreaking CI, it also improves our build times a bit: - Building Git goes from 26 to 22 minutes. - Executing tests goes from ~1h for one slice of tests to ~30 minutes. This is still painfully slow, but the issue here is that the Windows runners on GitLab CI are quite underwhelming overall. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-02doc: fix formatting of function-wrap shell aliasKyle E. Mitchell1-1/+1
Add a missed backtick to the end of a code segment so that it will be rendered like preceding examples. I deeply appreciate the thoroughness of this documentation. I noticed the formatting discrepancy reading https://git-scm.com/docs/git-config. Signed-off-by: Kyle E. Mitchell <kyle@kemitchell.com> Acked-by: Jean-Noël AVILA <avila.jn@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-27curl: add support for curl_global_trace() componentsJeff King3-1/+18
In addition to the regular trace information produced by CURLOPT_VERBOSE, recent curl versions can enable or disable tracing of specific subsystems using a call to curl_global_trace(). This level of detail may or may not be useful for us in Git as mere users of libcurl, but there's one case where we need it for a test. In t5564, we set up a socks proxy, access it with GIT_TRACE_CURL set, and expect to find socks-related messages in the output. This test is broken in the release candidates for libcurl 8.16, as those socks messages are no longer produced in the trace. The problem bisects to curl's commit ab5e0bfddc (pytest: add SOCKS tests and scoring, 2025-07-21). There the socks messages were moved from generic infof() messages to the component-specific CURL_TRC_CF() system. And so we do not see them by default, but only if "socks" is enabled as a logging component. Teach Git's http code to accept a component list from the environment and pass it into curl_global_trace(). We can then use that in the test to enable the correct component. It should be safe to do so unconditionally. In older versions of curl which don't support this call, setting the environment variable is a noop. Likewise, any versions of curl which don't recognize the "socks" component should silently ignore it. The manpage for curl_global_trace() says this: The config string is a list of comma-separated component names. Names are case-insensitive and unknown names are ignored. The special name "all" applies to all components. Names may be prefixed with '+' or '-' to enable or disable detailed logging for a component. The list of component names is not part of curl's public API. Names may be added or disappear in future versions of libcurl. Since unknown names are silently ignored, outdated log configurations does not cause errors when upgrading libcurl. Given that, some names can be expected to be fairly stable and are listed below for easy reference. So this should let us make the test work on all versions without worrying about confusing older (or newer) versions. For the same reason, I've opted not to document this interface. This is deep internal voodoo for which we can make no promises to users. In fact, I was tempted to simply hard-code "socks" to let our test pass and not expose anything. But I suspect a little run-time flexibility may come in handy in the future when debugging or dealing with similar logging issues. I also considered just putting "all" into such a hard-coded default. But if you try it, you will see that many of the components are quite verbose and likely not interesting. They would clutter up our trace output if we enabled them by default. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-26Makefile: build libgit-rs and libgit-sys seriallyDavid Aguilar2-16/+9
"make -JN" with INCLUDE_LIBGIT_RS enabled causes cargo lock warnings and can trigger ld errors during the build. The build errors are caused by two inner "make" invocations getting triggered concurrently: once inside of libgit-sys and another inside of libgit-rs. Make libgit-rs depend on libgit-sys so that "make" prevents them from running concurrently. Apply the same logic to the test invocations. Use cargo's "--manifest-path" option instead of "cd" in the recipes. Signed-off-by: David Aguilar <davvid@gmail.com> Acked-by: Kyle Lippincott <spectral@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-26docs: update sendmail docs to use more secure SMTP server for GmailAditya Garg1-4/+4
Earlier recommendation by IETF with RFC 2595 was to deprecate implicit TLS in preference for upgrade an initially unencrypted connection with STARTTLS command. These days, however, IETF recommends that connections be made using "Implicit TLS", in preference to STARTTLS and the like, completely reversing their earlier position, in RFC8314. Update the GMail example to use the implicit TLS to match the current recommendation at port 465. Signed-off-by: Aditya Garg <gargaditya08@live.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-26docs: note that extensions.compatobjectformat is incompletebrian m. carlson1-0/+4
The compatibility object format is only implemented for loose objects, not packed objects, so anyone attempting to push or fetch data into a repository with this option will likely not see it work as expected. In addition, the underlying storage of loose object mapping is likely to change because the current format is inefficient and does not handle important mapping information such as that of submodules. It would have been preferable to initially document that this was not yet ready for prime time, but we did not do so. We hinted at the fact that this functionality is incomplete in the description, but did not say so explicitly. Let's do so now: indicate that this feature is incomplete and subject to change and that the option is not designed to be used by end users. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-25progress: pay attention to (customized) delay timeJohannes Sixt2-6/+8
Using one of the start_delayed_*() functions, clients of the progress API can request that a progress meter is only shown after some time. To do that, the implementation intends to count down the number of seconds stored in struct progress by observing flag progress_update, which the timer interrupt handler sets when a second has elapsed. This works during the first second of the delay. But the code forgets to reset the flag to zero, so that subsequent calls of display_progress() think that another second has elapsed and decrease the count again until zero is reached. Due to the frequency of the calls, this happens without an observable delay in practice, so that the effective delay is always just one second. This bug has been with us since the inception of the feature. Despite having been touched on various occasions, such as 8aade107dd84 (progress: simplify "delayed" progress API), 9c5951cacf5c (progress: drop delay-threshold code), and 44a4693bfcec (progress: create GIT_PROGRESS_DELAY), the short delay went unnoticed. Copy the flag state into a local variable and reset the global flag right away so that we can detect the next clock tick correctly. Since we have not had any complaints that the delay of one second is too short nor that GIT_PROGRESS_DELAY is ignored, people seem to be comfortable with the status quo. Therefore, set the default to 1 to keep the current behavior. Signed-off-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-25doc: config: replace backtick with apostrophe for possessiveKristoffer Haugsbakk1-1/+1
Revert back to “Git's” which was used before d30c5cc4592 (doc: convert git-mergetool options to new synopsis style, 2025-05-25) accidentally changed it. Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-25fetch-pack: re-scan when double-checking graph objectsJeff King1-1/+2
The fetch code tries to avoid asking the remote side for an object we already have. It does this by traversing recent commits reachable from our refs looking for matches. Commit 5d4cc78f72 (fetch-pack: die if in commit graph but not obj db, 2024-11-05) introduced an extra check there: if we think we have an object because it's in the commit graph, we double-check that we actually have it in our object database with a call to odb_has_object(). But that call does not pass any flags, and so the function won't call reprepared_packed_git() if it does not find the object. That opens us up to the usual race against some other process repacking the odb: 1. We scan the list of packs in objects/pack but haven't yet opened them. 2. Somebody else packs the object into a new pack (which we don't know about), and deletes the old pack it was in. 3. Our odb_has_object() calls tries to open that old pack, but finds it is gone. We declare that we don't have the object. And this causes us to erroneously complain and abort the fetch, thinking our commit-graph and object database are out of sync. Instead, we should pass HAS_OBJECT_RECHECK_PACKED, which will add a new step: 4. We re-scan the pack directory again, find the new pack, and locate the object. Often the fetch code tries to avoid these kinds of re-scans if it's likely that we won't have the object. If the other side has told us about object X and we want to know if we have it, we'll skip the re-scan (to avoid spending a lot of effort when there are many such objects). We can accept the racy false negative in that case because the worst case is that we ask the other side to send us the object. But this is not one of those cases. These are objects which are accessible from _our_ refs, and which we already found in the commit graph file. We should have them, and if we don't, we'll die() immediately. So the performance impact is negligible, and getting the right answer is important. There's no test here because it's inherently racy. In fact, I had trouble even developing a minimal test. The problem seen in the wild can be produced like this: # Any git.git mirror which supports partial clones; I think this # should work with any repo that contains submodules, but note that # $obj below is specific to this repo url=https://github.com/git/git.git # This is a commit that is not at the tip of any branches (so after # we have it, we'll still have some commits to fetch). obj=cf6f63ea6bf35173e02e18bdc6a4ba41288acff9 git init git fetch --filter=tree:0 $url $obj:refs/heads/foo git checkout foo git commit-graph write --reachable git fetch $url What happens here is that the initial fetch grabs that older commit (and its ancestors) but no trees or blobs, and the subsequent checkout grabs the necessary trees and blobs just for that commit. The final fetch spawns a long sequence of child fetches due to fetch_submodules(), which wants to check whether there have been any gitlink modifications which should trigger a fetch of the related submodule (we'll leave aside the irony that we did not even check out any submodules yet). That series of fetches causes us to accumulate packs, which eventually triggers background maintenance to run. That repacks all-into-one, and the pack containing $obj goes away in favor of a new pack. And then the fetch eventually fails with: fatal: You are attempting to fetch cf6f63ea6bf35173e02e18bdc6a4ba41288acff9, which is in the commit graph file but not in the object database. In the scenario above, the race becomes likely because of the long series of quick fetches. But I _think_ the bug is independent of partial clones entirely, and you could run into the same thing with a single fetch, some other process running "git repack" simultaneously, and a bit of bad luck. I haven't been able to reproduce, though. I'm not sure if that's because there's some mis-analysis above, or if the race window is just small enough that it's hard to trigger. At any rate, re-scanning here seems like an obviously correct thing to do with no downside, and it does fix the partial-clone case shown above. Reported-by: Дилян Палаузов <dilyan.palauzov@aegee.org> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-25doc/format-patch: adjust Thunderbird MUA hint to new add-onJohannes Sixt1-3/+9
There are three tips how to compose a non-line-wrapped patch with Thunderbird. The first one suggests use of an add-on. The one referenced has long been superseded by a different one. Update the link to the new one. Mention that additional configuration is required to make the add-on work. Signed-off-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-25doc: clarify which remotes can be used with GitGitGadgetDaniele Sassoli1-4/+7
The docs mostly point to using git/git as one's remote, however, when it comes to Sending a PR to GitGitGadget section, the reader is told to use gitgitgadget/git, with no mention of git/git, potentially leading to some confusion. Clarify that both gitgitgadget/git and git/git can be used, albeit with some differences. Signed-off-by: Daniele Sassoli <danielesassoli@gmail.com> Acked-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-25path-walk: create initializer for path listsDerrick Stolee1-32/+25
The previous change fixed a bug in 'git repack -adf --path-walk' that was due to an update to how path lists are initialized and missing some important cases when processing the pending objects. This change takes the three critical places where path lists are initialized and combines them into a static method. This simplifies the callers somewhat while also helping to avoid a missed update in the future. The other places where a path list (struct type_and_oid_list) is initialized is for the following "fixed" lists: * Tag objects. * Commit objects. * Root trees. * Tagged trees. * Tagged blobs. These lists are created and consumed in different ways, with only the root trees being passed into the logic that cares about the "maybe_interesting" bit. It is appropriate to keep these uses separate. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-25path-walk: fix setup of pending objectsDerrick Stolee2-0/+65
Users reported an issue where objects were missing from their local repositories after a full repack using 'git repack -adf --path-walk'. This was alarming and took a while to create a reproducer. Here, we fix the bug and include a test case that would fail without this fix. The root cause is that certain objects existed in the index and had no second versions. These objects are usually blobs, though trees can be included if a cache-tree exists. The issue is that the revision walk adds these objects to the "pending" list and the path-walk API forgets to mark the lists it creates at this point as "maybe_interesting". If these paths only ever have a single version in the history of the repo (including the current staged version) then the parent directory never tries to add a new object to the list and mark the list as "maybe_interesting". Thus, when walking the list later, the group is skipped as it is expected that no objects are interesting. This happens even when there are actually no UNINTERESTING objects at all! This is based on the optimization enabled by the pack.useSparse=true config option, which is the default. Thus, we create a test case that demonstrates the many cases of this issue for reproducibility: 1. File a/b/c has only one committed version. 2. Files a/i and x/y only exist as staged changes. 3. Tree x/ only exists in the cache-tree. After performing a non-path-walk repack to force all loose objects into packfiles, run a --path-walk repack followed by 'git fsck'. This fsck is what fails with the following errors: error: invalid object 100644 f2e41136... for 'a/b/c' This is the dropped instance of the single-versioned a/b/c file. broken link from tree cfda31d8... to tree 3f725fcd... This is the missing tree for the single-versioned a/b/ directory. missing blob 0ddf2bae... (a/i) missing blob 975fbec8... (x/y) missing blob a60d869d... (file) missing blob f2e41136... (a/b/c) missing tree 3f725fcd... (a/b/) dangling tree 5896d7e... (staged root tree) Note that since the staged root tree is missing, the fsck output cannot even report that the staged x/ tree is missing as well. The core problem here is that the "maybe_interesting" member of 'struct type_and_oid_list' is not initialized to '1'. This member was added in 6333e7ae0b (path-walk: mark trees and blobs as UNINTERESTING, 2024-12-20) in a way to help when creating packfiles for a small commit range using the sparse path algorithm (enabled by pack.useSparse=true). The idea here is that the list is marked as "maybe_interesting" if an object is added that does not have the UNINTERESTING flag on it. Later, this is checked again in case all objects in the list were marked UNINTERESTING after that point in time. In this case, the algorithm skips the list as there is no reason to visit it. This leads to the problem where the "maybe_interesting" member was not appropriately initialized when the list is created from pending objects. Initializing this in the correct places fixes the bug. To reduce risk of similar bugs around initializing this structure, a follow-up change will make initializing lists use a shared method. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-22doc: interpret-trailers: close all pairs of single quotesKristoffer Haugsbakk1-4/+4
Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-21config: document includeIf conditions consistentlyJunio C Hamano1-5/+4
When 399b1984 (config: include file if remote URL matches a glob, 2022-01-18) added the 'hasconfig:remote.*.url:<URL>' condition to be used in the "includeIf.<condition>.path" configuration, the keyword was added with an extra colon in the documentation. The section that documents these condition begins with this preamble: The condition starts with a keyword followed by a colon and some data whose format and meaning depends on the keyword. Supported keywords are: which makes it clear that the colon that comes between the condition keyword (e.g. "gitdir") and the parameter (aka "some data") is not a part of the keyword. Lose the extra colon. Also rewrite description of all keywords to clarify that "some data" does not directly follow "keyword", and the colon is not a part of keyword. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-20doc: fix asciidoc format compatibility in pretty-formats.adocJean-Noël Avila1-2/+2
Asciidoc.py and Asciidoctor do not process the '+' verbatim the same way. A span is detected when the format sign (here '+')is preceded by a non-word character. It seems that '{nbsp}' is considered a non-word sign by Asciidoc.py, but not by Asciidoctor. Using a double format-sign opens 'unconstrained' span, independent on the preceding character in both engines. The '+' sign is used instead of the backtick '`' because it is not processed as synopsis in asciidoc.py. Unfortunately, the post-processing of verbatim synopsis in asciidoctor cannot be bypassed and formatting of the parentheses is forced in syntax sign instead of keywords, unless a proper grammar analyzer is used. Signed-off-by: Jean-Noël Avila <jn.avila@free.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-20line-log: show all line ranges touched by the same diff rangeSZEDER Gábor5-0/+33
When line-level log is invoked with more than one disjoint line range in the same file, and one of the commits happens to change that file such that one diff range modifies more than one line range, then changes to all modified line ranges should be shown, but only the changes in the first modified line range are: $ git log --oneline -p 80ca903 (HEAD -> master) Initial diff --git a/file b/file new file mode 100644 index 0000000..00935f1 --- /dev/null +++ b/file @@ -0,0 +1,10 @@ +Line 1 +Line 2 +Line 3 +Line 4 +Line 5 +Line 6 +Line 7 +Line 8 +Line 9 +Line 10 $ git log --oneline -L1,2:file -L4,5:file -L7,8:file 80ca903 (HEAD -> master) Initial diff --git a/file b/file --- /dev/null +++ b/file @@ -0,0 +1,2 @@ +Line 1 +Line 2 The line-log-specific diff printer is already clever enough to handle the case when one line range covers multiple diff ranges, but the possibility of one diff range touching multiple disjoint line ranges was apparently overlooked. Add the necessary condition to dump_diff_hacky_one() to handle this case as well, and show all modified line ranges: $ git log --oneline -L1,2:file -L4,5:file -L7,8:file 0f9a5b4 (HEAD -> master) Initial diff --git a/file b/file --- /dev/null +++ b/file @@ -0,0 +1,2 @@ +Line 1 +Line 2 @@ -0,0 +4,2 @@ +Line 4 +Line 5 @@ -0,0 +7,2 @@ +Line 7 +Line 8 This bug was already present in the initial line-log implementation added in 2da1d1f6f (Implement line-history search (git log -L), 2013-03-28). Interestingly, that commit already contained a canned test case covering a similar scenario: "-L '/long f/',/^}/:a.c -L /main/,/^}/:a.c simple" This test case looks for two line ranges in the same file, and both trace back disjointly to the test repository's inital commit, therefore changes to both line ranges should have been shown for the initial commit, but only changes for the first line range are shown. So this test case should have failed from the very beginning, but it never did, because, unfortunately, the canned expected result is incorrect, as it doesn't include changes for the second line range. A similar test with a similarly incorrect canned expected result was added later in 209618860c (log -L: fix overlapping input ranges, 2013-04-05). Correct these two canned expected results to contain the changes for the second line range for the initial commit as well. Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-20line-log: fix assertion errorSZEDER Gábor4-3/+185
When line-level log is invoked with more than one disjoint line range in the same file, and one of the commits happens to change that file such that: - the last line of a line range R(n) immediately preceeds the first line modified or added by a hunk H, and - subtracting the number of lines added by hunk H from the start and end of the subsequent line range R(n+1) would result in a range overlapping with line range R(n), then git aborts with an assertion error, because those overlapping line ranges violate the invariants: $ git log --oneline -p 73e4e2f (HEAD -> master) Add lines 6 7 8 9 10 diff --git a/file b/file index 572d5d9..00935f1 100644 --- a/file +++ b/file @@ -3,3 +3,8 @@ Line 2 Line 3 Line 4 Line 5 +Line 6 +Line 7 +Line 8 +Line 9 +Line 10 66e3561 Add lines 1 2 3 4 5 diff --git a/file b/file new file mode 100644 index 0000000..572d5d9 --- /dev/null +++ b/file @@ -0,0 +1,5 @@ +Line 1 +Line 2 +Line 3 +Line 4 +Line 5 $ git log --oneline -L3,5:file -L7,8:file git: line-log.c:73: range_set_append: Assertion `rs->nr == 0 || rs->ranges[rs->nr-1].end <= a' failed. Aborted (core dumped) The line-log machinery encodes line and diff ranges internally as [start, end) pairs, i.e. include 'start' but exclude 'end', and line numbering starts at 0 (as opposed to the -LX,Y option, where it starts at 1, IOW the parameter -L3,5 is represented internally as { start = 2, end = 5 }). The reason for this assertion error and some related issues is that there are a couple of places where 'end' is mistakenly considered to be part of the range: - When a commit modifies an interesting path, the line-log machinery first checks which diff range (i.e. hunk) modify any line ranges. This is done in diff_ranges_filter_touched(), where the outer loop iterates over the diff ranges, and in each iteration the inner loop advances the line ranges supposedly until the current line range ends at or after the current diff range starts, and then the current diff and line ranges are checked for overlap. For HEAD in the above example the first line range [2, 5) ends just before the diff range [5, 10) starts, so the inner loop should advance, and then the second line range [6, 8) and the diff range should be checked for overlap. Unfortunately, the condition of the inner loop mistakenly considers 'end' as part of the line range, and, seeing the diff range starting at 5 and the line range ending at 5, it doesn't skip the first range. Consequently, the diff range and the first line range are checked for overlap, and after that the outer loop runs out of diff ranges, and then the processing goes on in the false belief that this commit didn't touch any of the interesting line ranges. The line-log machinery later shifts the line ranges to account for any added/removed lines in the diff ranges preceeding each line range. This leaves the first line range intact, but attempts to shift the second line range [6, 8) by 5 lines towards the beginning of the file, resulting in [1, 3), triggering the assertion error, because the two overlapping line ranges violate the invariants. Fix that loop condition in diff_ranges_filter_touched() to not treat 'end' as part of the line range. - With the above fix the assertion error is gone... but, alas, we now get stuck in an endless loop! This happens in range_set_difference(), where a couple of nested loops iterate over the line and diff ranges, and a condition is supposed to break the middle loop when the current line range ends before the current diff range, so processing could continue with the next line range. For HEAD in the above example the first line range [2, 5) ends just before the diff range [5, 10) starts, so this condition should trigger and break the middle loop. Unfortunately, just like in the case of the assertion error, this conditions mistakenly considers 'end' as part of the line range, and, seeing the line range ending at 5 and the diff range starting at 5, it doesn't break the loop, which will then go on and on. Fix this condition in range_set_difference() to not treat 'end' as part of the line range. - With the above fix the endless loop is gone... but, alas, the output is now wrong, as it shows both line ranges for HEAD, even though the first line range is not modified by that commit: $ git log --oneline -L3,5:file -L7,8:file 73e4e2f (HEAD -> master) Add lines 6 7 8 9 10 diff --git a/file b/file --- a/file +++ b/file @@ -3,3 +3,3 @@ Line 3 Line 4 Line 5 @@ -6,0 +7,2 @@ +Line 7 +Line 8 66e3561 Add lines 1 2 3 4 5 diff --git a/file b/file --- /dev/null +++ b/file @@ -0,0 +3,3 @@ +Line 3 +Line 4 +Line 5 In dump_diff_hacky_one() a couple of nested loops are responsible for finding and printing the modified line ranges: the big outer loop iterates over all line ranges, and the first inner loop skips over the diff ranges that end before the start of the current line range. This is followed by a condition checking whether the current diff range starts after the end of the current line range, which, when fulfilled, continues and advances the outer loop to the next line range. For HEAD in the above example the first line range [2, 5) ends just before the diff range [5, 10), so this condition should trigger, and the outer loop should advance to the second line range. Unfortunately, just like in the previous cases, this condition mistakenly considers 'end' as part of the line range, and, seeing the first line range ending at 5 and the diff range starting at 5, it doesn't continue to advance the outher loop, but goes on to show the (unmodified) first line range. Fix this condition to not treat 'end' as part of the line range, just like in the previous cases. After all this the command in the above example finally finishes and produces the right output: $ git log --oneline -L3,5:file -L7,8:file 73e4e2f (HEAD -> master) Add lines 6 7 8 9 10 diff --git a/file b/file --- a/file +++ b/file @@ -6,0 +7,2 @@ +Line 7 +Line 8 66e3561 Add lines 1 2 3 4 5 diff --git a/file b/file --- /dev/null +++ b/file @@ -0,0 +3,3 @@ +Line 3 +Line 4 +Line 5 Add a canned test similar to the above example, with the line ranges adjusted to the test repository's history. Reported-by: Evgeni Chasnovski <evgeni.chasnovski@gmail.com> Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-20doc/gitk: update reference to the external projectJohannes Sixt1-4/+4
Gitk is now maintained by Johannes Sixt and the repository can be cloned from a new URL. b59358100c20 (Update the official repo of gitk, 2024-12-24) could have updated this instance in the manual, too, but the opportunity was missed. Update it now. Do give credit to Paul Mackerras as the inventor of the program. Signed-off-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-17Git 2.51v2.51.0Junio C Hamano1-1/+1
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-17Merge tag 'l10n-2.51.0-2' of https://github.com/git-l10n/git-poJunio C Hamano10-4029/+6223
l10n-2.51.0-2 * tag 'l10n-2.51.0-2' of https://github.com/git-l10n/git-po: l10n: Update Catalan Translation for Git 2.51-rc2 l10n: zh_CN: updated translation for 2.51 l10n: uk: add 2.51 translation l10n: zh_TW: Git 2.51 l10n: po-id for 2.51 l10n: fr translation update for v2.51.0 l10n: tr: Update Turkish translations for 2.51.0 l10n: Updated translation for vi-2.51 l10n: sv.po: Update Swedish translation l10n: bg.po: Updated Bulgarian translation (5856t)
2025-08-17cmake: accommodate for `UNIT_TEST_SOURCES`Johannes Schindelin1-1/+3
As part of 9bbc981c6f2 (t/unit-tests: finalize migration of reftable-related tests, 2025-07-24), the explicit list of `UNIT_TEST_PROGRAMS` was turned into a wildcard pattern-derived list. Let's do the same in the CMake definition. This fixes build errors with symptoms like this: CMake Error at CMakeLists.txt:132 (string): string sub-command REPLACE requires at least four arguments. Call Stack (most recent call first): CMakeLists.txt:1037 (parse_makefile_for_scripts) Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-17l10n: Update Catalan Translation for Git 2.51-rc2Mikel Forcada1-993/+1803
Edit: We are continuing to follow the existing PO file convention, which includes filenames but strips out line numbers from the file-location comments. This standard was set by our former lead, Jordi Mas, and we are maintaining it for project-wide consistency. Signed-off-by: Mikel Forcada <mikel.forcada@gmail.com> Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
2025-08-17Merge branch 'jx/zh_CN-2.51' of github.com:jiangxin/gitJiang Xin1-248/+444
* 'jx/zh_CN-2.51' of github.com:jiangxin/git: l10n: zh_CN: updated translation for 2.51
2025-08-17l10n: zh_CN: updated translation for 2.51Teng Long1-248/+444
Signed-off-by: Teng Long <dyroneteng@gmail.com> Reviewed-by: Fangyi Zhou <me@fangyi.io> Reviewed-by: 依云 <lilydjwg@gmail.com> Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
2025-08-17Merge branch '2.51-uk-update' of github.com:arkid15r/git-ukrainian-l10nJiang Xin1-181/+347
* '2.51-uk-update' of github.com:arkid15r/git-ukrainian-l10n: l10n: uk: add 2.51 translation
2025-08-16l10n: uk: add 2.51 translationArkadii Yakovets1-181/+347
Co-authored-by: Kate Golovanova <kate@kgthreads.com> Signed-off-by: Arkadii Yakovets <ark@cho.red> Signed-off-by: Kate Golovanova <kate@kgthreads.com>
2025-08-16Merge branch 'fr_v2.51.0' of github.com:jnavila/gitJiang Xin1-463/+345
* 'fr_v2.51.0' of github.com:jnavila/git: l10n: fr translation update for v2.51.0
2025-08-16Merge branch 'po-id' of github.com:bagasme/git-poJiang Xin1-235/+431
* 'po-id' of github.com:bagasme/git-po: l10n: po-id for 2.51
2025-08-16Merge branch 'tr-l10n' of github.com:bitigchi/git-poJiang Xin1-173/+332
* 'tr-l10n' of github.com:bitigchi/git-po: l10n: tr: Update Turkish translations for 2.51.0
2025-08-16Merge branch 'l10n/zh-TW/2025-08-08' of github.com:l10n-tw/git-poJiang Xin1-393/+617
* 'l10n/zh-TW/2025-08-08' of github.com:l10n-tw/git-po: l10n: zh_TW: Git 2.51
2025-08-16Merge branch 'master' of github.com:alshopov/git-poJiang Xin1-210/+387
* 'master' of github.com:alshopov/git-po: l10n: bg.po: Updated Bulgarian translation (5856t)
2025-08-16Merge branch 'master' of github.com:nafmo/git-l10n-svJiang Xin1-524/+560
* 'master' of github.com:nafmo/git-l10n-sv: l10n: sv.po: Update Swedish translation
2025-08-16Merge branch 'vi-2.51' of github.com:Nekosha/git-poJiang Xin1-609/+957
* 'vi-2.51' of github.com:Nekosha/git-po: l10n: Updated translation for vi-2.51