d7f900969a5f6be4ad8f6a7e5a3c4ed6531a41f7
[git.git] / t / t1000-read-tree-m-3way.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2005 Junio C Hamano
4 #
5
6 test_description='Three way merge with read-tree -m
7
8 This test tries three-way merge with read-tree -m
9
10 There is one ancestor (called O for Original) and two branches A
11 and B derived from it.  We want to do a 3-way merge between A and
12 B, using O as the common ancestor.
13
14     merge A O B
15
16 Decisions are made by comparing contents of O, A and B pathname
17 by pathname.  The result is determined by the following guiding
18 principle:
19
20  - If only A does something to it and B does not touch it, take
21    whatever A does.
22
23  - If only B does something to it and A does not touch it, take
24    whatever B does.
25
26  - If both A and B does something but in the same way, take
27    whatever they do.
28
29  - If A and B does something but different things, we need a
30    3-way merge:
31
32    - We cannot do anything about the following cases:
33
34      * O does not have it.  A and B both must be adding to the
35        same path independently.
36
37      * A deletes it.  B must be modifying.
38
39    - Otherwise, A and B are modifying.  Run 3-way merge.
40
41 First, the case matrix.
42
43  - Vertical axis is for A'\''s actions.
44  - Horizontal axis is for B'\''s actions.
45
46 .----------------------------------------------------------------.
47 | A        B | No Action  |   Delete   |   Modify   |    Add     |
48 |------------+------------+------------+------------+------------|
49 | No Action  |            |            |            |            |
50 |            | select O   | delete     | select B   | select B   |
51 |            |            |            |            |            |
52 |------------+------------+------------+------------+------------|
53 | Delete     |            |            | ********** |    can     |
54 |            | delete     | delete     | merge      |    not     |
55 |            |            |            |            |  happen    |
56 |------------+------------+------------+------------+------------|
57 | Modify     |            | ********** | ?????????? |    can     |
58 |            | select A   | merge      | select A=B |    not     |
59 |            |            |            | merge      |  happen    |
60 |------------+------------+------------+------------+------------|
61 | Add        |            |    can     |    can     | ?????????? |
62 |            | select A   |    not     |    not     | select A=B |
63 |            |            |  happen    |  happen    | merge      |
64 .----------------------------------------------------------------.
65
66 In addition:
67
68  SS: a special case of MM, where A and B makes the same modification.
69  LL: a special case of AA, where A and B creates the same file.
70  TT: a special case of MM, where A and B makes mergeable changes.
71  DF: a special case, where A makes a directory and B makes a file.
72
73 '
74
75 . ./test-lib.sh
76
77 # Original tree.
78 mkdir Z
79 for a in N D M
80 do
81     for b in N D M
82     do
83         p=$a$b
84         echo This is $p from the original tree. >$p
85         echo This is Z/$p from the original tree. >Z/$p
86         test_expect_success \
87             "adding test file $p and Z/$p" \
88             'git-update-cache --add $p &&
89             git-update-cache --add Z/$p'
90     done
91 done
92 echo This is SS from the original tree. >SS
93 test_expect_success \
94     'adding test file SS' \
95     'git-update-cache --add SS'
96 cat >TT <<\EOF
97 This is a trivial merge sample text.
98 Branch A is expected to upcase this word, here.
99 There are some filler lines to avoid diff context
100 conflicts here,
101 like this one,
102 and this one,
103 and this one is yet another one of them.
104 At the very end, here comes another line, that is
105 the word, expected to be upcased by Branch B.
106 This concludes the trivial merge sample file.
107 EOF
108 test_expect_success \
109     'adding test file TT' \
110     'git-update-cache --add TT'
111 test_expect_success \
112     'prepare initial tree' \
113     'tree_O=$(git-write-tree)'
114
115 test_expect_success \
116     'commit initial tree' \
117     'commit_O=$(echo "Original tree for the merge test." |
118      git-commit-tree $tree_O)'
119 echo $commit_O >.git/HEAD-O
120
121 ################################################################
122 # Branch A and B makes the changes according to the above matrix.
123
124 ################################################################
125 # Branch A
126
127 to_remove=$(echo D? Z/D?)
128 rm -f $to_remove
129 test_expect_success \
130     'change in branch A (removal)' \
131     'git-update-cache --remove $to_remove'
132
133 for p in M? Z/M?
134 do
135     echo This is modified $p in the branch A. >$p
136     test_expect_success \
137         'change in branch A (modification)' \
138         "git-update-cache $p"
139 done
140
141 for p in AN AA Z/AN Z/AA
142 do
143     echo This is added $p in the branch A. >$p
144     test_expect_success \
145         'change in branch A (addition)' \
146         "git-update-cache --add $p"
147 done
148
149 echo This is SS from the modified tree. >SS
150 echo This is LL from the modified tree. >LL
151 test_expect_success \
152     'change in branch A (addition)' \
153     'git-update-cache --add LL &&
154      git-update-cache SS'
155 mv TT TT-
156 sed -e '/Branch A/s/word/WORD/g' <TT- >TT
157 rm -f TT-
158 test_expect_success \
159     'change in branch A (edit)' \
160     'git-update-cache TT'
161
162 mkdir DF
163 echo Branch A makes a file at DF/DF, creating a directory DF. >DF/DF
164 test_expect_success \
165     'change in branch A (change file to directory)' \
166     'git-update-cache --add DF/DF'
167
168 test_expect_success \
169     'recording branch A tree' \
170     'tree_A=$(git-write-tree)'
171 test_expect_success \
172     'committing branch A changes' \
173     'commit_A=$(echo "Branch A for the merge test." |
174            git-commit-tree $tree_A -p $commit_O)'
175 echo $commit_A >.git/HEAD-A
176            
177 ################################################################
178 # Branch B
179 # Start from O
180
181 rm -rf [NDMASLT][NDMASLT] Z DF
182 mkdir Z
183 test_expect_success \
184     'reading original tree and checking out' \
185     'git-read-tree $tree_O &&
186      git-checkout-cache -a'
187
188 to_remove=$(echo ?D Z/?D)
189 rm -f $to_remove
190 test_expect_success \
191     'change in branch B (removal)' \
192     "git-update-cache --remove $to_remove"
193
194 for p in ?M Z/?M
195 do
196     echo This is modified $p in the branch B. >$p
197     test_expect_success \
198         'change in branch B (modification)' \
199         "git-update-cache $p"
200 done
201
202 for p in NA AA Z/NA Z/AA
203 do
204     echo This is added $p in the branch B. >$p
205     test_expect_success \
206         'change in branch B (addition)' \
207         "git-update-cache --add $p"
208 done
209 echo This is SS from the modified tree. >SS
210 echo This is LL from the modified tree. >LL
211 test_expect_success \
212     'change in branch B (addition and modification)' \
213     'git-update-cache --add LL &&
214      git-update-cache SS'
215 mv TT TT-
216 sed -e '/Branch B/s/word/WORD/g' <TT- >TT
217 rm -f TT-
218 test_expect_success \
219     'change in branch B (modification)' \
220     'git-update-cache TT'
221
222 echo Branch B makes a file at DF. >DF
223 test_expect_success \
224     'change in branch B (addition of a file to conflict with directory)' \
225     'git-update-cache --add DF'
226
227 test_expect_success \
228     'recording branch B tree' \
229     'tree_B=$(git-write-tree)'
230 test_expect_success \
231     'committing branch B changes' \
232     'commit_B=$(echo "Branch B for the merge test." |
233            git-commit-tree $tree_B -p $commit_O)'
234 echo $commit_B >.git/HEAD-B
235
236 ################################################################
237 # Done preparation.
238
239 test_debug '
240     for T in O A B
241     do
242         echo "# $T $(eval git-cat-file commit \$commit_$T | sed -e 1q)"
243     done
244 '
245
246 ################################################################
247 # Try merging and showing the various diffs
248
249 test_expect_success \
250     '3-way merge with git-read-tree -m' \
251     "git-read-tree -m $tree_O $tree_A $tree_B"
252
253 strip_object_id='s/^\([0-7]*\) [0-9a-f]* \([0-3].*\)$/\1 \2/'
254
255 test_expect_success \
256     'git-ls-files --stage of the merge result' \
257     'git-ls-files --stage >current- &&
258      sed -e "$strip_object_id" <current- >current'
259
260 cat >expected <<\EOF
261 100644 2 AA
262 100644 3 AA
263 100644 2 AN
264 100644 1 DD
265 100644 3 DF
266 100644 2 DF/DF
267 100644 1 DM
268 100644 3 DM
269 100644 1 DN
270 100644 3 DN
271 100644 2 LL
272 100644 3 LL
273 100644 1 MD
274 100644 2 MD
275 100644 1 MM
276 100644 2 MM
277 100644 3 MM
278 100644 0 MN
279 100644 3 NA
280 100644 1 ND
281 100644 2 ND
282 100644 0 NM
283 100644 0 NN
284 100644 0 SS
285 100644 1 TT
286 100644 2 TT
287 100644 3 TT
288 100644 2 Z/AA
289 100644 3 Z/AA
290 100644 2 Z/AN
291 100644 1 Z/DD
292 100644 1 Z/DM
293 100644 3 Z/DM
294 100644 1 Z/DN
295 100644 3 Z/DN
296 100644 1 Z/MD
297 100644 2 Z/MD
298 100644 1 Z/MM
299 100644 2 Z/MM
300 100644 3 Z/MM
301 100644 0 Z/MN
302 100644 3 Z/NA
303 100644 1 Z/ND
304 100644 2 Z/ND
305 100644 0 Z/NM
306 100644 0 Z/NN
307 EOF
308
309 test_expect_success \
310     'validate merge result' \
311     'diff current expected'
312
313 test_done