Skip to content

Commit ab689ea

Browse files
committed
Revert "Merge branch 'cs/rebased-subtree-split'"
This reverts commit 79e3055, reversing changes made to 9813aac. Regresison report https://lore.kernel.org/git/755578cb-07e0-4b40-aa90-aacf4d45ccaa@heusel.eu/
1 parent 6959eee commit ab689ea

File tree

2 files changed

+55
-169
lines changed

2 files changed

+55
-169
lines changed

contrib/subtree/git-subtree.sh

Lines changed: 49 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -325,12 +325,6 @@ check_parents () {
325325
done
326326
}
327327

328-
# Usage: get_notree REV
329-
get_notree () {
330-
assert test $# = 1
331-
test -r "$cachedir/notree/$1"
332-
}
333-
334328
# Usage: set_notree REV
335329
set_notree () {
336330
assert test $# = 1
@@ -517,71 +511,6 @@ find_existing_splits () {
517511
done || exit $?
518512
}
519513

520-
# Usage: find_other_splits DIR REV UNREVS...
521-
#
522-
# Scan history in REV UNREVS for other `git subtree split --rejoin`
523-
# merge commits belonging to prefixes outside of DIR. These
524-
# "other splits" don't contribute to DIR and can be ignored.
525-
#
526-
# If any such rejoins are found,
527-
#
528-
# * emit their second-parent as an UNREV, avoiding a
529-
# potentially costly history traversal
530-
#
531-
# * mark the merge commit as "notree" to ignore it
532-
find_other_splits () {
533-
assert test $# -ge 2
534-
dir="${1%/}"
535-
rev="$2"
536-
shift 2
537-
debug "Looking for other splits with dir != $dir..."
538-
539-
git log \
540-
--grep '^git-subtree-mainline:' \
541-
--no-patch \
542-
--no-show-signature \
543-
--format='hash: %H%nparents: %P%n%(trailers:key=git-subtree-dir,key=git-subtree-mainline,key=git-subtree-split)%nEND' \
544-
"$rev" ${@:+"$@"} |
545-
while read -r key val
546-
do
547-
case "$key" in
548-
hash:)
549-
commit_hash="${val}"
550-
commit_parents=
551-
subtree_dir=
552-
subtree_mainline=
553-
subtree_split=
554-
;;
555-
parents:)
556-
commit_parents="${val}" ;;
557-
git-subtree-dir:)
558-
subtree_dir="${val%/}/" ;;
559-
git-subtree-mainline:)
560-
subtree_mainline="${val}" ;;
561-
git-subtree-split:)
562-
subtree_split="${val}" ;;
563-
END)
564-
# verify:
565-
# * all git-subtree-* trailers are present
566-
# * this subtree is outside of $dir
567-
# * the first parent is the git-subtree-mainline:
568-
# * the commit has at least two parents
569-
if test -n "${subtree_dir}" &&
570-
test -n "${subtree_split}" &&
571-
test -n "${subtree_mainline}" &&
572-
test "${subtree_dir}" = "${subtree_dir#"${dir}/"}" &&
573-
test "${commit_parents}" != "${commit_parents#"$subtree_mainline "}" &&
574-
rev_exists "${commit_hash}^2"
575-
then
576-
debug "find_other_splits excluding dir=$subtree_dir merged in ${commit_hash}"
577-
echo "^${commit_hash}^2"
578-
set_notree "${commit_hash}"
579-
fi
580-
;;
581-
esac
582-
done
583-
}
584-
585514
# Usage: copy_commit REV TREE FLAGS_STR
586515
copy_commit () {
587516
assert test $# = 3
@@ -856,6 +785,42 @@ ensure_valid_ref_format () {
856785
die "fatal: '$1' does not look like a ref"
857786
}
858787

788+
# Usage: should_ignore_subtree_split_commit REV
789+
#
790+
# Check if REV is a commit from another subtree and should be
791+
# ignored from processing for splits
792+
should_ignore_subtree_split_commit () {
793+
assert test $# = 1
794+
795+
git show \
796+
--no-patch \
797+
--no-show-signature \
798+
--format='%(trailers:key=git-subtree-dir,key=git-subtree-mainline)' \
799+
"$1" |
800+
(
801+
have_mainline=
802+
subtree_dir=
803+
804+
while read -r trailer val
805+
do
806+
case "$trailer" in
807+
git-subtree-dir:)
808+
subtree_dir="${val%/}" ;;
809+
git-subtree-mainline:)
810+
have_mainline=y ;;
811+
esac
812+
done
813+
814+
if test -n "${subtree_dir}" &&
815+
test -z "${have_mainline}" &&
816+
test "${subtree_dir}" != "$arg_prefix"
817+
then
818+
return 0
819+
fi
820+
return 1
821+
)
822+
}
823+
859824
# Usage: process_split_commit REV PARENTS
860825
process_split_commit () {
861826
assert test $# = 2
@@ -1029,39 +994,31 @@ cmd_split () {
1029994
fi
1030995

1031996
unrevs="$(find_existing_splits "$dir" "$rev" "$repository")" || exit $?
1032-
(find_other_splits >"$cachedir/prune" "$dir" "$rev" $unrevs) || exit $?
1033997

1034998
# We can't restrict rev-list to only $dir here, because some of our
1035999
# parents have the $dir contents the root, and those won't match.
10361000
# (and rev-list --follow doesn't seem to solve this)
1037-
revmax="$(git rev-list \
1038-
<"$cachedir/prune" \
1039-
--topo-order \
1040-
--reverse \
1041-
--parents \
1042-
--stdin \
1043-
--count \
1044-
"$rev" \
1045-
$unrevs
1046-
)"
1001+
grl='git rev-list --topo-order --reverse --parents $rev $unrevs'
1002+
revmax=$(eval "$grl" | wc -l)
10471003
revcount=0
10481004
createcount=0
10491005
extracount=0
1050-
git rev-list \
1051-
<"$cachedir/prune" \
1052-
--topo-order \
1053-
--reverse \
1054-
--parents \
1055-
--stdin \
1056-
"$rev" \
1057-
$unrevs |
1006+
eval "$grl" |
10581007
while read rev parents
10591008
do
1060-
if get_notree "$rev"
1009+
if should_ignore_subtree_split_commit "$rev"
10611010
then
10621011
continue
10631012
fi
1064-
process_split_commit "$rev" "$parents"
1013+
parsedparents=''
1014+
for parent in $parents
1015+
do
1016+
if ! should_ignore_subtree_split_commit "$parent"
1017+
then
1018+
parsedparents="$parsedparents$parent "
1019+
fi
1020+
done
1021+
process_split_commit "$rev" "$parsedparents"
10651022
done || exit $?
10661023

10671024
latest_new=$(cache_get latest_new) || exit $?

contrib/subtree/t/t7900-subtree.sh

Lines changed: 6 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -411,9 +411,8 @@ test_expect_success 'split sub dir/ with --rejoin' '
411411
git fetch ./"sub proj" HEAD &&
412412
git subtree merge --prefix="sub dir" FETCH_HEAD &&
413413
split_hash=$(git subtree split --prefix="sub dir" --annotate="*") &&
414-
git subtree split --prefix="sub dir" --annotate="*" -b spl --rejoin &&
415-
test "$(last_commit_subject)" = "Split '\''sub dir/'\'' into commit '\''$split_hash'\''" &&
416-
test "$(git rev-list --count spl)" -eq 5
414+
git subtree split --prefix="sub dir" --annotate="*" --rejoin &&
415+
test "$(last_commit_subject)" = "Split '\''sub dir/'\'' into commit '\''$split_hash'\''"
417416
)
418417
'
419418

@@ -443,25 +442,18 @@ test_expect_success 'split with multiple subtrees' '
443442
git -C "$test_count" subtree add --prefix=subADir FETCH_HEAD &&
444443
git -C "$test_count" fetch ./subB HEAD &&
445444
git -C "$test_count" subtree add --prefix=subBDir FETCH_HEAD &&
446-
test "$(git -C "$test_count" rev-list --count main)" -eq 7 &&
447445
test_create_commit "$test_count" subADir/main-subA1 &&
448446
test_create_commit "$test_count" subBDir/main-subB1 &&
449447
git -C "$test_count" subtree split --prefix=subADir \
450-
--squash --rejoin -m "Sub A Split 1" -b a1 &&
451-
test "$(git -C "$test_count" rev-list --count main..a1)" -eq 1 &&
448+
--squash --rejoin -m "Sub A Split 1" &&
452449
git -C "$test_count" subtree split --prefix=subBDir \
453-
--squash --rejoin -m "Sub B Split 1" -b b1 &&
454-
test "$(git -C "$test_count" rev-list --count main..b1)" -eq 1 &&
450+
--squash --rejoin -m "Sub B Split 1" &&
455451
test_create_commit "$test_count" subADir/main-subA2 &&
456452
test_create_commit "$test_count" subBDir/main-subB2 &&
457453
git -C "$test_count" subtree split --prefix=subADir \
458-
--squash --rejoin -m "Sub A Split 2" -b a2 &&
459-
test "$(git -C "$test_count" rev-list --count main..a2)" -eq 2 &&
460-
test "$(git -C "$test_count" rev-list --count a1..a2)" -eq 1 &&
454+
--squash --rejoin -m "Sub A Split 2" &&
461455
test "$(git -C "$test_count" subtree split --prefix=subBDir \
462-
--squash --rejoin -d -m "Sub B Split 1" -b b2 2>&1 | grep -w "\[1\]")" = "" &&
463-
test "$(git -C "$test_count" rev-list --count main..b2)" -eq 2 &&
464-
test "$(git -C "$test_count" rev-list --count b1..b2)" -eq 1
456+
--squash --rejoin -d -m "Sub B Split 1" 2>&1 | grep -w "\[1\]")" = ""
465457
'
466458

467459
# When subtree split-ing a directory that has other subtree
@@ -485,7 +477,6 @@ do
485477
test_path_is_file subA/file1.t &&
486478
test_path_is_file subA/subB/file2.t &&
487479
git subtree split --prefix=subA --branch=bsplit &&
488-
test "$(git rev-list --count bsplit)" -eq 2 &&
489480
git checkout bsplit &&
490481
test_path_is_file file1.t &&
491482
test_path_is_file subB/file2.t &&
@@ -498,7 +489,6 @@ do
498489
--prefix=subA/subB mksubtree &&
499490
test_path_is_file subA/subB/file3.t &&
500491
git subtree split --prefix=subA --branch=bsplit &&
501-
test "$(git rev-list --count bsplit)" -eq 3 &&
502492
git checkout bsplit &&
503493
test_path_is_file file1.t &&
504494
test_path_is_file subB/file2.t &&
@@ -507,67 +497,6 @@ do
507497
'
508498
done
509499

510-
# Usually,
511-
#
512-
# git subtree merge -P subA --squash f00...
513-
#
514-
# makes two commits, in this order:
515-
#
516-
# 1. Squashed 'subA/' content from commit f00...
517-
# 2. Merge commit (1) as 'subA'
518-
#
519-
# Commit 1 updates the subtree but does *not* rewrite paths.
520-
# Commit 2 rewrites all trees to start with `subA/`
521-
#
522-
# Commit 1 either has no parents or depends only on other
523-
# "Squashed 'subA/' content" commits.
524-
#
525-
# For merge without --squash, subtree produces just one commit:
526-
# a merge commit with git-subtree trailers.
527-
#
528-
# In either case, if the user rebases these commits, they will
529-
# still have the git-subtree-* trailers… but will NOT have
530-
# the layout described above.
531-
#
532-
# Test that subsequent `git subtree split` are not confused by this.
533-
test_expect_success 'split with rebased subtree commit' '
534-
subtree_test_create_repo "$test_count" &&
535-
(
536-
cd "$test_count" &&
537-
test_commit file0 &&
538-
test_create_subtree_add \
539-
. mksubtree subA file1 --squash &&
540-
test_path_is_file subA/file1.t &&
541-
mkdir subB &&
542-
test_commit subB/bfile &&
543-
git commit --amend -F - <<'EOF' &&
544-
Squashed '\''subB/'\'' content from commit '\''badf00da911bbe895347b4b236f5461d55dc9877'\''
545-
546-
Simulate a cherry-picked or rebased subtree commit.
547-
548-
git-subtree-dir: subB
549-
git-subtree-split: badf00da911bbe895347b4b236f5461d55dc9877
550-
EOF
551-
test_commit subA/file2 &&
552-
test_commit subB/bfile2 &&
553-
git commit --amend -F - <<'EOF' &&
554-
Split '\''subB/'\'' into commit '\''badf00da911bbe895347b4b236f5461d55dc9877'\''
555-
556-
Simulate a cherry-picked or rebased subtree commit.
557-
558-
git-subtree-dir: subB
559-
git-subtree-mainline: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
560-
git-subtree-split: badf00da911bbe895347b4b236f5461d55dc9877
561-
EOF
562-
git subtree split --prefix=subA --branch=bsplit &&
563-
git checkout bsplit &&
564-
test_path_is_file file1.t &&
565-
test_path_is_file file2.t &&
566-
test "$(last_commit_subject)" = "subA/file2" &&
567-
test "$(git rev-list --count bsplit)" -eq 2
568-
)
569-
'
570-
571500
test_expect_success 'split sub dir/ with --rejoin from scratch' '
572501
subtree_test_create_repo "$test_count" &&
573502
test_create_commit "$test_count" main1 &&

0 commit comments

Comments
 (0)