##// END OF EJS Templates
merge: fix spurious merges for copies in linear updates...
Matt Mackall -
r4416:bb1800a7 default
parent child Browse files
Show More
@@ -1,525 +1,531 b''
1 # merge.py - directory-level update/merge handling for Mercurial
1 # merge.py - directory-level update/merge handling for Mercurial
2 #
2 #
3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from node import *
8 from node import *
9 from i18n import gettext as _
9 from i18n import gettext as _
10 from demandload import *
10 from demandload import *
11 demandload(globals(), "errno util os tempfile")
11 demandload(globals(), "errno util os tempfile context")
12
12
13 def filemerge(repo, fw, fo, wctx, mctx):
13 def filemerge(repo, fw, fo, wctx, mctx):
14 """perform a 3-way merge in the working directory
14 """perform a 3-way merge in the working directory
15
15
16 fw = filename in the working directory
16 fw = filename in the working directory
17 fo = filename in other parent
17 fo = filename in other parent
18 wctx, mctx = working and merge changecontexts
18 wctx, mctx = working and merge changecontexts
19 """
19 """
20
20
21 def temp(prefix, ctx):
21 def temp(prefix, ctx):
22 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
22 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
23 (fd, name) = tempfile.mkstemp(prefix=pre)
23 (fd, name) = tempfile.mkstemp(prefix=pre)
24 f = os.fdopen(fd, "wb")
24 f = os.fdopen(fd, "wb")
25 repo.wwrite(ctx.path(), ctx.data(), f)
25 repo.wwrite(ctx.path(), ctx.data(), f)
26 f.close()
26 f.close()
27 return name
27 return name
28
28
29 fcm = wctx.filectx(fw)
29 fcm = wctx.filectx(fw)
30 fco = mctx.filectx(fo)
30 fco = mctx.filectx(fo)
31
31
32 if not fco.cmp(fcm.data()): # files identical?
32 if not fco.cmp(fcm.data()): # files identical?
33 return None
33 return None
34
34
35 fca = fcm.ancestor(fco)
35 fca = fcm.ancestor(fco)
36 if not fca:
36 if not fca:
37 fca = repo.filectx(fw, fileid=nullrev)
37 fca = repo.filectx(fw, fileid=nullrev)
38 a = repo.wjoin(fw)
38 a = repo.wjoin(fw)
39 b = temp("base", fca)
39 b = temp("base", fca)
40 c = temp("other", fco)
40 c = temp("other", fco)
41
41
42 if fw != fo:
42 if fw != fo:
43 repo.ui.status(_("merging %s and %s\n") % (fw, fo))
43 repo.ui.status(_("merging %s and %s\n") % (fw, fo))
44 else:
44 else:
45 repo.ui.status(_("merging %s\n") % fw)
45 repo.ui.status(_("merging %s\n") % fw)
46
46
47 repo.ui.debug(_("my %s other %s ancestor %s\n") % (fcm, fco, fca))
47 repo.ui.debug(_("my %s other %s ancestor %s\n") % (fcm, fco, fca))
48
48
49 cmd = (os.environ.get("HGMERGE") or repo.ui.config("ui", "merge")
49 cmd = (os.environ.get("HGMERGE") or repo.ui.config("ui", "merge")
50 or "hgmerge")
50 or "hgmerge")
51 r = util.system('%s "%s" "%s" "%s"' % (cmd, a, b, c), cwd=repo.root,
51 r = util.system('%s "%s" "%s" "%s"' % (cmd, a, b, c), cwd=repo.root,
52 environ={'HG_FILE': fw,
52 environ={'HG_FILE': fw,
53 'HG_MY_NODE': str(wctx.parents()[0]),
53 'HG_MY_NODE': str(wctx.parents()[0]),
54 'HG_OTHER_NODE': str(mctx)})
54 'HG_OTHER_NODE': str(mctx)})
55 if r:
55 if r:
56 repo.ui.warn(_("merging %s failed!\n") % fw)
56 repo.ui.warn(_("merging %s failed!\n") % fw)
57
57
58 os.unlink(b)
58 os.unlink(b)
59 os.unlink(c)
59 os.unlink(c)
60 return r
60 return r
61
61
62 def checkunknown(wctx, mctx):
62 def checkunknown(wctx, mctx):
63 "check for collisions between unknown files and files in mctx"
63 "check for collisions between unknown files and files in mctx"
64 man = mctx.manifest()
64 man = mctx.manifest()
65 for f in wctx.unknown():
65 for f in wctx.unknown():
66 if f in man:
66 if f in man:
67 if mctx.filectx(f).cmp(wctx.filectx(f).data()):
67 if mctx.filectx(f).cmp(wctx.filectx(f).data()):
68 raise util.Abort(_("untracked local file '%s' differs"\
68 raise util.Abort(_("untracked local file '%s' differs"\
69 " from remote version") % f)
69 " from remote version") % f)
70
70
71 def checkcollision(mctx):
71 def checkcollision(mctx):
72 "check for case folding collisions in the destination context"
72 "check for case folding collisions in the destination context"
73 folded = {}
73 folded = {}
74 for fn in mctx.manifest():
74 for fn in mctx.manifest():
75 fold = fn.lower()
75 fold = fn.lower()
76 if fold in folded:
76 if fold in folded:
77 raise util.Abort(_("case-folding collision between %s and %s")
77 raise util.Abort(_("case-folding collision between %s and %s")
78 % (fn, folded[fold]))
78 % (fn, folded[fold]))
79 folded[fold] = fn
79 folded[fold] = fn
80
80
81 def forgetremoved(wctx, mctx):
81 def forgetremoved(wctx, mctx):
82 """
82 """
83 Forget removed files
83 Forget removed files
84
84
85 If we're jumping between revisions (as opposed to merging), and if
85 If we're jumping between revisions (as opposed to merging), and if
86 neither the working directory nor the target rev has the file,
86 neither the working directory nor the target rev has the file,
87 then we need to remove it from the dirstate, to prevent the
87 then we need to remove it from the dirstate, to prevent the
88 dirstate from listing the file when it is no longer in the
88 dirstate from listing the file when it is no longer in the
89 manifest.
89 manifest.
90 """
90 """
91
91
92 action = []
92 action = []
93 man = mctx.manifest()
93 man = mctx.manifest()
94 for f in wctx.deleted() + wctx.removed():
94 for f in wctx.deleted() + wctx.removed():
95 if f not in man:
95 if f not in man:
96 action.append((f, "f"))
96 action.append((f, "f"))
97
97
98 return action
98 return action
99
99
100 def findcopies(repo, m1, m2, ma, limit):
100 def findcopies(repo, m1, m2, ma, limit):
101 """
101 """
102 Find moves and copies between m1 and m2 back to limit linkrev
102 Find moves and copies between m1 and m2 back to limit linkrev
103 """
103 """
104
104
105 def nonoverlap(d1, d2, d3):
105 def nonoverlap(d1, d2, d3):
106 "Return list of elements in d1 not in d2 or d3"
106 "Return list of elements in d1 not in d2 or d3"
107 l = [d for d in d1 if d not in d3 and d not in d2]
107 l = [d for d in d1 if d not in d3 and d not in d2]
108 l.sort()
108 l.sort()
109 return l
109 return l
110
110
111 def dirname(f):
111 def dirname(f):
112 s = f.rfind("/")
112 s = f.rfind("/")
113 if s == -1:
113 if s == -1:
114 return ""
114 return ""
115 return f[:s]
115 return f[:s]
116
116
117 def dirs(files):
117 def dirs(files):
118 d = {}
118 d = {}
119 for f in files:
119 for f in files:
120 f = dirname(f)
120 f = dirname(f)
121 while f not in d:
121 while f not in d:
122 d[f] = True
122 d[f] = True
123 f = dirname(f)
123 f = dirname(f)
124 return d
124 return d
125
125
126 wctx = repo.workingctx()
127
128 def makectx(f, n):
129 if len(n) == 20:
130 return repo.filectx(f, fileid=n)
131 return wctx.filectx(f)
132 ctx = util.cachefunc(makectx)
133
126 def findold(fctx):
134 def findold(fctx):
127 "find files that path was copied from, back to linkrev limit"
135 "find files that path was copied from, back to linkrev limit"
128 old = {}
136 old = {}
129 seen = {}
137 seen = {}
130 orig = fctx.path()
138 orig = fctx.path()
131 visit = [fctx]
139 visit = [fctx]
132 while visit:
140 while visit:
133 fc = visit.pop()
141 fc = visit.pop()
134 s = str(fc)
142 s = str(fc)
135 if s in seen:
143 if s in seen:
136 continue
144 continue
137 seen[s] = 1
145 seen[s] = 1
138 if fc.path() != orig and fc.path() not in old:
146 if fc.path() != orig and fc.path() not in old:
139 old[fc.path()] = 1
147 old[fc.path()] = 1
140 if fc.rev() < limit:
148 if fc.rev() < limit:
141 continue
149 continue
142 visit += fc.parents()
150 visit += fc.parents()
143
151
144 old = old.keys()
152 old = old.keys()
145 old.sort()
153 old.sort()
146 return old
154 return old
147
155
148 copy = {}
156 copy = {}
149 fullcopy = {}
157 fullcopy = {}
150
158
151 def checkcopies(c, man):
159 def checkcopies(c, man):
152 '''check possible copies for filectx c'''
160 '''check possible copies for filectx c'''
153 for of in findold(c):
161 for of in findold(c):
154 if of not in man: # original file not in other manifest?
162 if of not in man: # original file not in other manifest?
155 continue
163 continue
156 c2 = ctx(of, man[of])
164 c2 = ctx(of, man[of])
157 ca = c.ancestor(c2)
165 ca = c.ancestor(c2)
158 if not ca: # unrelated?
166 if not ca: # unrelated?
159 continue
167 continue
160 # named changed on only one side?
168 # named changed on only one side?
161 if ca.path() == c.path() or ca.path() == c2.path():
169 if ca.path() == c.path() or ca.path() == c2.path():
162 fullcopy[c.path()] = of # remember for dir rename detection
170 fullcopy[c.path()] = of # remember for dir rename detection
163 if c == c2: # no merge needed, ignore copy
171 if c == ca or c2 == ca: # no merge needed, ignore copy
164 continue
172 continue
165 copy[c.path()] = of
173 copy[c.path()] = of
166
174
167 if not repo.ui.configbool("merge", "followcopies", True):
175 if not repo.ui.configbool("merge", "followcopies", True):
168 return {}
176 return {}
169
177
170 # avoid silly behavior for update from empty dir
178 # avoid silly behavior for update from empty dir
171 if not m1 or not m2 or not ma:
179 if not m1 or not m2 or not ma:
172 return {}
180 return {}
173
181
174 dcopies = repo.dirstate.copies()
175 u1 = nonoverlap(m1, m2, ma)
182 u1 = nonoverlap(m1, m2, ma)
176 u2 = nonoverlap(m2, m1, ma)
183 u2 = nonoverlap(m2, m1, ma)
177 ctx = util.cachefunc(lambda f, n: repo.filectx(f, fileid=n[:20]))
178
184
179 for f in u1:
185 for f in u1:
180 checkcopies(ctx(dcopies.get(f, f), m1[f]), m2)
186 checkcopies(ctx(f, m1[f]), m2)
181
187
182 for f in u2:
188 for f in u2:
183 checkcopies(ctx(f, m2[f]), m1)
189 checkcopies(ctx(f, m2[f]), m1)
184
190
185 if not fullcopy or not repo.ui.configbool("merge", "followdirs", True):
191 if not fullcopy or not repo.ui.configbool("merge", "followdirs", True):
186 return copy
192 return copy
187
193
188 # generate a directory move map
194 # generate a directory move map
189 d1, d2 = dirs(m1), dirs(m2)
195 d1, d2 = dirs(m1), dirs(m2)
190 invalid = {}
196 invalid = {}
191 dirmove = {}
197 dirmove = {}
192
198
193 # examine each file copy for a potential directory move, which is
199 # examine each file copy for a potential directory move, which is
194 # when all the files in a directory are moved to a new directory
200 # when all the files in a directory are moved to a new directory
195 for dst, src in fullcopy.items():
201 for dst, src in fullcopy.items():
196 dsrc, ddst = dirname(src), dirname(dst)
202 dsrc, ddst = dirname(src), dirname(dst)
197 if dsrc in invalid:
203 if dsrc in invalid:
198 # already seen to be uninteresting
204 # already seen to be uninteresting
199 continue
205 continue
200 elif dsrc in d1 and ddst in d1:
206 elif dsrc in d1 and ddst in d1:
201 # directory wasn't entirely moved locally
207 # directory wasn't entirely moved locally
202 invalid[dsrc] = True
208 invalid[dsrc] = True
203 elif dsrc in d2 and ddst in d2:
209 elif dsrc in d2 and ddst in d2:
204 # directory wasn't entirely moved remotely
210 # directory wasn't entirely moved remotely
205 invalid[dsrc] = True
211 invalid[dsrc] = True
206 elif dsrc in dirmove and dirmove[dsrc] != ddst:
212 elif dsrc in dirmove and dirmove[dsrc] != ddst:
207 # files from the same directory moved to two different places
213 # files from the same directory moved to two different places
208 invalid[dsrc] = True
214 invalid[dsrc] = True
209 else:
215 else:
210 # looks good so far
216 # looks good so far
211 dirmove[dsrc + "/"] = ddst + "/"
217 dirmove[dsrc + "/"] = ddst + "/"
212
218
213 for i in invalid:
219 for i in invalid:
214 if i in dirmove:
220 if i in dirmove:
215 del dirmove[i]
221 del dirmove[i]
216
222
217 del d1, d2, invalid
223 del d1, d2, invalid
218
224
219 if not dirmove:
225 if not dirmove:
220 return copy
226 return copy
221
227
222 # check unaccounted nonoverlapping files against directory moves
228 # check unaccounted nonoverlapping files against directory moves
223 for f in u1 + u2:
229 for f in u1 + u2:
224 if f not in fullcopy:
230 if f not in fullcopy:
225 for d in dirmove:
231 for d in dirmove:
226 if f.startswith(d):
232 if f.startswith(d):
227 # new file added in a directory that was moved, move it
233 # new file added in a directory that was moved, move it
228 copy[f] = dirmove[d] + f[len(d):]
234 copy[f] = dirmove[d] + f[len(d):]
229 break
235 break
230
236
231 return copy
237 return copy
232
238
233 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
239 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
234 """
240 """
235 Merge p1 and p2 with ancestor ma and generate merge action list
241 Merge p1 and p2 with ancestor ma and generate merge action list
236
242
237 overwrite = whether we clobber working files
243 overwrite = whether we clobber working files
238 partial = function to filter file lists
244 partial = function to filter file lists
239 """
245 """
240
246
241 repo.ui.note(_("resolving manifests\n"))
247 repo.ui.note(_("resolving manifests\n"))
242 repo.ui.debug(_(" overwrite %s partial %s\n") % (overwrite, bool(partial)))
248 repo.ui.debug(_(" overwrite %s partial %s\n") % (overwrite, bool(partial)))
243 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (pa, p1, p2))
249 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (pa, p1, p2))
244
250
245 m1 = p1.manifest()
251 m1 = p1.manifest()
246 m2 = p2.manifest()
252 m2 = p2.manifest()
247 ma = pa.manifest()
253 ma = pa.manifest()
248 backwards = (pa == p2)
254 backwards = (pa == p2)
249 action = []
255 action = []
250 copy = {}
256 copy = {}
251
257
252 def fmerge(f, f2=None, fa=None):
258 def fmerge(f, f2=None, fa=None):
253 """merge executable flags"""
259 """merge executable flags"""
254 if not f2:
260 if not f2:
255 f2 = f
261 f2 = f
256 fa = f
262 fa = f
257 a, b, c = ma.execf(fa), m1.execf(f), m2.execf(f2)
263 a, b, c = ma.execf(fa), m1.execf(f), m2.execf(f2)
258 return ((a^b) | (a^c)) ^ a
264 return ((a^b) | (a^c)) ^ a
259
265
260 def act(msg, m, f, *args):
266 def act(msg, m, f, *args):
261 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
267 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
262 action.append((f, m) + args)
268 action.append((f, m) + args)
263
269
264 if not (backwards or overwrite):
270 if not (backwards or overwrite):
265 copy = findcopies(repo, m1, m2, ma, pa.rev())
271 copy = findcopies(repo, m1, m2, ma, pa.rev())
266 copied = dict.fromkeys(copy.values())
272 copied = dict.fromkeys(copy.values())
267
273
268 # Compare manifests
274 # Compare manifests
269 for f, n in m1.iteritems():
275 for f, n in m1.iteritems():
270 if partial and not partial(f):
276 if partial and not partial(f):
271 continue
277 continue
272 if f in m2:
278 if f in m2:
273 # are files different?
279 # are files different?
274 if n != m2[f]:
280 if n != m2[f]:
275 a = ma.get(f, nullid)
281 a = ma.get(f, nullid)
276 # are both different from the ancestor?
282 # are both different from the ancestor?
277 if not overwrite and n != a and m2[f] != a:
283 if not overwrite and n != a and m2[f] != a:
278 act("versions differ", "m", f, f, f, fmerge(f), False)
284 act("versions differ", "m", f, f, f, fmerge(f), False)
279 # are we clobbering?
285 # are we clobbering?
280 # is remote's version newer?
286 # is remote's version newer?
281 # or are we going back in time and clean?
287 # or are we going back in time and clean?
282 elif overwrite or m2[f] != a or (backwards and not n[20:]):
288 elif overwrite or m2[f] != a or (backwards and not n[20:]):
283 act("remote is newer", "g", f, m2.execf(f))
289 act("remote is newer", "g", f, m2.execf(f))
284 # local is newer, not overwrite, check mode bits
290 # local is newer, not overwrite, check mode bits
285 elif fmerge(f) != m1.execf(f):
291 elif fmerge(f) != m1.execf(f):
286 act("update permissions", "e", f, m2.execf(f))
292 act("update permissions", "e", f, m2.execf(f))
287 # contents same, check mode bits
293 # contents same, check mode bits
288 elif m1.execf(f) != m2.execf(f):
294 elif m1.execf(f) != m2.execf(f):
289 if overwrite or fmerge(f) != m1.execf(f):
295 if overwrite or fmerge(f) != m1.execf(f):
290 act("update permissions", "e", f, m2.execf(f))
296 act("update permissions", "e", f, m2.execf(f))
291 elif f in copied:
297 elif f in copied:
292 continue
298 continue
293 elif f in copy:
299 elif f in copy:
294 f2 = copy[f]
300 f2 = copy[f]
295 if f2 not in m2: # directory rename
301 if f2 not in m2: # directory rename
296 act("remote renamed directory to " + f2, "d",
302 act("remote renamed directory to " + f2, "d",
297 f, None, f2, m1.execf(f))
303 f, None, f2, m1.execf(f))
298 elif f2 in m1: # case 2 A,B/B/B
304 elif f2 in m1: # case 2 A,B/B/B
299 act("local copied to " + f2, "m",
305 act("local copied to " + f2, "m",
300 f, f2, f, fmerge(f, f2, f2), False)
306 f, f2, f, fmerge(f, f2, f2), False)
301 else: # case 4,21 A/B/B
307 else: # case 4,21 A/B/B
302 act("local moved to " + f2, "m",
308 act("local moved to " + f2, "m",
303 f, f2, f, fmerge(f, f2, f2), False)
309 f, f2, f, fmerge(f, f2, f2), False)
304 elif f in ma:
310 elif f in ma:
305 if n != ma[f] and not overwrite:
311 if n != ma[f] and not overwrite:
306 if repo.ui.prompt(
312 if repo.ui.prompt(
307 (_(" local changed %s which remote deleted\n") % f) +
313 (_(" local changed %s which remote deleted\n") % f) +
308 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("d"):
314 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("d"):
309 act("prompt delete", "r", f)
315 act("prompt delete", "r", f)
310 else:
316 else:
311 act("other deleted", "r", f)
317 act("other deleted", "r", f)
312 else:
318 else:
313 # file is created on branch or in working directory
319 # file is created on branch or in working directory
314 if (overwrite and n[20:] != "u") or (backwards and not n[20:]):
320 if (overwrite and n[20:] != "u") or (backwards and not n[20:]):
315 act("remote deleted", "r", f)
321 act("remote deleted", "r", f)
316
322
317 for f, n in m2.iteritems():
323 for f, n in m2.iteritems():
318 if partial and not partial(f):
324 if partial and not partial(f):
319 continue
325 continue
320 if f in m1:
326 if f in m1:
321 continue
327 continue
322 if f in copied:
328 if f in copied:
323 continue
329 continue
324 if f in copy:
330 if f in copy:
325 f2 = copy[f]
331 f2 = copy[f]
326 if f2 not in m1: # directory rename
332 if f2 not in m1: # directory rename
327 act("local renamed directory to " + f2, "d",
333 act("local renamed directory to " + f2, "d",
328 None, f, f2, m2.execf(f))
334 None, f, f2, m2.execf(f))
329 elif f2 in m2: # rename case 1, A/A,B/A
335 elif f2 in m2: # rename case 1, A/A,B/A
330 act("remote copied to " + f, "m",
336 act("remote copied to " + f, "m",
331 f2, f, f, fmerge(f2, f, f2), False)
337 f2, f, f, fmerge(f2, f, f2), False)
332 else: # case 3,20 A/B/A
338 else: # case 3,20 A/B/A
333 act("remote moved to " + f, "m",
339 act("remote moved to " + f, "m",
334 f2, f, f, fmerge(f2, f, f2), True)
340 f2, f, f, fmerge(f2, f, f2), True)
335 elif f in ma:
341 elif f in ma:
336 if overwrite or backwards:
342 if overwrite or backwards:
337 act("recreating", "g", f, m2.execf(f))
343 act("recreating", "g", f, m2.execf(f))
338 elif n != ma[f]:
344 elif n != ma[f]:
339 if repo.ui.prompt(
345 if repo.ui.prompt(
340 (_("remote changed %s which local deleted\n") % f) +
346 (_("remote changed %s which local deleted\n") % f) +
341 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("k"):
347 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("k"):
342 act("prompt recreating", "g", f, m2.execf(f))
348 act("prompt recreating", "g", f, m2.execf(f))
343 else:
349 else:
344 act("remote created", "g", f, m2.execf(f))
350 act("remote created", "g", f, m2.execf(f))
345
351
346 return action
352 return action
347
353
348 def applyupdates(repo, action, wctx, mctx):
354 def applyupdates(repo, action, wctx, mctx):
349 "apply the merge action list to the working directory"
355 "apply the merge action list to the working directory"
350
356
351 updated, merged, removed, unresolved = 0, 0, 0, 0
357 updated, merged, removed, unresolved = 0, 0, 0, 0
352 action.sort()
358 action.sort()
353 for a in action:
359 for a in action:
354 f, m = a[:2]
360 f, m = a[:2]
355 if f and f[0] == "/":
361 if f and f[0] == "/":
356 continue
362 continue
357 if m == "r": # remove
363 if m == "r": # remove
358 repo.ui.note(_("removing %s\n") % f)
364 repo.ui.note(_("removing %s\n") % f)
359 util.audit_path(f)
365 util.audit_path(f)
360 try:
366 try:
361 util.unlink(repo.wjoin(f))
367 util.unlink(repo.wjoin(f))
362 except OSError, inst:
368 except OSError, inst:
363 if inst.errno != errno.ENOENT:
369 if inst.errno != errno.ENOENT:
364 repo.ui.warn(_("update failed to remove %s: %s!\n") %
370 repo.ui.warn(_("update failed to remove %s: %s!\n") %
365 (f, inst.strerror))
371 (f, inst.strerror))
366 removed += 1
372 removed += 1
367 elif m == "m": # merge
373 elif m == "m": # merge
368 f2, fd, flag, move = a[2:]
374 f2, fd, flag, move = a[2:]
369 r = filemerge(repo, f, f2, wctx, mctx)
375 r = filemerge(repo, f, f2, wctx, mctx)
370 if r > 0:
376 if r > 0:
371 unresolved += 1
377 unresolved += 1
372 else:
378 else:
373 if r is None:
379 if r is None:
374 updated += 1
380 updated += 1
375 else:
381 else:
376 merged += 1
382 merged += 1
377 if f != fd:
383 if f != fd:
378 repo.ui.debug(_("copying %s to %s\n") % (f, fd))
384 repo.ui.debug(_("copying %s to %s\n") % (f, fd))
379 repo.wwrite(fd, repo.wread(f))
385 repo.wwrite(fd, repo.wread(f))
380 if move:
386 if move:
381 repo.ui.debug(_("removing %s\n") % f)
387 repo.ui.debug(_("removing %s\n") % f)
382 os.unlink(repo.wjoin(f))
388 os.unlink(repo.wjoin(f))
383 util.set_exec(repo.wjoin(fd), flag)
389 util.set_exec(repo.wjoin(fd), flag)
384 elif m == "g": # get
390 elif m == "g": # get
385 flag = a[2]
391 flag = a[2]
386 repo.ui.note(_("getting %s\n") % f)
392 repo.ui.note(_("getting %s\n") % f)
387 t = mctx.filectx(f).data()
393 t = mctx.filectx(f).data()
388 repo.wwrite(f, t)
394 repo.wwrite(f, t)
389 util.set_exec(repo.wjoin(f), flag)
395 util.set_exec(repo.wjoin(f), flag)
390 updated += 1
396 updated += 1
391 elif m == "d": # directory rename
397 elif m == "d": # directory rename
392 f2, fd, flag = a[2:]
398 f2, fd, flag = a[2:]
393 if f:
399 if f:
394 repo.ui.note(_("moving %s to %s\n") % (f, fd))
400 repo.ui.note(_("moving %s to %s\n") % (f, fd))
395 t = wctx.filectx(f).data()
401 t = wctx.filectx(f).data()
396 repo.wwrite(fd, t)
402 repo.wwrite(fd, t)
397 util.set_exec(repo.wjoin(fd), flag)
403 util.set_exec(repo.wjoin(fd), flag)
398 util.unlink(repo.wjoin(f))
404 util.unlink(repo.wjoin(f))
399 if f2:
405 if f2:
400 repo.ui.note(_("getting %s to %s\n") % (f2, fd))
406 repo.ui.note(_("getting %s to %s\n") % (f2, fd))
401 t = mctx.filectx(f2).data()
407 t = mctx.filectx(f2).data()
402 repo.wwrite(fd, t)
408 repo.wwrite(fd, t)
403 util.set_exec(repo.wjoin(fd), flag)
409 util.set_exec(repo.wjoin(fd), flag)
404 updated += 1
410 updated += 1
405 elif m == "e": # exec
411 elif m == "e": # exec
406 flag = a[2]
412 flag = a[2]
407 util.set_exec(repo.wjoin(f), flag)
413 util.set_exec(repo.wjoin(f), flag)
408
414
409 return updated, merged, removed, unresolved
415 return updated, merged, removed, unresolved
410
416
411 def recordupdates(repo, action, branchmerge):
417 def recordupdates(repo, action, branchmerge):
412 "record merge actions to the dirstate"
418 "record merge actions to the dirstate"
413
419
414 for a in action:
420 for a in action:
415 f, m = a[:2]
421 f, m = a[:2]
416 if m == "r": # remove
422 if m == "r": # remove
417 if branchmerge:
423 if branchmerge:
418 repo.dirstate.update([f], 'r')
424 repo.dirstate.update([f], 'r')
419 else:
425 else:
420 repo.dirstate.forget([f])
426 repo.dirstate.forget([f])
421 elif m == "f": # forget
427 elif m == "f": # forget
422 repo.dirstate.forget([f])
428 repo.dirstate.forget([f])
423 elif m == "g": # get
429 elif m == "g": # get
424 if branchmerge:
430 if branchmerge:
425 repo.dirstate.update([f], 'n', st_mtime=-1)
431 repo.dirstate.update([f], 'n', st_mtime=-1)
426 else:
432 else:
427 repo.dirstate.update([f], 'n')
433 repo.dirstate.update([f], 'n')
428 elif m == "m": # merge
434 elif m == "m": # merge
429 f2, fd, flag, move = a[2:]
435 f2, fd, flag, move = a[2:]
430 if branchmerge:
436 if branchmerge:
431 # We've done a branch merge, mark this file as merged
437 # We've done a branch merge, mark this file as merged
432 # so that we properly record the merger later
438 # so that we properly record the merger later
433 repo.dirstate.update([fd], 'm')
439 repo.dirstate.update([fd], 'm')
434 if f != f2: # copy/rename
440 if f != f2: # copy/rename
435 if move:
441 if move:
436 repo.dirstate.update([f], 'r')
442 repo.dirstate.update([f], 'r')
437 if f != fd:
443 if f != fd:
438 repo.dirstate.copy(f, fd)
444 repo.dirstate.copy(f, fd)
439 else:
445 else:
440 repo.dirstate.copy(f2, fd)
446 repo.dirstate.copy(f2, fd)
441 else:
447 else:
442 # We've update-merged a locally modified file, so
448 # We've update-merged a locally modified file, so
443 # we set the dirstate to emulate a normal checkout
449 # we set the dirstate to emulate a normal checkout
444 # of that file some time in the past. Thus our
450 # of that file some time in the past. Thus our
445 # merge will appear as a normal local file
451 # merge will appear as a normal local file
446 # modification.
452 # modification.
447 repo.dirstate.update([fd], 'n', st_size=-1, st_mtime=-1)
453 repo.dirstate.update([fd], 'n', st_size=-1, st_mtime=-1)
448 if move:
454 if move:
449 repo.dirstate.forget([f])
455 repo.dirstate.forget([f])
450 elif m == "d": # directory rename
456 elif m == "d": # directory rename
451 f2, fd, flag = a[2:]
457 f2, fd, flag = a[2:]
452 if branchmerge:
458 if branchmerge:
453 repo.dirstate.update([fd], 'a')
459 repo.dirstate.update([fd], 'a')
454 if f:
460 if f:
455 repo.dirstate.update([f], 'r')
461 repo.dirstate.update([f], 'r')
456 repo.dirstate.copy(f, fd)
462 repo.dirstate.copy(f, fd)
457 if f2:
463 if f2:
458 repo.dirstate.copy(f2, fd)
464 repo.dirstate.copy(f2, fd)
459 else:
465 else:
460 repo.dirstate.update([fd], 'n')
466 repo.dirstate.update([fd], 'n')
461 if f:
467 if f:
462 repo.dirstate.forget([f])
468 repo.dirstate.forget([f])
463
469
464 def update(repo, node, branchmerge, force, partial, wlock):
470 def update(repo, node, branchmerge, force, partial, wlock):
465 """
471 """
466 Perform a merge between the working directory and the given node
472 Perform a merge between the working directory and the given node
467
473
468 branchmerge = whether to merge between branches
474 branchmerge = whether to merge between branches
469 force = whether to force branch merging or file overwriting
475 force = whether to force branch merging or file overwriting
470 partial = a function to filter file lists (dirstate not updated)
476 partial = a function to filter file lists (dirstate not updated)
471 wlock = working dir lock, if already held
477 wlock = working dir lock, if already held
472 """
478 """
473
479
474 if not wlock:
480 if not wlock:
475 wlock = repo.wlock()
481 wlock = repo.wlock()
476
482
477 overwrite = force and not branchmerge
483 overwrite = force and not branchmerge
478 forcemerge = force and branchmerge
484 forcemerge = force and branchmerge
479 wc = repo.workingctx()
485 wc = repo.workingctx()
480 pl = wc.parents()
486 pl = wc.parents()
481 p1, p2 = pl[0], repo.changectx(node)
487 p1, p2 = pl[0], repo.changectx(node)
482 pa = p1.ancestor(p2)
488 pa = p1.ancestor(p2)
483 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
489 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
484
490
485 ### check phase
491 ### check phase
486 if not overwrite and len(pl) > 1:
492 if not overwrite and len(pl) > 1:
487 raise util.Abort(_("outstanding uncommitted merges"))
493 raise util.Abort(_("outstanding uncommitted merges"))
488 if pa == p1 or pa == p2: # is there a linear path from p1 to p2?
494 if pa == p1 or pa == p2: # is there a linear path from p1 to p2?
489 if branchmerge:
495 if branchmerge:
490 raise util.Abort(_("there is nothing to merge, just use "
496 raise util.Abort(_("there is nothing to merge, just use "
491 "'hg update' or look at 'hg heads'"))
497 "'hg update' or look at 'hg heads'"))
492 elif not (overwrite or branchmerge):
498 elif not (overwrite or branchmerge):
493 raise util.Abort(_("update spans branches, use 'hg merge' "
499 raise util.Abort(_("update spans branches, use 'hg merge' "
494 "or 'hg update -C' to lose changes"))
500 "or 'hg update -C' to lose changes"))
495 if branchmerge and not forcemerge:
501 if branchmerge and not forcemerge:
496 if wc.files():
502 if wc.files():
497 raise util.Abort(_("outstanding uncommitted changes"))
503 raise util.Abort(_("outstanding uncommitted changes"))
498
504
499 ### calculate phase
505 ### calculate phase
500 action = []
506 action = []
501 if not force:
507 if not force:
502 checkunknown(wc, p2)
508 checkunknown(wc, p2)
503 if not util.checkfolding(repo.path):
509 if not util.checkfolding(repo.path):
504 checkcollision(p2)
510 checkcollision(p2)
505 if not branchmerge:
511 if not branchmerge:
506 action += forgetremoved(wc, p2)
512 action += forgetremoved(wc, p2)
507 action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
513 action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
508
514
509 ### apply phase
515 ### apply phase
510 if not branchmerge: # just jump to the new rev
516 if not branchmerge: # just jump to the new rev
511 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
517 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
512 if not partial:
518 if not partial:
513 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
519 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
514
520
515 stats = applyupdates(repo, action, wc, p2)
521 stats = applyupdates(repo, action, wc, p2)
516
522
517 if not partial:
523 if not partial:
518 recordupdates(repo, action, branchmerge)
524 recordupdates(repo, action, branchmerge)
519 repo.dirstate.setparents(fp1, fp2)
525 repo.dirstate.setparents(fp1, fp2)
520 if not branchmerge:
526 if not branchmerge:
521 repo.dirstate.setbranch(p2.branch())
527 repo.dirstate.setbranch(p2.branch())
522 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
528 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
523
529
524 return stats
530 return stats
525
531
@@ -1,67 +1,67 b''
1 # revision 0
1 # revision 0
2 adding copy
2 adding copy
3 adding move
3 adding move
4 adding remove
4 adding remove
5 adding unchanged
5 adding unchanged
6 adding zzz1_merge_ok
6 adding zzz1_merge_ok
7 adding zzz2_merge_bad
7 adding zzz2_merge_bad
8 # revision 1
8 # revision 1
9 # local changes to revision 0
9 # local changes to revision 0
10 4 files updated, 0 files merged, 3 files removed, 0 files unresolved
10 4 files updated, 0 files merged, 3 files removed, 0 files unresolved
11 --- a/zzz1_merge_ok
11 --- a/zzz1_merge_ok
12 +++ b/zzz1_merge_ok
12 +++ b/zzz1_merge_ok
13 +new last line
13 +new last line
14 --- a/zzz2_merge_bad
14 --- a/zzz2_merge_bad
15 +++ b/zzz2_merge_bad
15 +++ b/zzz2_merge_bad
16 +another last line
16 +another last line
17 M zzz1_merge_ok
17 M zzz1_merge_ok
18 M zzz2_merge_bad
18 M zzz2_merge_bad
19 # local merge with bad merge tool
19 # local merge with bad merge tool
20 merging zzz1_merge_ok
20 merging zzz1_merge_ok
21 merging zzz1_merge_ok failed!
21 merging zzz1_merge_ok failed!
22 merging zzz2_merge_bad
22 merging zzz2_merge_bad
23 merging zzz2_merge_bad failed!
23 merging zzz2_merge_bad failed!
24 3 files updated, 0 files merged, 1 files removed, 2 files unresolved
24 3 files updated, 0 files merged, 2 files removed, 2 files unresolved
25 There are unresolved merges with locally modified files.
25 There are unresolved merges with locally modified files.
26 You can redo the full merge using:
26 You can redo the full merge using:
27 hg update 0
27 hg update 0
28 hg update 1
28 hg update 1
29 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
29 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
30 --- a/zzz1_merge_ok
30 --- a/zzz1_merge_ok
31 +++ b/zzz1_merge_ok
31 +++ b/zzz1_merge_ok
32 +new last line
32 +new last line
33 --- a/zzz2_merge_bad
33 --- a/zzz2_merge_bad
34 +++ b/zzz2_merge_bad
34 +++ b/zzz2_merge_bad
35 +another last line
35 +another last line
36 M zzz1_merge_ok
36 M zzz1_merge_ok
37 M zzz2_merge_bad
37 M zzz2_merge_bad
38 # local merge with conflicts
38 # local merge with conflicts
39 merge: warning: conflicts during merge
39 merge: warning: conflicts during merge
40 merging zzz1_merge_ok
40 merging zzz1_merge_ok
41 merging zzz2_merge_bad
41 merging zzz2_merge_bad
42 merging zzz2_merge_bad failed!
42 merging zzz2_merge_bad failed!
43 3 files updated, 1 files merged, 1 files removed, 1 files unresolved
43 3 files updated, 1 files merged, 2 files removed, 1 files unresolved
44 There are unresolved merges with locally modified files.
44 There are unresolved merges with locally modified files.
45 You can finish the partial merge using:
45 You can finish the partial merge using:
46 hg update 0
46 hg update 0
47 hg update 1
47 hg update 1
48 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
48 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
49 --- a/zzz1_merge_ok
49 --- a/zzz1_merge_ok
50 +++ b/zzz1_merge_ok
50 +++ b/zzz1_merge_ok
51 +new first line
51 +new first line
52 +new last line
52 +new last line
53 --- a/zzz2_merge_bad
53 --- a/zzz2_merge_bad
54 +++ b/zzz2_merge_bad
54 +++ b/zzz2_merge_bad
55 +another last line
55 +another last line
56 +=======
56 +=======
57 +new last line
57 +new last line
58 M zzz1_merge_ok
58 M zzz1_merge_ok
59 M zzz2_merge_bad
59 M zzz2_merge_bad
60 # local merge without conflicts
60 # local merge without conflicts
61 merging zzz1_merge_ok
61 merging zzz1_merge_ok
62 4 files updated, 1 files merged, 1 files removed, 0 files unresolved
62 4 files updated, 1 files merged, 2 files removed, 0 files unresolved
63 --- a/zzz1_merge_ok
63 --- a/zzz1_merge_ok
64 +++ b/zzz1_merge_ok
64 +++ b/zzz1_merge_ok
65 +new last line
65 +new last line
66 M zzz1_merge_ok
66 M zzz1_merge_ok
67 ? zzz2_merge_bad.orig
67 ? zzz2_merge_bad.orig
@@ -1,10 +1,9 b''
1 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2 pulling from ../a
2 pulling from ../a
3 searching for changes
3 searching for changes
4 adding changesets
4 adding changesets
5 adding manifests
5 adding manifests
6 adding file changes
6 adding file changes
7 added 2 changesets with 2 changes to 1 files
7 added 2 changesets with 2 changes to 1 files
8 (run 'hg update' to get a working copy)
8 (run 'hg update' to get a working copy)
9 merging a and b
9 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
10 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
@@ -1,48 +1,42 b''
1 adding a/a
1 adding a/a
2 adding a/b
2 adding a/b
3 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
3 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 copying a/a to b/a
4 copying a/a to b/a
5 copying a/b to b/b
5 copying a/b to b/b
6 removing a/a
6 removing a/a
7 removing a/b
7 removing a/b
8 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
8 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
9 resolving manifests
9 resolving manifests
10 overwrite None partial False
10 overwrite None partial False
11 ancestor f9b20c0d4c51 local ce36d17b18fb+ remote 55119e611c80
11 ancestor f9b20c0d4c51 local ce36d17b18fb+ remote 55119e611c80
12 a/c: remote renamed directory to b/c -> d
12 a/c: remote renamed directory to b/c -> d
13 a/a: remote moved to b/a -> m
13 a/b: other deleted -> r
14 a/b: remote moved to b/b -> m
14 a/a: other deleted -> r
15 copying a/a to b/a
15 b/a: remote created -> g
16 b/b: remote created -> g
16 removing a/a
17 removing a/a
17 copying a/b to b/b
18 removing a/b
18 removing a/b
19 moving a/c to b/c
19 moving a/c to b/c
20 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
20 getting b/a
21 getting b/b
22 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
21 (branch merge, don't forget to commit)
23 (branch merge, don't forget to commit)
22 a/* b/a b/b b/c
24 a/* b/a b/b b/c
23 M b/a
25 M b/a
24 a/a
25 M b/b
26 M b/b
26 a/b
27 A b/c
27 A b/c
28 a/c
28 a/c
29 R a/a
29 R a/a
30 R a/b
30 R a/b
31 R a/c
31 R a/c
32 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
32 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
33 resolving manifests
33 resolving manifests
34 overwrite None partial False
34 overwrite None partial False
35 ancestor f9b20c0d4c51 local 55119e611c80+ remote ce36d17b18fb
35 ancestor f9b20c0d4c51 local 55119e611c80+ remote ce36d17b18fb
36 b/a: local moved to a/a -> m
37 b/b: local moved to a/b -> m
38 None: local renamed directory to b/c -> d
36 None: local renamed directory to b/c -> d
39 getting a/c to b/c
37 getting a/c to b/c
40 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
38 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
41 (branch merge, don't forget to commit)
39 (branch merge, don't forget to commit)
42 a/* b/a b/b b/c
40 a/* b/a b/b b/c
43 M b/a
44 a/a
45 M b/b
46 a/b
47 A b/c
41 A b/c
48 a/c
42 a/c
@@ -1,21 +1,19 b''
1 adding a/f
1 adding a/f
2 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
3 copying a/f to b/f
3 copying a/f to b/f
4 removing a/f
4 removing a/f
5 adding a/aa/g
5 adding a/aa/g
6 pulling from ../r2
6 pulling from ../r2
7 searching for changes
7 searching for changes
8 adding changesets
8 adding changesets
9 adding manifests
9 adding manifests
10 adding file changes
10 adding file changes
11 added 1 changesets with 1 changes to 1 files (+1 heads)
11 added 1 changesets with 1 changes to 1 files (+1 heads)
12 (run 'hg heads' to see heads, 'hg merge' to merge)
12 (run 'hg heads' to see heads, 'hg merge' to merge)
13 merging a/f and b/f
13 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
14 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
15 (branch merge, don't forget to commit)
14 (branch merge, don't forget to commit)
16 M b/f
15 M b/f
17 a/f
18 A b/aa/g
16 A b/aa/g
19 a/aa/g
17 a/aa/g
20 R a/aa/g
18 R a/aa/g
21 R a/f
19 R a/f
@@ -1,414 +1,409 b''
1 --------------
1 --------------
2 test L:up a R:nc a b W: - 1 get local a to b
2 test L:up a R:nc a b W: - 1 get local a to b
3 --------------
3 --------------
4 resolving manifests
4 resolving manifests
5 overwrite None partial False
5 overwrite None partial False
6 ancestor 924404dff337 local e300d1c794ec+ remote 735846fee2d7
6 ancestor 924404dff337 local e300d1c794ec+ remote 735846fee2d7
7 rev: versions differ -> m
7 rev: versions differ -> m
8 a: remote copied to b -> m
8 a: remote copied to b -> m
9 merging a and b
9 merging a and b
10 my a@e300d1c794ec+ other b@735846fee2d7 ancestor a@924404dff337
10 my a@e300d1c794ec+ other b@735846fee2d7 ancestor a@924404dff337
11 copying a to b
11 copying a to b
12 merging rev
12 merging rev
13 my rev@e300d1c794ec+ other rev@735846fee2d7 ancestor rev@924404dff337
13 my rev@e300d1c794ec+ other rev@735846fee2d7 ancestor rev@924404dff337
14 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
14 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
15 (branch merge, don't forget to commit)
15 (branch merge, don't forget to commit)
16 --------------
16 --------------
17 M a
17 M a
18 M b
18 M b
19 a
19 a
20 --------------
20 --------------
21
21
22 --------------
22 --------------
23 test L:nc a b R:up a W: - 2 get rem change to a and b
23 test L:nc a b R:up a W: - 2 get rem change to a and b
24 --------------
24 --------------
25 resolving manifests
25 resolving manifests
26 overwrite None partial False
26 overwrite None partial False
27 ancestor 924404dff337 local ac809aeed39a+ remote f4db7e329e71
27 ancestor 924404dff337 local ac809aeed39a+ remote f4db7e329e71
28 a: remote is newer -> g
28 a: remote is newer -> g
29 b: local copied to a -> m
29 b: local copied to a -> m
30 rev: versions differ -> m
30 rev: versions differ -> m
31 getting a
31 getting a
32 merging b and a
32 merging b and a
33 my b@ac809aeed39a+ other a@f4db7e329e71 ancestor a@924404dff337
33 my b@ac809aeed39a+ other a@f4db7e329e71 ancestor a@924404dff337
34 merging rev
34 merging rev
35 my rev@ac809aeed39a+ other rev@f4db7e329e71 ancestor rev@924404dff337
35 my rev@ac809aeed39a+ other rev@f4db7e329e71 ancestor rev@924404dff337
36 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
36 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
37 (branch merge, don't forget to commit)
37 (branch merge, don't forget to commit)
38 --------------
38 --------------
39 M a
39 M a
40 M b
40 M b
41 a
41 a
42 --------------
42 --------------
43
43
44 --------------
44 --------------
45 test L:up a R:nm a b W: - 3 get local a change to b, remove a
45 test L:up a R:nm a b W: - 3 get local a change to b, remove a
46 --------------
46 --------------
47 resolving manifests
47 resolving manifests
48 overwrite None partial False
48 overwrite None partial False
49 ancestor 924404dff337 local e300d1c794ec+ remote e03727d2d66b
49 ancestor 924404dff337 local e300d1c794ec+ remote e03727d2d66b
50 rev: versions differ -> m
50 rev: versions differ -> m
51 a: remote moved to b -> m
51 a: remote moved to b -> m
52 merging a and b
52 merging a and b
53 my a@e300d1c794ec+ other b@e03727d2d66b ancestor a@924404dff337
53 my a@e300d1c794ec+ other b@e03727d2d66b ancestor a@924404dff337
54 copying a to b
54 copying a to b
55 removing a
55 removing a
56 merging rev
56 merging rev
57 my rev@e300d1c794ec+ other rev@e03727d2d66b ancestor rev@924404dff337
57 my rev@e300d1c794ec+ other rev@e03727d2d66b ancestor rev@924404dff337
58 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
58 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
59 (branch merge, don't forget to commit)
59 (branch merge, don't forget to commit)
60 --------------
60 --------------
61 M b
61 M b
62 a
62 a
63 --------------
63 --------------
64
64
65 --------------
65 --------------
66 test L:nm a b R:up a W: - 4 get remote change to b
66 test L:nm a b R:up a W: - 4 get remote change to b
67 --------------
67 --------------
68 resolving manifests
68 resolving manifests
69 overwrite None partial False
69 overwrite None partial False
70 ancestor 924404dff337 local ecf3cb2a4219+ remote f4db7e329e71
70 ancestor 924404dff337 local ecf3cb2a4219+ remote f4db7e329e71
71 b: local moved to a -> m
71 b: local moved to a -> m
72 rev: versions differ -> m
72 rev: versions differ -> m
73 merging b and a
73 merging b and a
74 my b@ecf3cb2a4219+ other a@f4db7e329e71 ancestor a@924404dff337
74 my b@ecf3cb2a4219+ other a@f4db7e329e71 ancestor a@924404dff337
75 merging rev
75 merging rev
76 my rev@ecf3cb2a4219+ other rev@f4db7e329e71 ancestor rev@924404dff337
76 my rev@ecf3cb2a4219+ other rev@f4db7e329e71 ancestor rev@924404dff337
77 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
77 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
78 (branch merge, don't forget to commit)
78 (branch merge, don't forget to commit)
79 --------------
79 --------------
80 M b
80 M b
81 a
81 a
82 --------------
82 --------------
83
83
84 --------------
84 --------------
85 test L: R:nc a b W: - 5 get b
85 test L: R:nc a b W: - 5 get b
86 --------------
86 --------------
87 resolving manifests
87 resolving manifests
88 overwrite None partial False
88 overwrite None partial False
89 ancestor 924404dff337 local 94b33a1b7f2d+ remote 735846fee2d7
89 ancestor 924404dff337 local 94b33a1b7f2d+ remote 735846fee2d7
90 rev: versions differ -> m
90 rev: versions differ -> m
91 a: remote copied to b -> m
91 b: remote created -> g
92 copying a to b
92 getting b
93 merging rev
93 merging rev
94 my rev@94b33a1b7f2d+ other rev@735846fee2d7 ancestor rev@924404dff337
94 my rev@94b33a1b7f2d+ other rev@735846fee2d7 ancestor rev@924404dff337
95 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
95 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
96 (branch merge, don't forget to commit)
96 (branch merge, don't forget to commit)
97 --------------
97 --------------
98 M b
98 M b
99 a
100 C a
99 C a
101 --------------
100 --------------
102
101
103 --------------
102 --------------
104 test L:nc a b R: W: - 6 nothing
103 test L:nc a b R: W: - 6 nothing
105 --------------
104 --------------
106 resolving manifests
105 resolving manifests
107 overwrite None partial False
106 overwrite None partial False
108 ancestor 924404dff337 local ac809aeed39a+ remote 97c705ade336
107 ancestor 924404dff337 local ac809aeed39a+ remote 97c705ade336
109 b: local copied to a -> m
110 rev: versions differ -> m
108 rev: versions differ -> m
111 merging rev
109 merging rev
112 my rev@ac809aeed39a+ other rev@97c705ade336 ancestor rev@924404dff337
110 my rev@ac809aeed39a+ other rev@97c705ade336 ancestor rev@924404dff337
113 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
111 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
114 (branch merge, don't forget to commit)
112 (branch merge, don't forget to commit)
115 --------------
113 --------------
116 M b
117 a
118 C a
114 C a
115 C b
119 --------------
116 --------------
120
117
121 --------------
118 --------------
122 test L: R:nm a b W: - 7 get b
119 test L: R:nm a b W: - 7 get b
123 --------------
120 --------------
124 resolving manifests
121 resolving manifests
125 overwrite None partial False
122 overwrite None partial False
126 ancestor 924404dff337 local 94b33a1b7f2d+ remote e03727d2d66b
123 ancestor 924404dff337 local 94b33a1b7f2d+ remote e03727d2d66b
124 a: other deleted -> r
127 rev: versions differ -> m
125 rev: versions differ -> m
128 a: remote moved to b -> m
126 b: remote created -> g
129 copying a to b
130 removing a
127 removing a
128 getting b
131 merging rev
129 merging rev
132 my rev@94b33a1b7f2d+ other rev@e03727d2d66b ancestor rev@924404dff337
130 my rev@94b33a1b7f2d+ other rev@e03727d2d66b ancestor rev@924404dff337
133 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
131 1 files updated, 1 files merged, 1 files removed, 0 files unresolved
134 (branch merge, don't forget to commit)
132 (branch merge, don't forget to commit)
135 --------------
133 --------------
136 M b
134 M b
137 a
138 --------------
135 --------------
139
136
140 --------------
137 --------------
141 test L:nm a b R: W: - 8 nothing
138 test L:nm a b R: W: - 8 nothing
142 --------------
139 --------------
143 resolving manifests
140 resolving manifests
144 overwrite None partial False
141 overwrite None partial False
145 ancestor 924404dff337 local ecf3cb2a4219+ remote 97c705ade336
142 ancestor 924404dff337 local ecf3cb2a4219+ remote 97c705ade336
146 b: local moved to a -> m
147 rev: versions differ -> m
143 rev: versions differ -> m
148 merging rev
144 merging rev
149 my rev@ecf3cb2a4219+ other rev@97c705ade336 ancestor rev@924404dff337
145 my rev@ecf3cb2a4219+ other rev@97c705ade336 ancestor rev@924404dff337
150 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
146 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
151 (branch merge, don't forget to commit)
147 (branch merge, don't forget to commit)
152 --------------
148 --------------
153 M b
149 C b
154 a
155 --------------
150 --------------
156
151
157 --------------
152 --------------
158 test L:um a b R:um a b W: - 9 do merge with ancestor in a
153 test L:um a b R:um a b W: - 9 do merge with ancestor in a
159 --------------
154 --------------
160 resolving manifests
155 resolving manifests
161 overwrite None partial False
156 overwrite None partial False
162 ancestor 924404dff337 local ec03c2ca8642+ remote 79cc6877a3b7
157 ancestor 924404dff337 local ec03c2ca8642+ remote 79cc6877a3b7
163 b: versions differ -> m
158 b: versions differ -> m
164 rev: versions differ -> m
159 rev: versions differ -> m
165 merging b
160 merging b
166 my b@ec03c2ca8642+ other b@79cc6877a3b7 ancestor a@924404dff337
161 my b@ec03c2ca8642+ other b@79cc6877a3b7 ancestor a@924404dff337
167 merging rev
162 merging rev
168 my rev@ec03c2ca8642+ other rev@79cc6877a3b7 ancestor rev@924404dff337
163 my rev@ec03c2ca8642+ other rev@79cc6877a3b7 ancestor rev@924404dff337
169 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
164 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
170 (branch merge, don't forget to commit)
165 (branch merge, don't forget to commit)
171 --------------
166 --------------
172 M b
167 M b
173 --------------
168 --------------
174
169
175 --------------
170 --------------
176 test L:nm a b R:nm a c W: - 11 get c, keep b
171 test L:nm a b R:nm a c W: - 11 get c, keep b
177 --------------
172 --------------
178 resolving manifests
173 resolving manifests
179 overwrite None partial False
174 overwrite None partial False
180 ancestor 924404dff337 local ecf3cb2a4219+ remote e6abcc1a30c2
175 ancestor 924404dff337 local ecf3cb2a4219+ remote e6abcc1a30c2
181 rev: versions differ -> m
176 rev: versions differ -> m
182 c: remote created -> g
177 c: remote created -> g
183 getting c
178 getting c
184 merging rev
179 merging rev
185 my rev@ecf3cb2a4219+ other rev@e6abcc1a30c2 ancestor rev@924404dff337
180 my rev@ecf3cb2a4219+ other rev@e6abcc1a30c2 ancestor rev@924404dff337
186 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
181 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
187 (branch merge, don't forget to commit)
182 (branch merge, don't forget to commit)
188 --------------
183 --------------
189 M c
184 M c
190 C b
185 C b
191 --------------
186 --------------
192
187
193 --------------
188 --------------
194 test L:nc a b R:up b W: - 12 merge b no ancestor
189 test L:nc a b R:up b W: - 12 merge b no ancestor
195 --------------
190 --------------
196 resolving manifests
191 resolving manifests
197 overwrite None partial False
192 overwrite None partial False
198 ancestor 924404dff337 local ac809aeed39a+ remote af30c7647fc7
193 ancestor 924404dff337 local ac809aeed39a+ remote af30c7647fc7
199 b: versions differ -> m
194 b: versions differ -> m
200 rev: versions differ -> m
195 rev: versions differ -> m
201 merging b
196 merging b
202 my b@ac809aeed39a+ other b@af30c7647fc7 ancestor b@000000000000
197 my b@ac809aeed39a+ other b@af30c7647fc7 ancestor b@000000000000
203 merging rev
198 merging rev
204 my rev@ac809aeed39a+ other rev@af30c7647fc7 ancestor rev@924404dff337
199 my rev@ac809aeed39a+ other rev@af30c7647fc7 ancestor rev@924404dff337
205 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
200 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
206 (branch merge, don't forget to commit)
201 (branch merge, don't forget to commit)
207 --------------
202 --------------
208 M b
203 M b
209 C a
204 C a
210 --------------
205 --------------
211
206
212 --------------
207 --------------
213 test L:up b R:nm a b W: - 13 merge b no ancestor
208 test L:up b R:nm a b W: - 13 merge b no ancestor
214 --------------
209 --------------
215 resolving manifests
210 resolving manifests
216 overwrite None partial False
211 overwrite None partial False
217 ancestor 924404dff337 local 59318016310c+ remote e03727d2d66b
212 ancestor 924404dff337 local 59318016310c+ remote e03727d2d66b
218 a: other deleted -> r
213 a: other deleted -> r
219 b: versions differ -> m
214 b: versions differ -> m
220 rev: versions differ -> m
215 rev: versions differ -> m
221 removing a
216 removing a
222 merging b
217 merging b
223 my b@59318016310c+ other b@e03727d2d66b ancestor b@000000000000
218 my b@59318016310c+ other b@e03727d2d66b ancestor b@000000000000
224 merging rev
219 merging rev
225 my rev@59318016310c+ other rev@e03727d2d66b ancestor rev@924404dff337
220 my rev@59318016310c+ other rev@e03727d2d66b ancestor rev@924404dff337
226 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
221 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
227 (branch merge, don't forget to commit)
222 (branch merge, don't forget to commit)
228 --------------
223 --------------
229 M b
224 M b
230 --------------
225 --------------
231
226
232 --------------
227 --------------
233 test L:nc a b R:up a b W: - 14 merge b no ancestor
228 test L:nc a b R:up a b W: - 14 merge b no ancestor
234 --------------
229 --------------
235 resolving manifests
230 resolving manifests
236 overwrite None partial False
231 overwrite None partial False
237 ancestor 924404dff337 local ac809aeed39a+ remote 8dbce441892a
232 ancestor 924404dff337 local ac809aeed39a+ remote 8dbce441892a
238 a: remote is newer -> g
233 a: remote is newer -> g
239 b: versions differ -> m
234 b: versions differ -> m
240 rev: versions differ -> m
235 rev: versions differ -> m
241 getting a
236 getting a
242 merging b
237 merging b
243 my b@ac809aeed39a+ other b@8dbce441892a ancestor b@000000000000
238 my b@ac809aeed39a+ other b@8dbce441892a ancestor b@000000000000
244 merging rev
239 merging rev
245 my rev@ac809aeed39a+ other rev@8dbce441892a ancestor rev@924404dff337
240 my rev@ac809aeed39a+ other rev@8dbce441892a ancestor rev@924404dff337
246 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
241 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
247 (branch merge, don't forget to commit)
242 (branch merge, don't forget to commit)
248 --------------
243 --------------
249 M a
244 M a
250 M b
245 M b
251 --------------
246 --------------
252
247
253 --------------
248 --------------
254 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
249 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
255 --------------
250 --------------
256 resolving manifests
251 resolving manifests
257 overwrite None partial False
252 overwrite None partial False
258 ancestor 924404dff337 local 59318016310c+ remote e03727d2d66b
253 ancestor 924404dff337 local 59318016310c+ remote e03727d2d66b
259 a: other deleted -> r
254 a: other deleted -> r
260 b: versions differ -> m
255 b: versions differ -> m
261 rev: versions differ -> m
256 rev: versions differ -> m
262 removing a
257 removing a
263 merging b
258 merging b
264 my b@59318016310c+ other b@e03727d2d66b ancestor b@000000000000
259 my b@59318016310c+ other b@e03727d2d66b ancestor b@000000000000
265 merging rev
260 merging rev
266 my rev@59318016310c+ other rev@e03727d2d66b ancestor rev@924404dff337
261 my rev@59318016310c+ other rev@e03727d2d66b ancestor rev@924404dff337
267 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
262 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
268 (branch merge, don't forget to commit)
263 (branch merge, don't forget to commit)
269 --------------
264 --------------
270 M b
265 M b
271 --------------
266 --------------
272
267
273 --------------
268 --------------
274 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
269 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
275 --------------
270 --------------
276 resolving manifests
271 resolving manifests
277 overwrite None partial False
272 overwrite None partial False
278 ancestor 924404dff337 local ac809aeed39a+ remote 8dbce441892a
273 ancestor 924404dff337 local ac809aeed39a+ remote 8dbce441892a
279 a: remote is newer -> g
274 a: remote is newer -> g
280 b: versions differ -> m
275 b: versions differ -> m
281 rev: versions differ -> m
276 rev: versions differ -> m
282 getting a
277 getting a
283 merging b
278 merging b
284 my b@ac809aeed39a+ other b@8dbce441892a ancestor b@000000000000
279 my b@ac809aeed39a+ other b@8dbce441892a ancestor b@000000000000
285 merging rev
280 merging rev
286 my rev@ac809aeed39a+ other rev@8dbce441892a ancestor rev@924404dff337
281 my rev@ac809aeed39a+ other rev@8dbce441892a ancestor rev@924404dff337
287 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
282 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
288 (branch merge, don't forget to commit)
283 (branch merge, don't forget to commit)
289 --------------
284 --------------
290 M a
285 M a
291 M b
286 M b
292 --------------
287 --------------
293
288
294 --------------
289 --------------
295 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
290 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
296 --------------
291 --------------
297 resolving manifests
292 resolving manifests
298 overwrite None partial False
293 overwrite None partial False
299 ancestor 924404dff337 local 0b76e65c8289+ remote 735846fee2d7
294 ancestor 924404dff337 local 0b76e65c8289+ remote 735846fee2d7
300 b: versions differ -> m
295 b: versions differ -> m
301 rev: versions differ -> m
296 rev: versions differ -> m
302 merging b
297 merging b
303 my b@0b76e65c8289+ other b@735846fee2d7 ancestor b@000000000000
298 my b@0b76e65c8289+ other b@735846fee2d7 ancestor b@000000000000
304 merging rev
299 merging rev
305 my rev@0b76e65c8289+ other rev@735846fee2d7 ancestor rev@924404dff337
300 my rev@0b76e65c8289+ other rev@735846fee2d7 ancestor rev@924404dff337
306 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
301 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
307 (branch merge, don't forget to commit)
302 (branch merge, don't forget to commit)
308 --------------
303 --------------
309 M b
304 M b
310 C a
305 C a
311 --------------
306 --------------
312
307
313 --------------
308 --------------
314 test L:nm a b R:up a b W: - 18 merge b no ancestor
309 test L:nm a b R:up a b W: - 18 merge b no ancestor
315 --------------
310 --------------
316 resolving manifests
311 resolving manifests
317 overwrite None partial False
312 overwrite None partial False
318 ancestor 924404dff337 local ecf3cb2a4219+ remote 8dbce441892a
313 ancestor 924404dff337 local ecf3cb2a4219+ remote 8dbce441892a
319 b: versions differ -> m
314 b: versions differ -> m
320 rev: versions differ -> m
315 rev: versions differ -> m
321 a: prompt recreating -> g
316 a: prompt recreating -> g
322 getting a
317 getting a
323 merging b
318 merging b
324 my b@ecf3cb2a4219+ other b@8dbce441892a ancestor b@000000000000
319 my b@ecf3cb2a4219+ other b@8dbce441892a ancestor b@000000000000
325 merging rev
320 merging rev
326 my rev@ecf3cb2a4219+ other rev@8dbce441892a ancestor rev@924404dff337
321 my rev@ecf3cb2a4219+ other rev@8dbce441892a ancestor rev@924404dff337
327 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
322 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
328 (branch merge, don't forget to commit)
323 (branch merge, don't forget to commit)
329 --------------
324 --------------
330 M a
325 M a
331 M b
326 M b
332 --------------
327 --------------
333
328
334 --------------
329 --------------
335 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
330 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
336 --------------
331 --------------
337 resolving manifests
332 resolving manifests
338 overwrite None partial False
333 overwrite None partial False
339 ancestor 924404dff337 local 0b76e65c8289+ remote e03727d2d66b
334 ancestor 924404dff337 local 0b76e65c8289+ remote e03727d2d66b
340 b: versions differ -> m
335 b: versions differ -> m
341 rev: versions differ -> m
336 rev: versions differ -> m
342 merging b
337 merging b
343 my b@0b76e65c8289+ other b@e03727d2d66b ancestor b@000000000000
338 my b@0b76e65c8289+ other b@e03727d2d66b ancestor b@000000000000
344 merging rev
339 merging rev
345 my rev@0b76e65c8289+ other rev@e03727d2d66b ancestor rev@924404dff337
340 my rev@0b76e65c8289+ other rev@e03727d2d66b ancestor rev@924404dff337
346 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
341 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
347 (branch merge, don't forget to commit)
342 (branch merge, don't forget to commit)
348 --------------
343 --------------
349 M b
344 M b
350 C a
345 C a
351 --------------
346 --------------
352
347
353 --------------
348 --------------
354 test L:up a R:um a b W: - 20 merge a and b to b, remove a
349 test L:up a R:um a b W: - 20 merge a and b to b, remove a
355 --------------
350 --------------
356 resolving manifests
351 resolving manifests
357 overwrite None partial False
352 overwrite None partial False
358 ancestor 924404dff337 local e300d1c794ec+ remote 79cc6877a3b7
353 ancestor 924404dff337 local e300d1c794ec+ remote 79cc6877a3b7
359 rev: versions differ -> m
354 rev: versions differ -> m
360 a: remote moved to b -> m
355 a: remote moved to b -> m
361 merging a and b
356 merging a and b
362 my a@e300d1c794ec+ other b@79cc6877a3b7 ancestor a@924404dff337
357 my a@e300d1c794ec+ other b@79cc6877a3b7 ancestor a@924404dff337
363 copying a to b
358 copying a to b
364 removing a
359 removing a
365 merging rev
360 merging rev
366 my rev@e300d1c794ec+ other rev@79cc6877a3b7 ancestor rev@924404dff337
361 my rev@e300d1c794ec+ other rev@79cc6877a3b7 ancestor rev@924404dff337
367 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
362 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
368 (branch merge, don't forget to commit)
363 (branch merge, don't forget to commit)
369 --------------
364 --------------
370 M b
365 M b
371 a
366 a
372 --------------
367 --------------
373
368
374 --------------
369 --------------
375 test L:um a b R:up a W: - 21 merge a and b to b
370 test L:um a b R:up a W: - 21 merge a and b to b
376 --------------
371 --------------
377 resolving manifests
372 resolving manifests
378 overwrite None partial False
373 overwrite None partial False
379 ancestor 924404dff337 local ec03c2ca8642+ remote f4db7e329e71
374 ancestor 924404dff337 local ec03c2ca8642+ remote f4db7e329e71
380 b: local moved to a -> m
375 b: local moved to a -> m
381 rev: versions differ -> m
376 rev: versions differ -> m
382 merging b and a
377 merging b and a
383 my b@ec03c2ca8642+ other a@f4db7e329e71 ancestor a@924404dff337
378 my b@ec03c2ca8642+ other a@f4db7e329e71 ancestor a@924404dff337
384 merging rev
379 merging rev
385 my rev@ec03c2ca8642+ other rev@f4db7e329e71 ancestor rev@924404dff337
380 my rev@ec03c2ca8642+ other rev@f4db7e329e71 ancestor rev@924404dff337
386 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
381 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
387 (branch merge, don't forget to commit)
382 (branch merge, don't forget to commit)
388 --------------
383 --------------
389 M b
384 M b
390 a
385 a
391 --------------
386 --------------
392
387
393 --------------
388 --------------
394 test L:nm a b R:up a c W: - 23 get c, keep b
389 test L:nm a b R:up a c W: - 23 get c, keep b
395 --------------
390 --------------
396 resolving manifests
391 resolving manifests
397 overwrite None partial False
392 overwrite None partial False
398 ancestor 924404dff337 local ecf3cb2a4219+ remote 2b958612230f
393 ancestor 924404dff337 local ecf3cb2a4219+ remote 2b958612230f
399 b: local moved to a -> m
394 b: local moved to a -> m
400 rev: versions differ -> m
395 rev: versions differ -> m
401 c: remote created -> g
396 c: remote created -> g
402 merging b and a
397 merging b and a
403 my b@ecf3cb2a4219+ other a@2b958612230f ancestor a@924404dff337
398 my b@ecf3cb2a4219+ other a@2b958612230f ancestor a@924404dff337
404 getting c
399 getting c
405 merging rev
400 merging rev
406 my rev@ecf3cb2a4219+ other rev@2b958612230f ancestor rev@924404dff337
401 my rev@ecf3cb2a4219+ other rev@2b958612230f ancestor rev@924404dff337
407 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
402 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
408 (branch merge, don't forget to commit)
403 (branch merge, don't forget to commit)
409 --------------
404 --------------
410 M b
405 M b
411 a
406 a
412 M c
407 M c
413 --------------
408 --------------
414
409
General Comments 0
You need to be logged in to leave comments. Login now