subtree: allow 'split' flags to be passed to 'push'

'push' does a 'split' internally, but it doesn't pass flags through to the 'split'. This is silly, if you need to pass flags to 'split', then it means that you can't use 'push'! So, have 'push' accept 'split' flags, and pass them through to 'split'. Add tests for this by copying split's tests with minimal modification. Signed-off-by: Luke Shumaker <lukeshu@datawire.io> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Luke Shumaker committed Apr 27, 2021 at 15:17 UTC 94389e7c81d47102f061b36a93e050d639fe3d40
3 files changed +223 -12
contrib/subtree/git-subtree.sh
+3 -3
@@ -33,13 +33,13 @@ h,help show the help
33 q quiet
34 d show debug messages
35 P,prefix= the name of the subdir to split out
36 - options for 'split'
36 + options for 'split' (also: 'push')
37 annotate= add a prefix to commit message of new commits
38 b,branch= create a new branch from the split subtree
39 ignore-joins ignore prior --rejoin commits
40 onto= try connecting new tree to an existing one
41 rejoin merge the new branch back into HEAD
42 - options for 'add' and 'merge' (also: 'pull' and 'split --rejoin')
42 + options for 'add' and 'merge' (also: 'pull', 'split --rejoin', and 'push --rejoin')
43 squash merge subtree changes as a single commit
44 m,message= use the given message as the commit message for the merge commit
45 "
@@ -964,7 +964,7 @@ cmd_push () {
964 repository=$1
965 refspec=$2
966 echo "git push using: " "$repository" "$refspec"
967 - localrev=$(git subtree split --prefix="$arg_prefix") || die
967 + localrev=$(cmd_split) || die
968 git push "$repository" "$localrev":"refs/heads/$refspec"
969 else
970 die "'$dir' must already exist. Try 'git subtree add'."
contrib/subtree/git-subtree.txt
+8 -7
@@ -137,11 +137,11 @@ OPTIONS FOR ALL COMMANDS
137 want to manipulate. This option is mandatory
138 for all commands.
139
140 -OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull' AND 'split --rejoin')
141 ------------------------------------------------------------------
140 +OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull', 'split --rejoin', AND 'push --rejoin')
141 +-----------------------------------------------------------------------------------
142 These options for 'add' and 'merge' may also be given to 'pull' (which
143 -wraps 'merge') and 'split --rejoin' (which wraps either 'add' or
144 -'merge' as appropriate).
143 +wraps 'merge'), 'split --rejoin' (which wraps either 'add' or 'merge'
144 +as appropriate), and 'push --rejoin' (which wraps 'split --rejoin').
145
146 --squash::
147 Instead of merging the entire history from the subtree project, produce
@@ -173,9 +173,10 @@ subproject.
173 --message=<message>::
174 Specify <message> as the commit message for the merge commit.
175
176 -OPTIONS FOR 'split'
177 --------------------
178 -These options are only valid for 'split'.
176 +OPTIONS FOR 'split' (ALSO: 'push')
177 +----------------------------------
178 +These options for 'split' may also be given to 'push' (which wraps
179 +'split').
180
181 --annotate=<annotation>::
182 When generating synthetic history, add <annotation> as a prefix to each
contrib/subtree/t/t7900-subtree.sh
+212 -2
@@ -5,8 +5,8 @@
5 #
6 test_description='Basic porcelain support for subtrees
7
8 -This test verifies the basic operation of the add, pull, merge
9 -and split subcommands of git subtree.
8 +This test verifies the basic operation of the add, merge, split, pull,
9 +and push subcommands of git subtree.
10 '
11
12 TEST_DIRECTORY=$(pwd)/../../../t
@@ -610,6 +610,216 @@ test_expect_success 'push basic operation' '
610 )
611 '
612
613 +test_expect_success 'push sub dir/ with --rejoin' '
614 + subtree_test_create_repo "$test_count" &&
615 + subtree_test_create_repo "$test_count/sub proj" &&
616 + test_create_commit "$test_count" main1 &&
617 + test_create_commit "$test_count/sub proj" sub1 &&
618 + (
619 + cd "$test_count" &&
620 + git fetch ./"sub proj" HEAD &&
621 + git subtree add --prefix="sub dir" FETCH_HEAD
622 + ) &&
623 + test_create_commit "$test_count" "sub dir"/main-sub1 &&
624 + test_create_commit "$test_count" main2 &&
625 + test_create_commit "$test_count/sub proj" sub2 &&
626 + test_create_commit "$test_count" "sub dir"/main-sub2 &&
627 + (
628 + cd "$test_count" &&
629 + git fetch ./"sub proj" HEAD &&
630 + git subtree merge --prefix="sub dir" FETCH_HEAD &&
631 + split_hash=$(git subtree split --prefix="sub dir" --annotate="*") &&
632 + git subtree push --prefix="sub dir" --annotate="*" --rejoin ./"sub proj" from-mainline &&
633 + test "$(last_commit_subject)" = "Split '\''sub dir/'\'' into commit '\''$split_hash'\''" &&
634 + test "$split_hash" = "$(git -C "sub proj" rev-parse --verify refs/heads/from-mainline)"
635 + )
636 +'
637 +
638 +test_expect_success 'push sub dir/ with --rejoin from scratch' '
639 + subtree_test_create_repo "$test_count" &&
640 + test_create_commit "$test_count" main1 &&
641 + (
642 + cd "$test_count" &&
643 + mkdir "sub dir" &&
644 + echo file >"sub dir"/file &&
645 + git add "sub dir/file" &&
646 + git commit -m"sub dir file" &&
647 + split_hash=$(git subtree split --prefix="sub dir" --rejoin) &&
648 + git init --bare "sub proj.git" &&
649 + git subtree push --prefix="sub dir" --rejoin ./"sub proj.git" from-mainline &&
650 + test "$(last_commit_subject)" = "Split '\''sub dir/'\'' into commit '\''$split_hash'\''" &&
651 + test "$split_hash" = "$(git -C "sub proj.git" rev-parse --verify refs/heads/from-mainline)"
652 + )
653 +'
654 +
655 +test_expect_success 'push sub dir/ with --rejoin and --message' '
656 + subtree_test_create_repo "$test_count" &&
657 + subtree_test_create_repo "$test_count/sub proj" &&
658 + test_create_commit "$test_count" main1 &&
659 + test_create_commit "$test_count/sub proj" sub1 &&
660 + (
661 + cd "$test_count" &&
662 + git fetch ./"sub proj" HEAD &&
663 + git subtree add --prefix="sub dir" FETCH_HEAD
664 + ) &&
665 + test_create_commit "$test_count" "sub dir"/main-sub1 &&
666 + test_create_commit "$test_count" main2 &&
667 + test_create_commit "$test_count/sub proj" sub2 &&
668 + test_create_commit "$test_count" "sub dir"/main-sub2 &&
669 + (
670 + cd "$test_count" &&
671 + git fetch ./"sub proj" HEAD &&
672 + git subtree merge --prefix="sub dir" FETCH_HEAD &&
673 + git subtree push --prefix="sub dir" --message="Split & rejoin" --annotate="*" --rejoin ./"sub proj" from-mainline &&
674 + test "$(last_commit_subject)" = "Split & rejoin" &&
675 + split_hash="$(git rev-parse --verify HEAD^2)" &&
676 + test "$split_hash" = "$(git -C "sub proj" rev-parse --verify refs/heads/from-mainline)"
677 + )
678 +'
679 +
680 +test_expect_success 'push "sub dir"/ with --rejoin and --squash' '
681 + subtree_test_create_repo "$test_count" &&
682 + subtree_test_create_repo "$test_count/sub proj" &&
683 + test_create_commit "$test_count" main1 &&
684 + test_create_commit "$test_count/sub proj" sub1 &&
685 + (
686 + cd "$test_count" &&
687 + git fetch ./"sub proj" HEAD &&
688 + git subtree add --prefix="sub dir" --squash FETCH_HEAD
689 + ) &&
690 + test_create_commit "$test_count" "sub dir"/main-sub1 &&
691 + test_create_commit "$test_count" main2 &&
692 + test_create_commit "$test_count/sub proj" sub2 &&
693 + test_create_commit "$test_count" "sub dir"/main-sub2 &&
694 + (
695 + cd "$test_count" &&
696 + git subtree pull --prefix="sub dir" --squash ./"sub proj" HEAD &&
697 + MAIN=$(git rev-parse --verify HEAD) &&
698 + SUB=$(git -C "sub proj" rev-parse --verify HEAD) &&
699 +
700 + SPLIT=$(git subtree split --prefix="sub dir" --annotate="*") &&
701 + git subtree push --prefix="sub dir" --annotate="*" --rejoin --squash ./"sub proj" from-mainline &&
702 +
703 + test_must_fail git merge-base --is-ancestor $SUB HEAD &&
704 + test_must_fail git merge-base --is-ancestor $SPLIT HEAD &&
705 + git rev-list HEAD ^$MAIN >commit-list &&
706 + test_line_count = 2 commit-list &&
707 + test "$(git rev-parse --verify HEAD:)" = "$(git rev-parse --verify $MAIN:)" &&
708 + test "$(git rev-parse --verify HEAD:"sub dir")" = "$(git rev-parse --verify $SPLIT:)" &&
709 + test "$(git rev-parse --verify HEAD^1)" = $MAIN &&
710 + test "$(git rev-parse --verify HEAD^2)" != $SPLIT &&
711 + test "$(git rev-parse --verify HEAD^2:)" = "$(git rev-parse --verify $SPLIT:)" &&
712 + test "$(last_commit_subject)" = "Split '\''sub dir/'\'' into commit '\''$SPLIT'\''" &&
713 + test "$SPLIT" = "$(git -C "sub proj" rev-parse --verify refs/heads/from-mainline)"
714 + )
715 +'
716 +
717 +test_expect_success 'push "sub dir"/ with --branch' '
718 + subtree_test_create_repo "$test_count" &&
719 + subtree_test_create_repo "$test_count/sub proj" &&
720 + test_create_commit "$test_count" main1 &&
721 + test_create_commit "$test_count/sub proj" sub1 &&
722 + (
723 + cd "$test_count" &&
724 + git fetch ./"sub proj" HEAD &&
725 + git subtree add --prefix="sub dir" FETCH_HEAD
726 + ) &&
727 + test_create_commit "$test_count" "sub dir"/main-sub1 &&
728 + test_create_commit "$test_count" main2 &&
729 + test_create_commit "$test_count/sub proj" sub2 &&
730 + test_create_commit "$test_count" "sub dir"/main-sub2 &&
731 + (
732 + cd "$test_count" &&
733 + git fetch ./"sub proj" HEAD &&
734 + git subtree merge --prefix="sub dir" FETCH_HEAD &&
735 + split_hash=$(git subtree split --prefix="sub dir" --annotate="*") &&
736 + git subtree push --prefix="sub dir" --annotate="*" --branch subproj-br ./"sub proj" from-mainline &&
737 + test "$(git rev-parse subproj-br)" = "$split_hash" &&
738 + test "$split_hash" = "$(git -C "sub proj" rev-parse --verify refs/heads/from-mainline)"
739 + )
740 +'
741 +
742 +test_expect_success 'check hash of push' '
743 + subtree_test_create_repo "$test_count" &&
744 + subtree_test_create_repo "$test_count/sub proj" &&
745 + test_create_commit "$test_count" main1 &&
746 + test_create_commit "$test_count/sub proj" sub1 &&
747 + (
748 + cd "$test_count" &&
749 + git fetch ./"sub proj" HEAD &&
750 + git subtree add --prefix="sub dir" FETCH_HEAD
751 + ) &&
752 + test_create_commit "$test_count" "sub dir"/main-sub1 &&
753 + test_create_commit "$test_count" main2 &&
754 + test_create_commit "$test_count/sub proj" sub2 &&
755 + test_create_commit "$test_count" "sub dir"/main-sub2 &&
756 + (
757 + cd "$test_count" &&
758 + git fetch ./"sub proj" HEAD &&
759 + git subtree merge --prefix="sub dir" FETCH_HEAD &&
760 + split_hash=$(git subtree split --prefix="sub dir" --annotate="*") &&
761 + git subtree push --prefix="sub dir" --annotate="*" --branch subproj-br ./"sub proj" from-mainline &&
762 + test "$(git rev-parse subproj-br)" = "$split_hash" &&
763 + # Check hash of split
764 + new_hash=$(git rev-parse subproj-br^2) &&
765 + (
766 + cd ./"sub proj" &&
767 + subdir_hash=$(git rev-parse HEAD) &&
768 + test "$new_hash" = "$subdir_hash"
769 + ) &&
770 + test "$split_hash" = "$(git -C "sub proj" rev-parse --verify refs/heads/from-mainline)"
771 + )
772 +'
773 +
774 +test_expect_success 'push "sub dir"/ with --branch for an existing branch' '
775 + subtree_test_create_repo "$test_count" &&
776 + subtree_test_create_repo "$test_count/sub proj" &&
777 + test_create_commit "$test_count" main1 &&
778 + test_create_commit "$test_count/sub proj" sub1 &&
779 + (
780 + cd "$test_count" &&
781 + git fetch ./"sub proj" HEAD &&
782 + git branch subproj-br FETCH_HEAD &&
783 + git subtree add --prefix="sub dir" FETCH_HEAD
784 + ) &&
785 + test_create_commit "$test_count" "sub dir"/main-sub1 &&
786 + test_create_commit "$test_count" main2 &&
787 + test_create_commit "$test_count/sub proj" sub2 &&
788 + test_create_commit "$test_count" "sub dir"/main-sub2 &&
789 + (
790 + cd "$test_count" &&
791 + git fetch ./"sub proj" HEAD &&
792 + git subtree merge --prefix="sub dir" FETCH_HEAD &&
793 + split_hash=$(git subtree split --prefix="sub dir" --annotate="*") &&
794 + git subtree push --prefix="sub dir" --annotate="*" --branch subproj-br ./"sub proj" from-mainline &&
795 + test "$(git rev-parse subproj-br)" = "$split_hash" &&
796 + test "$split_hash" = "$(git -C "sub proj" rev-parse --verify refs/heads/from-mainline)"
797 + )
798 +'
799 +
800 +test_expect_success 'push "sub dir"/ with --branch for an incompatible branch' '
801 + subtree_test_create_repo "$test_count" &&
802 + subtree_test_create_repo "$test_count/sub proj" &&
803 + test_create_commit "$test_count" main1 &&
804 + test_create_commit "$test_count/sub proj" sub1 &&
805 + (
806 + cd "$test_count" &&
807 + git branch init HEAD &&
808 + git fetch ./"sub proj" HEAD &&
809 + git subtree add --prefix="sub dir" FETCH_HEAD
810 + ) &&
811 + test_create_commit "$test_count" "sub dir"/main-sub1 &&
812 + test_create_commit "$test_count" main2 &&
813 + test_create_commit "$test_count/sub proj" sub2 &&
814 + test_create_commit "$test_count" "sub dir"/main-sub2 &&
815 + (
816 + cd "$test_count" &&
817 + git fetch ./"sub proj" HEAD &&
818 + git subtree merge --prefix="sub dir" FETCH_HEAD &&
819 + test_must_fail git subtree push --prefix="sub dir" --branch init "./sub proj" from-mainline
820 + )
821 +'
822 +
823 #
824 # Validity checking
825 #