aboutsummaryrefslogtreecommitdiff
path: root/contrib/subtree/git-subtree.sh
diff options
context:
space:
mode:
authorColin Stagner <ask+git@howdoi.land>2026-02-17 20:31:32 -0600
committerJunio C Hamano <gitster@pobox.com>2026-02-20 10:15:31 -0800
commit1f70684b517f4fcfeb7b998b0b7f3146ee8a8c75 (patch)
treede5b1c0ed17a2c88131896b0392cd36d6190561c /contrib/subtree/git-subtree.sh
parent715b406e47d51a6f4f6be3b0ed42cfbd59217258 (diff)
downloadgit-1f70684b517f4fcfeb7b998b0b7f3146ee8a8c75.tar.xz
contrib/subtree: process out-of-prefix subtrees
`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>
Diffstat (limited to 'contrib/subtree/git-subtree.sh')
-rwxr-xr-xcontrib/subtree/git-subtree.sh50
1 files changed, 1 insertions, 49 deletions
diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
index 17106d1a72..ba9fb2ee5d 100755
--- a/contrib/subtree/git-subtree.sh
+++ b/contrib/subtree/git-subtree.sh
@@ -785,42 +785,6 @@ ensure_valid_ref_format () {
die "fatal: '$1' does not look like a ref"
}
-# Usage: should_ignore_subtree_split_commit REV
-#
-# Check if REV is a commit from another subtree and should be
-# ignored from processing for splits
-should_ignore_subtree_split_commit () {
- assert test $# = 1
-
- git show \
- --no-patch \
- --no-show-signature \
- --format='%(trailers:key=git-subtree-dir,key=git-subtree-mainline)' \
- "$1" |
- (
- have_mainline=
- subtree_dir=
-
- while read -r trailer val
- do
- case "$trailer" in
- git-subtree-dir:)
- subtree_dir="${val%/}" ;;
- git-subtree-mainline:)
- have_mainline=y ;;
- esac
- done
-
- if test -n "${subtree_dir}" &&
- test -z "${have_mainline}" &&
- test "${subtree_dir}" != "$arg_prefix"
- then
- return 0
- fi
- return 1
- )
-}
-
# Usage: process_split_commit REV PARENTS
process_split_commit () {
assert test $# = 2
@@ -1006,19 +970,7 @@ cmd_split () {
eval "$grl" |
while read rev parents
do
- if should_ignore_subtree_split_commit "$rev"
- then
- continue
- fi
- parsedparents=''
- for parent in $parents
- do
- if ! should_ignore_subtree_split_commit "$parent"
- then
- parsedparents="$parsedparents$parent "
- fi
- done
- process_split_commit "$rev" "$parsedparents"
+ process_split_commit "$rev" "$parents"
done || exit $?
latest_new=$(cache_get latest_new) || exit $?