summaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorFilesLines
2026-02-23config: format bools or strings in helperDerrick Stolee1-7/+15
Move the logic for formatting bool-or-string config values into a helper. This parsing has always been gentle, so this is not unlocking new behavior. This extraction is only to match the formatting of the other cases that do need a behavior change. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23config: format bools or ints gentlyDerrick Stolee2-10/+34
Move the logic for formatting bool-or-int config values into a helper method and use gentle parsing when needed. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23config: format bools gentlyDerrick Stolee2-3/+22
Move the logic for formatting bool config values into a helper method and use gentle parsing when needed. This makes 'git config list --type=bool' not fail when coming across a non-boolean value. Such unparseable values are filtered out quietly. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23config: format int64s gentlyDerrick Stolee2-5/+26
Move the logic for formatting int64 config values into a helper method and use gentle parsing when needed. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23config: make 'git config list --type=<X>' workDerrick Stolee3-16/+119
Previously, the --type=<X> argument to 'git config list' was ignored and did nothing. Now, we add the use of format_config() to the show_all_config() function so each key-value pair is attempted to be parsed. This is our first use of the 'gently' parameter with a nonzero value. When listing multiple values, our initial settings for the output format is different. Add a new init helper to specify the fact that keys should be shown and also add the default delimiters as they were unset in some cases. Our intention is that if there is an error in parsing, then the row is not output. This is necessary to avoid the caller needing to build their own validator to understand the difference between valid, canonicalized types and other raw string values. The raw values will always be available to the user if they do not specify the --type=<X> option. The current behavior is more complicated, including error messages on bad parsing or potentially complete failure of the command. We add tests at this point that demonstrate the current behavior so we can witness the fix in future changes that parse these values quietly and gently. This is a change in behavior! We are starting to respect an option that was previously ignored, leading to potential user confusion. This is probably still a good option, since the --type argument did not change behavior at all previously, so users can get the behavior they expect by removing the --type argument or adding the --no-type argument. t1300-config.sh is updated with the current behavior of this formatting logic to justify the upcoming refactoring of format_config() that will incrementally fix some of these cases to be more user-friendly. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23config: add 'gently' parameter to format_config()Derrick Stolee1-4/+8
This parameter is set to 0 for all current callers and is UNUSED. However, we will start using this option in future changes and in a critical change that requires gentle parsing (not using die()) to try parsing all values in a list. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23config: move show_all_config()Derrick Stolee1-24/+24
In anticipation of using format_config() in this method, move show_all_config() lower in the file without changes. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: replace `refs_for_each_fullref_in()`Patrick Steinhardt8-46/+37
Replace calls to `refs_for_each_fullref_in()` with the newly introduced `refs_for_each_ref_ext()` function. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: replace `refs_for_each_namespaced_ref()`Patrick Steinhardt4-25/+13
Replace calls to `refs_for_each_namespaced_ref()` with the newly introduced `refs_for_each_ref_ext()` function. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: replace `refs_for_each_glob_ref()`Patrick Steinhardt5-19/+15
Replace calls to `refs_for_each_glob_ref()` with the newly introduced `refs_for_each_ref_ext()` function. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: replace `refs_for_each_glob_ref_in()`Patrick Steinhardt5-36/+55
Replace calls to `refs_for_each_glob_ref_in()` with the newly introduced `refs_for_each_ref_ext()` function. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: replace `refs_for_each_rawref_in()`Patrick Steinhardt3-16/+6
Replace calls to `refs_for_each_rawref_in()` with the newly introduced `refs_for_each_ref_ext()` function. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: replace `refs_for_each_rawref()`Patrick Steinhardt6-17/+30
Replace calls to `refs_for_each_rawref()` with the newly introduced `refs_for_each_ref_ext()` function. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: replace `refs_for_each_ref_in()`Patrick Steinhardt6-32/+45
Replace calls to `refs_for_each_ref_in()` with the newly introduced `refs_for_each_ref_ext()` function. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: improve verification for-each-ref optionsPatrick Steinhardt1-1/+12
Improve verification of the passed-in for-each-ref options: - Require that the `refs` store must be given. It's arguably very surprising that we simply return successfully in case the ref store is a `NULL` pointer. - When expected to trim ref prefixes we will `BUG()` in case the refname would become empty or in case we're expected to trim a longer prefix than the refname is long. As such, this case is only guaranteed to _not_ `BUG()` in case the caller also specified a prefix. And furthermore, that prefix must end in a trailing slash, as otherwise it may produce an exact match that could lead us to trim to the empty string. An audit shows that there are no callsites that rely on either of these behaviours, so this should not result in a functional change. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: generalize `refs_for_each_fullref_in_prefixes()`Patrick Steinhardt4-43/+34
The function `refs_for_each_fullref_in_prefixes()` can be used to iterate over all references part of any of the user-provided prefixes. In contrast to the `prefix` parameter of `refs_for_each_ref_ext()` it knows to handle the case well where multiple of the passed-in prefixes start with a common prefix by computing longest common prefixes and then iterating over those. While we could move this logic into `refs_for_each_ref_ext()`, this one feels somewhat special as we perform multiple iterations. But what we _can_ do is to generalize how this function works: instead of accepting only a small handful of parameters, we can have it accept the full options structure. One obvious exception is that the caller must not provide a prefix via the options. But this case can be easily detected. Refactor the code accordingly. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: generalize `refs_for_each_namespaced_ref()`Patrick Steinhardt2-18/+36
The function `refs_for_each_namespaced_ref()` iterates through all references that are part of the current ref namespace. This namespace can be configured by setting the `GIT_NAMESPACE` environment variable and is then retrieved by calling `get_git_namespace()`. If a namespace is configured, then we: - Obviously only yield refs that exist in this namespace. - Rewrite exclude patterns so that they work for the given namespace, if any namespace is currently configured. Port this logic to `refs_for_each_ref_ext()` by adding a new `namespace` field to the options structure. This gives callers more flexibility as they can decide by themselves whether they want to use the globally configured or an arbitrary other namespace. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: speed up `refs_for_each_glob_ref_in()`Patrick Steinhardt2-33/+64
The function `refs_for_each_glob_ref_in()` can be used to iterate through all refs in a specific prefix with globbing. The logic to handle this is currently hosted by `refs_for_each_glob_ref_in()`, which sets up a callback function that knows to filter out refs that _don't_ match the given globbing pattern. The way we do this is somewhat inefficient though: even though the function is expected to only yield refs in the given prefix, we still end up iterating through _all_ references, regardless of whether or not their name matches the given prefix. Extend `refs_for_each_ref_ext()` so that it can handle patterns and adapt `refs_for_each_glob_ref_in()` to use it. This means we continue to use the same callback-based infrastructure to filter individual refs via the globbing pattern, but we can now also use the other functionality of the `_ext()` variant. Most importantly, this means that we now properly handle the prefix. This results in a performance improvement when using a prefix where a significant majority of refs exists outside of the prefix. The following benchmark is an extreme case, with 1 million refs that exist outside the prefix and a single ref that exists inside it: Benchmark 1: git rev-parse --branches=refs/heads/* (rev = HEAD~) Time (mean ± σ): 115.9 ms ± 0.7 ms [User: 113.0 ms, System: 2.4 ms] Range (min … max): 114.9 ms … 117.8 ms 25 runs Benchmark 2: git rev-parse --branches=refs/heads/* (rev = HEAD) Time (mean ± σ): 1.1 ms ± 0.1 ms [User: 0.3 ms, System: 0.7 ms] Range (min … max): 1.0 ms … 2.3 ms 2092 runs Summary git rev-parse --branches=refs/heads/* (rev = HEAD) ran 107.01 ± 6.49 times faster than git rev-parse --branches=refs/heads/* (rev = HEAD~) Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: introduce `refs_for_each_ref_ext`Patrick Steinhardt2-30/+77
In the refs subsystem we have a proliferation of functions that all iterate through references. (Almost) all of these functions internally call `do_for_each_ref()` and provide slightly different arguments so that one can control different aspects of its behaviour. This approach doesn't really scale: every time there is a slightly different use case for iterating through refs we create another new function. This combinatorial explosion doesn't make a lot of sense: it leads to confusing interfaces and heightens the maintenance burden. Refactor the code to become more composable by: - Exposing `do_for_each_ref()` as `refs_for_each_ref_ext()`. - Introducing an options structure that lets the caller control individual options. This gives us a much better foundation to build on going forward. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: rename `each_ref_fn`Patrick Steinhardt11-50/+50
Similar to the preceding commit, rename `each_ref_fn` to better match our current best practices around how we name things. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: rename `do_for_each_ref_flags`Patrick Steinhardt6-31/+31
The enum `do_for_each_ref_flags` and its individual values don't match to our current best practices when it comes to naming things. Rename it to `refs_for_each_flag`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: move `do_for_each_ref_flags` further upPatrick Steinhardt1-37/+37
Move the `do_for_each_ref_flags` enum further up. This prepares for subsequent changes, where the flags will be used by more functions. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: move `refs_head_ref_namespaced()`Patrick Steinhardt1-2/+3
The function `refs_head_ref_namespaced()` is somewhat special when compared to most of the other functions that take a callback function: while `refs_for_each_*()` functions yield multiple refs, `refs_heasd_ref_namespaced()` will only yield at most the HEAD ref of the current namespace. As such, the function is related to `refs_head_ref()` and not to the for-each functions. Move the function to be located next to `refs_head_ref()` to clarify. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23refs: remove unused `refs_for_each_include_root_ref()`Patrick Steinhardt2-13/+0
Remove the unused `refs_for_each_include_root_ref()` function. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23pack-check: fix verification of large objectsPatrick Steinhardt2-1/+39
It was reported [1] that git-fsck(1) may sometimes run into an infinite loop when processing packfiles. This bug was bisected to c31bad4f7d (packfile: track packs via the MRU list exclusively, 2025-10-30), which refactored our lsit of packfiles to only be tracked via an MRU list, exclusively. This isn't entirely surprising: any caller that iterates through the list of packfiles and then hits `find_pack_entry()`, for example because they read an object from it, may cause the MRU list to be updated. And if the caller is unlucky, this may cause the mentioned infinite loop. While this mechanism is somewhat fragile, it is still surprising that we encounter it when verifying the packfile. We iterate through objects in a given pack one by one and then read them via their offset, and doing this shouldn't ever end up in `find_pack_entry()`. But there is an edge case here: when the object in question is a blob bigger than "core.largeFileThreshold", then we will be careful to not read it into memory. Instead, we read it via an object stream by calling `odb_read_object_stream()`, and that function will perform an object lookup via `odb_read_object_info()`. So in the case where there are at least two blobs in two different packfiles, and both of these blobs exceed "core.largeFileThreshold", then we'll run into an infinite loop because we'll always update the MRU. We could fix this by improving `repo_for_each_pack()` to not update the MRU, and this would address the issue. But the fun part is that using `odb_read_object_stream()` is the wrong thing to do in the first place: it may open _any_ instance of this object, so we ultimately cannot be sure that we even verified the object in our given packfile. Fix this bug by creating the object stream for the packed object directly via `packfile_read_object_stream()`. Add a test that would have caused the infinite loop. [1]: <20260222183710.2963424-1-sandals@crustytoothpaste.net> Reported-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23packfile: expose function to read object stream for an offsetPatrick Steinhardt2-16/+29
The function `packfile_store_read_object_stream()` takes as input an object ID and then constructs a `struct odb_read_stream` from it. In a subsequent commit we'll want to create an object stream for a given combination of packfile and offset though, which is not something that can currently be done. Extract a new function `packfile_read_object_stream()` that makes this functionality available. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23object-file: adapt `stream_object_signature()` to take a streamPatrick Steinhardt4-14/+31
The function `stream_object_signature()` is responsible for verifying whether the given object ID matches the actual hash of the object's contents. In contrast to `check_object_signature()` it does so in a streaming fashion so that we don't have to load the full object into memory. In a subsequent commit we'll want to adapt one of its callsites to pass a preconstructed stream. Prepare for this by accepting a stream as input that the caller needs to assemble. While at it, improve the error reporting in `parse_object_with_flags()` to tell apart the two failure modes. Helped-by: Jeff King <peff@peff.net> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-23t/helper: improve "genrandom" test helperPatrick Steinhardt8-13/+16
The `test-tool genrandom` test helper can be used to generate random data, either as an infinite stream or with a specified number of bytes. The way we handle parsing the number of bytes is lacking though: - We don't have good error handling, so if the caller for example uses `test-tool genrandom 200xyz` then we'll end up generating 200 bytes of random data successfully. - Many callers want to generate e.g. 1 kilobyte or megabyte of data, but they have to either use unwieldy numbers like 1048576, or they have to precompute them. Fix both of these issues by using `git_parse_ulong()` to parse the argument. This function has better error handling, and it knows to handle unit suffixes. Adapt a couple of our tests to use suffixes instead of manual computations. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-22object-file.c: avoid container_of() of a NULL containerJunio C Hamano1-2/+2
Even though the "struct odb_transaction" member is at the beginning of the containing "struct odb_transaction_files", i.e., at offset 0, using container_of() to add offset 0 to a NULL pointer gets flagged as a bad behaviour under SANITIZE=undefined. Use container_of_or_null() to work around this issue. Helped-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-21pack-redundant: fix memory leak when open_pack_index() failsSahitya Chandra1-1/+3
In add_pack(), we allocate l.remaining_objects with llist_init() before calling open_pack_index(). If open_pack_index() fails we return NULL without freeing the allocated list, leaking the memory. Fix by calling llist_free(l.remaining_objects) on the error path before returning. Signed-off-by: Sahitya Chandra <sahityajb@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-21path: factor out skip_slashes() in normalize_path_copy_len()Pushkar Singh1-6/+13
Extract skip_slashes() to avoid repeating the same is_dir_sep() loop in multiple places inside normalize_path_copy_len(). Keep the dot-component handling inline to preserve the original control flow and readability, as suggested in review. No functional changes. Behavior verified with t0060-path-utils.sh. Signed-off-by: Pushkar Singh <pushkarkumarsingh1970@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-21t2004: use test_path_is_file instead of test -fLambert Duclos-de Guise1-21/+21
Replace 'test -f' with the helper function 'test_path_is_file' to provide better error messages upon failure. Signed-off-by: Lambert Duclos-de Guise <lambertddg@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-21replay: prevent the_repository from coming backElijah Newren1-0/+6
Due to the use of DEFAULT_ABBREV, we cannot get rid of our usage of USE_THE_REPOSITORY_VARIABLE. We have removed all other uses of the_repository before, but without removing that definition, they keep coming back. Define the_repository to make it a compilation error so that they don't come back any more; the repo parameter plumbed through the various functions can be used instead. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-21merge-ort: prevent the_repository from coming backElijah Newren1-0/+8
Due to the use of DEFAULT_ABBREV, we cannot get rid of our usage of USE_THE_REPOSITORY_VARIABLE. However, we have removed all other uses of the_repository in merge-ort a few times. But they keep coming back. Define the_repository to make it a compilation error so that they don't come back any more. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-21merge-ort: replace the_hash_algo with opt->repo->hash_algoElijah Newren1-13/+13
We have a perfectly valid repository available and do not need to use the_hash_algo (a shorthand for the_repository->hash_algo), so use the known repository instead. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-21merge-ort: replace the_repository with opt->repoElijah Newren1-21/+21
We have a perfectly valid repository available and do not need to use the_repository. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-21merge-ort: pass repository to write_tree()Elijah Newren1-8/+8
In order to get rid of a usage of the_repository, we need to know the value of opt->repo; pass it along to write_tree(). Once we have the repository, though, we no longer need to pass opt->repo->hash_algo->rawsz, we can have write_tree() look up that value itself. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-21merge,diff: remove the_repository check before prefetching blobsElijah Newren4-5/+5
Prefetching of blobs from promisor remotes was added to diff in 7fbbcb21b162 (diff: batch fetching of missing blobs, 2019-04-05). In that commit, https://lore.kernel.org/git/20190405170934.20441-1-jonathantanmy@google.com/ was squashed into https://lore.kernel.org/git/44de02e584f449481e6fb00cf35d74adf0192e9d.1553895166.git.jonathantanmy@google.com/ without the extra explanation about the squashed changes being added to the commit message; in particular, this explanation from that first link is absent: > Also, prefetch only if the repository being diffed is the_repository > (because we do not support lazy fetching for any other repository > anyway). Then, later, this checking was spread from diff.c to diffcore-rename.c and diffcore-break.c by 95acf11a3dc3 (diff: restrict when prefetching occurs, 2020-04-07) and then further split in d331dd3b0c82 (diffcore-rename: allow different missing_object_cb functions, 2021-06-22). I also copied the logic from prefetching blobs from diff.c to merge-ort.c in 2bff554b23e8 (merge-ort: add prefetching for content merges, 2021-06-22). The reason for all these checks was noted above -- we only supported lazy fetching for the_repository. However, that changed with ef830cc43412 (promisor-remote: teach lazy-fetch in any repo, 2021-06-17), so these checks are now unnecessary. Remove them. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-20symlinks: use unsigned int for flagsTian Yuchen2-8/+9
The 'flags' and 'track_flags' fields in symlinks.c are used strictly as a collection of bits (using bitwise operators including &, |, ~). Using a signed integer for bitmasks may lead to undefined behavior with shift operations and logic errors if the MSB is touched. Change these fields from 'int' to 'unsigned int' to match our usage patterns. Signed-off-by: Tian Yuchen <a3205153416@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-20The 6th batchJunio C Hamano1-0/+7
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-20Merge branch 'ak/t9812-test-path-is-helpers'Junio C Hamano1-4/+4
Test update. * ak/t9812-test-path-is-helpers: t9812: modernize test path helpers
2026-02-20Merge branch 'pw/diff-anchored-optim'Junio C Hamano1-12/+6
"git diff --anchored=<text>" has been optimized. * pw/diff-anchored-optim: diff --anchored: avoid checking unmatched lines
2026-02-20Merge branch 'jc/doc-cg-c-comment'Junio C Hamano1-0/+2
A CodingGuidelines update. * jc/doc-cg-c-comment: CodingGuidelines: document // comments
2026-02-20Merge branch 'pw/xdiff-cleanups'Junio C Hamano2-9/+12
Small clean-up of xdiff library to remove unnecessary data duplication. * pw/xdiff-cleanups: xdiff: remove unused data from xdlclass_t xdiff: remove "line_hash" field from xrecord_t
2026-02-20tree-diff: remove the usage of the_hash_algo globalShreyansh Paliwal1-4/+2
emit_path() uses the global the_hash_algo even though a local repository is already available via struct diff_options *opt. Replace these uses with opt->repo->hash_algo. With no remaining reliance on global states in this file, drop the dependency on 'environment.h' and remove '#define USE_THE_REPOSITORY_VARIABLE'. This follows earlier cleanups to introduce opt->repo in tree-diff.c [1][2]. [1]- https://lore.kernel.org/git/20180921155739.14407-21-pclouds@gmail.com/ [2]- https://lore.kernel.org/git/20260109213021.2546-2-l.s.r@web.de/ Signed-off-by: Shreyansh Paliwal <shreyanshpaliwalcmsmn@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-20contrib/subtree: process out-of-prefix subtreesColin Stagner2-53/+65
`should_ignore_subtree_split_commit` detects subtrees which are outside of the current path --prefix and ignores them. This can speed up splits of repositories that have many subtrees. Since its inception [1], every iteration of this logic [2], [3] incorrectly excludes commits. This alters the split history. The split history and its commit hashes are API contract, so this is not permissible. While a commit from a different subtree may look like it doesn't contribute anything to a split, sometimes it does. Merge commits are a particular hot spot. For these, the pruning logic in `copy_or_skip` performs: 1. a check for "treesame" parents 2. two different common ancestry checks These checks operate on the **split history**, not the input history. The split history omits commits that do not affect the --prefix. This can significantly alter the ancestry of a merge. In order to determine if `copy_or_skip` will skip a merge, it is likely necessary to compute all the split history... which is what `should_ignore_subtree_split_commit` tries to avoid. To make this logic API-preserving, we could gate it behind a new CLI argument. The present implementation is actually a speed penalty in many cases, however, so this is not done here. Remove the `should_ignore_subtree_split_commit` logic. This fixes the regression reported in [4]. [1]: 98ba49ccc2 (subtree: fix split processing with multiple subtrees present, 2023-12-01) [2]: 83f9dad7d6 (contrib/subtree: fix split with squashed subtrees, 2025-09-09) [3]: 28a7e27cff (contrib/subtree: detect rewritten subtree commits, 2026-01-09) [4]: <20251230170719.845029-1-george@mail.dietrich.pub> Reported-by: George <george@mail.dietrich.pub> Reported-by: Christian Heusel <christian@heusel.eu> Signed-off-by: Colin Stagner <ask+git@howdoi.land> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-20contrib/subtree: test history depthColin Stagner1-6/+16
Add history depth checks to some of the subtree unit tests. These checks were previously introduced as part of 28a7e27cff (contrib/subtree: detect rewritten subtree commits, 2026-01-09), which has since been reverted. Signed-off-by: Colin Stagner <ask+git@howdoi.land> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-20contrib/subtree: capture additional test-casesColin Stagner1-0/+110
Patch series e7b07376e5 (Merge branch 'rs/subtree-fixes', 2018-10-26) corrects several defects in `git subtree split`. The defects affect `split --rejoin` and merge commit processing. There is no test coverage for this, and e7b07376e5 did not introduce any. Convert the minimum working example [1] from the original patch submission [2] into test cases. [1]: https://gist.github.com/FoxFireX/1b794384612b7fd5e7cd157cff96269e [2]: <20180928183540.48968-1-roger.strain@swri.org> Signed-off-by: Colin Stagner <ask+git@howdoi.land> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-20apply: normalize path in --directory argumentJoaquim Rocha2-0/+45
When passing a relative path like --directory=./some/sub, the leading "./" caused apply to prepend it literally to patch filenames, resulting in an error (invalid path). There may be more cases like this where users pass some/./path to the directory which can easily be normalized to an acceptable path, so these changes try to normalize the path before using it. Signed-off-by: Joaquim Rocha <joaquim@amutable.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-02-20Merge branch 'ps/for-each-ref-in-fixes' into ps/refs-for-eachJunio C Hamano8-43/+137
* ps/for-each-ref-in-fixes: bisect: simplify string_list memory handling bisect: fix misuse of `refs_for_each_ref_in()` pack-bitmap: fix bug with exact ref match in "pack.preferBitmapTips" pack-bitmap: deduplicate logic to iterate over preferred bitmap tips