Skip to content

Commit a2ea7bc

Browse files
gitsterdscho
authored andcommitted
Merge branch 'cs/subtree-squash-split-fix'
"git subtree" (in contrib/) did not work correctly when splitting squashed subtrees, which has been improved. * cs/subtree-squash-split-fix: contrib/subtree: fix split with squashed subtrees
2 parents 3bd53ca + 40f6c69 commit a2ea7bc

File tree

2 files changed

+99
-8
lines changed

2 files changed

+99
-8
lines changed

contrib/subtree/git-subtree.sh

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -785,20 +785,40 @@ ensure_valid_ref_format () {
785785
die "fatal: '$1' does not look like a ref"
786786
}
787787

788-
# Usage: check if a commit from another subtree should be
788+
# Usage: should_ignore_subtree_split_commit REV
789+
#
790+
# Check if REV is a commit from another subtree and should be
789791
# ignored from processing for splits
790792
should_ignore_subtree_split_commit () {
791793
assert test $# = 1
792-
local rev="$1"
793-
if test -n "$(git log -1 --grep="git-subtree-dir:" $rev)"
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"
794817
then
795-
if test -z "$(git log -1 --grep="git-subtree-mainline:" $rev)" &&
796-
test -z "$(git log -1 --grep="git-subtree-dir: $arg_prefix$" $rev)"
797-
then
798-
return 0
799-
fi
818+
return 0
800819
fi
801820
return 1
821+
)
802822
}
803823

804824
# Usage: process_split_commit REV PARENTS

contrib/subtree/t/t7900-subtree.sh

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ This test verifies the basic operation of the add, merge, split, pull,
99
and push subcommands of git subtree.
1010
'
1111

12+
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
13+
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
14+
1215
TEST_DIRECTORY=$(pwd)/../../../t
1316
. "$TEST_DIRECTORY"/test-lib.sh
1417
. "$TEST_DIRECTORY"/lib-gpg.sh
@@ -68,6 +71,33 @@ test_create_pre2_32_repo () {
6871
git -C "$1-clone" replace HEAD^2 $new_commit
6972
}
7073

74+
# test_create_subtree_add REPO ORPHAN PREFIX FILENAME ...
75+
#
76+
# Create a simple subtree on a new branch named ORPHAN in REPO.
77+
# The subtree is then merged into the current branch of REPO,
78+
# under PREFIX. The generated subtree has has one commit
79+
# with subject and tag FILENAME with a single file "FILENAME.t"
80+
#
81+
# When this method returns:
82+
# - the current branch of REPO will have file PREFIX/FILENAME.t
83+
# - REPO will have a branch named ORPHAN with subtree history
84+
#
85+
# additional arguments are forwarded to "subtree add"
86+
test_create_subtree_add () {
87+
(
88+
cd "$1" &&
89+
orphan="$2" &&
90+
prefix="$3" &&
91+
filename="$4" &&
92+
shift 4 &&
93+
last="$(git branch --show-current)" &&
94+
git switch --orphan "$orphan" &&
95+
test_commit "$filename" &&
96+
git checkout "$last" &&
97+
git subtree add --prefix="$prefix" "$@" "$orphan"
98+
)
99+
}
100+
71101
test_expect_success 'shows short help text for -h' '
72102
test_expect_code 129 git subtree -h >out 2>err &&
73103
test_must_be_empty err &&
@@ -426,6 +456,47 @@ test_expect_success 'split with multiple subtrees' '
426456
--squash --rejoin -d -m "Sub B Split 1" 2>&1 | grep -w "\[1\]")" = ""
427457
'
428458

459+
# When subtree split-ing a directory that has other subtree
460+
# *merges* underneath it, the split must include those subtrees.
461+
# This test creates a nested subtree, `subA/subB`, and tests
462+
# that the tree is correct after a subtree split of `subA/`.
463+
# The test covers:
464+
# - An initial `subtree add`; and
465+
# - A follow-up `subtree merge`
466+
# both with and without `--squashed`.
467+
for is_squashed in '' 'y'
468+
do
469+
test_expect_success "split keeps nested ${is_squashed:+--squash }subtrees that are part of the split" '
470+
subtree_test_create_repo "$test_count" &&
471+
(
472+
cd "$test_count" &&
473+
mkdir subA &&
474+
test_commit subA/file1 &&
475+
test_create_subtree_add \
476+
. mksubtree subA/subB file2 ${is_squashed:+--squash} &&
477+
test_path_is_file subA/file1.t &&
478+
test_path_is_file subA/subB/file2.t &&
479+
git subtree split --prefix=subA --branch=bsplit &&
480+
git checkout bsplit &&
481+
test_path_is_file file1.t &&
482+
test_path_is_file subB/file2.t &&
483+
git checkout mksubtree &&
484+
git branch -D bsplit &&
485+
test_commit file3 &&
486+
git checkout main &&
487+
git subtree merge \
488+
${is_squashed:+--squash} \
489+
--prefix=subA/subB mksubtree &&
490+
test_path_is_file subA/subB/file3.t &&
491+
git subtree split --prefix=subA --branch=bsplit &&
492+
git checkout bsplit &&
493+
test_path_is_file file1.t &&
494+
test_path_is_file subB/file2.t &&
495+
test_path_is_file subB/file3.t
496+
)
497+
'
498+
done
499+
429500
test_expect_success 'split sub dir/ with --rejoin from scratch' '
430501
subtree_test_create_repo "$test_count" &&
431502
test_create_commit "$test_count" main1 &&

0 commit comments

Comments
 (0)