@@ -11,113 +11,96 @@ commit_message() {
1111 git log --pretty=format:%s -1 " $1 "
1212}
1313
14+ # There are a few bugs in the rebase with regards to the subtree strategy, and
15+ # this test script tries to document them. First, the following commit history
16+ # is generated (the onelines are shown, time flows from left to right):
17+ #
18+ # master1 - master2 - master3
19+ # \
20+ # README ---------------------- Add subproject master - master4 - files_subtree/master5
21+ #
22+ # Where the merge moves the files master[123].t into the subdirectory
23+ # files_subtree/ and master4 as well as files_subtree/master5 add files to that
24+ # directory directly.
25+ #
26+ # Then, in subsequent test cases, `git filter-branch` is used to distill just
27+ # the commits that touch files_subtree/. To give it a final pre-rebase touch,
28+ # an empty commit is added on top. The pre-rebase commit history looks like
29+ # this:
30+ #
31+ # Add subproject master - master4 - files_subtree/master5 - Empty commit
32+ #
33+ # where the root commit adds three files: master1.t, master2.t and master3.t.
34+ #
35+ # This commit history is then rebased onto `master3` with the
36+ # `-Xsubtree=files_subtree` option in three different ways:
37+ #
38+ # 1. using `--preserve-merges`
39+ # 2. using `--preserve-merges` and --keep-empty
40+ # 3. without specifying a rebase backend
41+
1442test_expect_success ' setup' '
1543 test_commit README &&
16- mkdir files &&
17- (
18- cd files &&
19- git init &&
20- test_commit master1 &&
21- test_commit master2 &&
22- test_commit master3
23- ) &&
24- git fetch files master &&
25- git branch files-master FETCH_HEAD &&
26- git read-tree --prefix=files_subtree files-master &&
27- git checkout -- files_subtree &&
28- tree=$(git write-tree) &&
29- head=$(git rev-parse HEAD) &&
30- rev=$(git rev-parse --verify files-master^0) &&
31- commit=$(git commit-tree -p $head -p $rev -m "Add subproject master" $tree) &&
32- git update-ref HEAD $commit &&
33- (
34- cd files_subtree &&
35- test_commit master4
36- ) &&
37- test_commit files_subtree/master5
38- '
3944
40- # FAILURE: Does not preserve master4.
41- test_expect_failure REBASE_P \
42- ' Rebase -Xsubtree --preserve-merges --onto commit 4' '
43- reset_rebase &&
44- git checkout -b rebase-preserve-merges-4 master &&
45+ git init files &&
46+ test_commit -C files master1 &&
47+ test_commit -C files master2 &&
48+ test_commit -C files master3 &&
49+
50+ : perform subtree merge into files_subtree/ &&
51+ git fetch files refs/heads/master:refs/heads/files-master &&
52+ git merge -s ours --no-commit --allow-unrelated-histories \
53+ files-master &&
54+ git read-tree --prefix=files_subtree -u files-master &&
55+ git commit -m "Add subproject master" &&
56+
57+ : add two extra commits to rebase &&
58+ test_commit -C files_subtree master4 &&
59+ test_commit files_subtree/master5 &&
60+
61+ git checkout -b to-rebase &&
4562 git filter-branch --prune-empty -f --subdirectory-filter files_subtree &&
46- git commit -m "Empty commit" --allow-empty &&
47- git rebase -Xsubtree=files_subtree --preserve-merges --onto files-master master &&
48- verbose test "$(commit_message HEAD~)" = "files_subtree/master4"
63+ git commit -m "Empty commit" --allow-empty
4964'
5065
51- # FAILURE: Does not preserve master5.
52- test_expect_failure REBASE_P \
53- ' Rebase -Xsubtree --preserve-merges --onto commit 5' '
66+ # FAILURE: Does not preserve master4.
67+ test_expect_failure REBASE_P ' Rebase -Xsubtree --preserve-merges --onto commit' '
5468 reset_rebase &&
55- git checkout -b rebase-preserve-merges-5 master &&
56- git filter-branch --prune-empty -f --subdirectory-filter files_subtree &&
57- git commit -m "Empty commit" --allow-empty &&
69+ git checkout -b rebase-preserve-merges to-rebase &&
5870 git rebase -Xsubtree=files_subtree --preserve-merges --onto files-master master &&
71+ verbose test "$(commit_message HEAD~)" = "master4" &&
5972 verbose test "$(commit_message HEAD)" = "files_subtree/master5"
6073'
6174
6275# FAILURE: Does not preserve master4.
63- test_expect_failure REBASE_P \
64- ' Rebase -Xsubtree --keep-empty --preserve-merges --onto commit 4' '
76+ test_expect_failure REBASE_P ' Rebase -Xsubtree --keep-empty --preserve-merges --onto commit' '
6577 reset_rebase &&
66- git checkout -b rebase-keep-empty-4 master &&
67- git filter-branch --prune-empty -f --subdirectory-filter files_subtree &&
68- git commit -m "Empty commit" --allow-empty &&
69- git rebase -Xsubtree=files_subtree --keep-empty --preserve-merges --onto files-master master &&
70- verbose test "$(commit_message HEAD~2)" = "files_subtree/master4"
71- '
72-
73- # FAILURE: Does not preserve master5.
74- test_expect_failure REBASE_P \
75- ' Rebase -Xsubtree --keep-empty --preserve-merges --onto commit 5' '
76- reset_rebase &&
77- git checkout -b rebase-keep-empty-5 master &&
78- git filter-branch --prune-empty -f --subdirectory-filter files_subtree &&
79- git commit -m "Empty commit" --allow-empty &&
80- git rebase -Xsubtree=files_subtree --keep-empty --preserve-merges --onto files-master master &&
81- verbose test "$(commit_message HEAD~)" = "files_subtree/master5"
82- '
83-
84- # FAILURE: Does not preserve Empty.
85- test_expect_failure REBASE_P \
86- ' Rebase -Xsubtree --keep-empty --preserve-merges --onto empty commit' '
87- reset_rebase &&
88- git checkout -b rebase-keep-empty-empty master &&
89- git filter-branch --prune-empty -f --subdirectory-filter files_subtree &&
90- git commit -m "Empty commit" --allow-empty &&
78+ git checkout -b rebase-keep-empty to-rebase &&
9179 git rebase -Xsubtree=files_subtree --keep-empty --preserve-merges --onto files-master master &&
80+ verbose test "$(commit_message HEAD~2)" = "master4" &&
81+ verbose test "$(commit_message HEAD~)" = "files_subtree/master5" &&
9282 verbose test "$(commit_message HEAD)" = "Empty commit"
9383'
9484
95- # FAILURE: fatal: Could not parse object
96- test_expect_failure ' Rebase -Xsubtree --onto commit 4' '
85+ test_expect_success ' Rebase -Xsubtree --keep-empty --onto commit' '
9786 reset_rebase &&
98- git checkout -b rebase-onto-4 master &&
99- git filter-branch --prune-empty -f --subdirectory-filter files_subtree &&
100- git commit -m "Empty commit" --allow-empty &&
101- git rebase -Xsubtree=files_subtree --onto files-master master &&
102- verbose test "$(commit_message HEAD~2)" = "files_subtree/master4"
87+ git checkout -b rebase-onto to-rebase &&
88+ test_must_fail git rebase -Xsubtree=files_subtree --keep-empty --onto files-master master &&
89+ : first pick results in no changes &&
90+ git rebase --continue &&
91+ verbose test "$(commit_message HEAD~2)" = "master4" &&
92+ verbose test "$(commit_message HEAD~)" = "files_subtree/master5" &&
93+ verbose test "$(commit_message HEAD)" = "Empty commit"
10394'
10495
105- # FAILURE: fatal: Could not parse object
106- test_expect_failure ' Rebase -Xsubtree --onto commit 5' '
107- reset_rebase &&
108- git checkout -b rebase-onto-5 master &&
109- git filter-branch --prune-empty -f --subdirectory-filter files_subtree &&
110- git commit -m "Empty commit" --allow-empty &&
111- git rebase -Xsubtree=files_subtree --onto files-master master &&
112- verbose test "$(commit_message HEAD~)" = "files_subtree/master5"
113- '
114- # FAILURE: fatal: Could not parse object
115- test_expect_failure ' Rebase -Xsubtree --onto empty commit' '
96+ test_expect_success ' Rebase -Xsubtree --keep-empty --rebase-merges --onto commit' '
11697 reset_rebase &&
117- git checkout -b rebase-onto-empty master &&
118- git filter-branch --prune-empty -f --subdirectory-filter files_subtree &&
119- git commit -m "Empty commit" --allow-empty &&
120- git rebase -Xsubtree=files_subtree --onto files-master master &&
98+ git checkout -b rebase-merges-onto to-rebase &&
99+ test_must_fail git rebase -Xsubtree=files_subtree --keep-empty --rebase-merges --onto files-master --root &&
100+ : first pick results in no changes &&
101+ git rebase --continue &&
102+ verbose test "$(commit_message HEAD~2)" = "master4" &&
103+ verbose test "$(commit_message HEAD~)" = "files_subtree/master5" &&
121104 verbose test "$(commit_message HEAD)" = "Empty commit"
122105'
123106
0 commit comments