1#!/bin/sh
2#
3# Copyright (c) 2017 Johannes E. Schindelin
4#
5
6test_description='git rebase -i --recreate-merges
7
8This test runs git rebase "interactively", retaining the branch structure by
9recreating merge commits.
10
11Initial setup:
12
13 -- B -- (first)
14 / \
15 A - C - D - E - H (master)
16 \ /
17 F - G (second)
18'
19. ./test-lib.sh
20. "$TEST_DIRECTORY"/lib-rebase.sh
21
22test_expect_success 'setup' '
23 write_script replace-editor.sh <<-\EOF &&
24 mv "$1" "$(git rev-parse --git-path ORIGINAL-TODO)"
25 cp script-from-scratch "$1"
26 EOF
27
28 test_commit A &&
29 git checkout -b first &&
30 test_commit B &&
31 git checkout master &&
32 test_commit C &&
33 test_commit D &&
34 git merge --no-commit B &&
35 test_tick &&
36 git commit -m E &&
37 git tag -m E E &&
38 git checkout -b second C &&
39 test_commit F &&
40 test_commit G &&
41 git checkout master &&
42 git merge --no-commit G &&
43 test_tick &&
44 git commit -m H &&
45 git tag -m H H
46'
47
48cat >script-from-scratch <<\EOF
49label onto
50
51# onebranch
52pick G
53pick D
54label onebranch
55
56# second
57reset onto
58pick B
59label second
60
61reset onto
62merge -C H second
63merge onebranch # Merge the topic branch 'onebranch'
64EOF
65
66test_cmp_graph () {
67 cat >expect &&
68 git log --graph --boundary --format=%s "$@" >output &&
69 sed "s/ *$//" <output >output.trimmed &&
70 test_cmp expect output.trimmed
71}
72
73test_expect_success 'create completely different structure' '
74 test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
75 test_tick &&
76 git rebase -i --recreate-merges A &&
77 test_cmp_graph <<-\EOF
78 * Merge the topic branch '\''onebranch'\''
79 |\
80 | * D
81 | * G
82 * | H
83 |\ \
84 | |/
85 |/|
86 | * B
87 |/
88 * A
89 EOF
90'
91
92test_expect_success 'generate correct todo list' '
93 cat >expect <<-\EOF &&
94 label onto
95
96 reset onto
97 pick d9df450 B
98 label E
99
100 reset onto
101 pick 5dee784 C
102 label branch-point
103 pick ca2c861 F
104 pick 088b00a G
105 label H
106
107 reset branch-point # C
108 pick 12bd07b D
109 merge -C 2051b56 E # E
110 merge -C 233d48a H # H
111
112 EOF
113
114 grep -v "^#" <.git/ORIGINAL-TODO >output &&
115 test_cmp expect output
116'
117
118test_expect_success 'with a branch tip that was cherry-picked already' '
119 git checkout -b already-upstream master &&
120 base="$(git rev-parse --verify HEAD)" &&
121
122 test_commit A1 &&
123 test_commit A2 &&
124 git reset --hard $base &&
125 test_commit B1 &&
126 test_tick &&
127 git merge -m "Merge branch A" A2 &&
128
129 git checkout -b upstream-with-a2 $base &&
130 test_tick &&
131 git cherry-pick A2 &&
132
133 git checkout already-upstream &&
134 test_tick &&
135 git rebase -i --recreate-merges upstream-with-a2 &&
136 test_cmp_graph upstream-with-a2.. <<-\EOF
137 * Merge branch A
138 |\
139 | * A1
140 * | B1
141 |/
142 o A2
143 EOF
144'
145
146test_expect_success 'do not rebase cousins unless asked for' '
147 write_script copy-editor.sh <<-\EOF &&
148 cp "$1" "$(git rev-parse --git-path ORIGINAL-TODO)"
149 EOF
150
151 test_config sequence.editor \""$PWD"/copy-editor.sh\" &&
152 git checkout -b cousins master &&
153 before="$(git rev-parse --verify HEAD)" &&
154 test_tick &&
155 git rebase -i --recreate-merges HEAD^ &&
156 test_cmp_rev HEAD $before &&
157 test_tick &&
158 git rebase -i --recreate-merges=rebase-cousins HEAD^ &&
159 test_cmp_graph HEAD^.. <<-\EOF
160 * Merge the topic branch '\''onebranch'\''
161 |\
162 | * D
163 | * G
164 |/
165 o H
166 EOF
167'
168
169test_expect_success 'refs/rewritten/* is worktree-local' '
170 git worktree add wt &&
171 cat >wt/script-from-scratch <<-\EOF &&
172 label xyz
173 exec GIT_DIR=../.git git rev-parse --verify refs/rewritten/xyz >a || :
174 exec git rev-parse --verify refs/rewritten/xyz >b
175 EOF
176
177 test_config -C wt sequence.editor \""$PWD"/replace-editor.sh\" &&
178 git -C wt rebase -i HEAD &&
179 test_must_be_empty wt/a &&
180 test_cmp_rev HEAD "$(cat wt/b)"
181'
182
183test_expect_success 'post-rewrite hook and fixups work for merges' '
184 git checkout -b post-rewrite &&
185 test_commit same1 &&
186 git reset --hard HEAD^ &&
187 test_commit same2 &&
188 git merge -m "to fix up" same1 &&
189 echo same old same old >same2.t &&
190 test_tick &&
191 git commit --fixup HEAD same2.t &&
192 fixup="$(git rev-parse HEAD)" &&
193
194 mkdir -p .git/hooks &&
195 test_when_finished "rm .git/hooks/post-rewrite" &&
196 echo "cat >actual" | write_script .git/hooks/post-rewrite &&
197
198 test_tick &&
199 git rebase -i --autosquash --recreate-merges HEAD^^^ &&
200 printf "%s %s\n%s %s\n%s %s\n%s %s\n" >expect $(git rev-parse \
201 $fixup^^2 HEAD^2 \
202 $fixup^^ HEAD^ \
203 $fixup^ HEAD \
204 $fixup HEAD) &&
205 test_cmp expect actual
206'
207
208test_done