##// END OF EJS Templates
merge: remove linear variable
Matt Mackall -
r3110:40e777bd default
parent child Browse files
Show More
@@ -1,364 +1,363
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")
12
12
13 def fmerge(f, local, other, ancestor):
13 def fmerge(f, local, other, ancestor):
14 """merge executable flags"""
14 """merge executable flags"""
15 a, b, c = ancestor.execf(f), local.execf(f), other.execf(f)
15 a, b, c = ancestor.execf(f), local.execf(f), other.execf(f)
16 return ((a^b) | (a^c)) ^ a
16 return ((a^b) | (a^c)) ^ a
17
17
18 def merge3(repo, fn, my, other, p1, p2):
18 def merge3(repo, fn, my, other, p1, p2):
19 """perform a 3-way merge in the working directory"""
19 """perform a 3-way merge in the working directory"""
20
20
21 def temp(prefix, node):
21 def temp(prefix, node):
22 pre = "%s~%s." % (os.path.basename(fn), prefix)
22 pre = "%s~%s." % (os.path.basename(fn), 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(fn, fl.read(node), f)
25 repo.wwrite(fn, fl.read(node), f)
26 f.close()
26 f.close()
27 return name
27 return name
28
28
29 fl = repo.file(fn)
29 fl = repo.file(fn)
30 base = fl.ancestor(my, other)
30 base = fl.ancestor(my, other)
31 a = repo.wjoin(fn)
31 a = repo.wjoin(fn)
32 b = temp("base", base)
32 b = temp("base", base)
33 c = temp("other", other)
33 c = temp("other", other)
34
34
35 repo.ui.note(_("resolving %s\n") % fn)
35 repo.ui.note(_("resolving %s\n") % fn)
36 repo.ui.debug(_("file %s: my %s other %s ancestor %s\n") %
36 repo.ui.debug(_("file %s: my %s other %s ancestor %s\n") %
37 (fn, short(my), short(other), short(base)))
37 (fn, short(my), short(other), short(base)))
38
38
39 cmd = (os.environ.get("HGMERGE") or repo.ui.config("ui", "merge")
39 cmd = (os.environ.get("HGMERGE") or repo.ui.config("ui", "merge")
40 or "hgmerge")
40 or "hgmerge")
41 r = util.system('%s "%s" "%s" "%s"' % (cmd, a, b, c), cwd=repo.root,
41 r = util.system('%s "%s" "%s" "%s"' % (cmd, a, b, c), cwd=repo.root,
42 environ={'HG_FILE': fn,
42 environ={'HG_FILE': fn,
43 'HG_MY_NODE': p1,
43 'HG_MY_NODE': p1,
44 'HG_OTHER_NODE': p2,
44 'HG_OTHER_NODE': p2,
45 'HG_FILE_MY_NODE': hex(my),
45 'HG_FILE_MY_NODE': hex(my),
46 'HG_FILE_OTHER_NODE': hex(other),
46 'HG_FILE_OTHER_NODE': hex(other),
47 'HG_FILE_BASE_NODE': hex(base)})
47 'HG_FILE_BASE_NODE': hex(base)})
48 if r:
48 if r:
49 repo.ui.warn(_("merging %s failed!\n") % fn)
49 repo.ui.warn(_("merging %s failed!\n") % fn)
50
50
51 os.unlink(b)
51 os.unlink(b)
52 os.unlink(c)
52 os.unlink(c)
53 return r
53 return r
54
54
55 def checkunknown(repo, m2, status):
55 def checkunknown(repo, m2, status):
56 """
56 """
57 check for collisions between unknown files and files in m2
57 check for collisions between unknown files and files in m2
58 """
58 """
59 modified, added, removed, deleted, unknown = status[:5]
59 modified, added, removed, deleted, unknown = status[:5]
60 for f in unknown:
60 for f in unknown:
61 if f in m2:
61 if f in m2:
62 if repo.file(f).cmp(m2[f], repo.wread(f)):
62 if repo.file(f).cmp(m2[f], repo.wread(f)):
63 raise util.Abort(_("'%s' already exists in the working"
63 raise util.Abort(_("'%s' already exists in the working"
64 " dir and differs from remote") % f)
64 " dir and differs from remote") % f)
65
65
66 def workingmanifest(repo, man, status):
66 def workingmanifest(repo, man, status):
67 """
67 """
68 Update manifest to correspond to the working directory
68 Update manifest to correspond to the working directory
69 """
69 """
70
70
71 modified, added, removed, deleted, unknown = status[:5]
71 modified, added, removed, deleted, unknown = status[:5]
72 for i,l in (("a", added), ("m", modified), ("u", unknown)):
72 for i,l in (("a", added), ("m", modified), ("u", unknown)):
73 for f in l:
73 for f in l:
74 man[f] = man.get(f, nullid) + i
74 man[f] = man.get(f, nullid) + i
75 man.set(f, util.is_exec(repo.wjoin(f), man.execf(f)))
75 man.set(f, util.is_exec(repo.wjoin(f), man.execf(f)))
76
76
77 for f in deleted + removed:
77 for f in deleted + removed:
78 del man[f]
78 del man[f]
79
79
80 return man
80 return man
81
81
82 def forgetremoved(m2, status):
82 def forgetremoved(m2, status):
83 """
83 """
84 Forget removed files
84 Forget removed files
85
85
86 If we're jumping between revisions (as opposed to merging), and if
86 If we're jumping between revisions (as opposed to merging), and if
87 neither the working directory nor the target rev has the file,
87 neither the working directory nor the target rev has the file,
88 then we need to remove it from the dirstate, to prevent the
88 then we need to remove it from the dirstate, to prevent the
89 dirstate from listing the file when it is no longer in the
89 dirstate from listing the file when it is no longer in the
90 manifest.
90 manifest.
91 """
91 """
92
92
93 modified, added, removed, deleted, unknown = status[:5]
93 modified, added, removed, deleted, unknown = status[:5]
94 action = []
94 action = []
95
95
96 for f in deleted + removed:
96 for f in deleted + removed:
97 if f not in m2:
97 if f not in m2:
98 action.append((f, "f"))
98 action.append((f, "f"))
99
99
100 return action
100 return action
101
101
102 def manifestmerge(ui, m1, m2, ma, overwrite, backwards, partial):
102 def manifestmerge(ui, m1, m2, ma, overwrite, backwards, partial):
103 """
103 """
104 Merge manifest m1 with m2 using ancestor ma and generate merge action list
104 Merge manifest m1 with m2 using ancestor ma and generate merge action list
105 """
105 """
106
106
107 action = []
107 action = []
108
108
109 # Filter manifests
109 # Filter manifests
110 if partial:
110 if partial:
111 for f in m1.keys():
111 for f in m1.keys():
112 if not partial(f): del m1[f]
112 if not partial(f): del m1[f]
113 for f in m2.keys():
113 for f in m2.keys():
114 if not partial(f): del m2[f]
114 if not partial(f): del m2[f]
115
115
116 # Compare manifests
116 # Compare manifests
117 for f, n in m1.iteritems():
117 for f, n in m1.iteritems():
118 if f in m2:
118 if f in m2:
119 queued = 0
119 queued = 0
120
120
121 # are files different?
121 # are files different?
122 if n != m2[f]:
122 if n != m2[f]:
123 a = ma.get(f, nullid)
123 a = ma.get(f, nullid)
124 # are both different from the ancestor?
124 # are both different from the ancestor?
125 if not overwrite and n != a and m2[f] != a:
125 if not overwrite and n != a and m2[f] != a:
126 ui.debug(_(" %s versions differ, resolve\n") % f)
126 ui.debug(_(" %s versions differ, resolve\n") % f)
127 action.append((f, "m", fmerge(f, m1, m2, ma), n[:20], m2[f]))
127 action.append((f, "m", fmerge(f, m1, m2, ma), n[:20], m2[f]))
128 queued = 1
128 queued = 1
129 # are we clobbering?
129 # are we clobbering?
130 # is remote's version newer?
130 # is remote's version newer?
131 # or are we going back in time and clean?
131 # or are we going back in time and clean?
132 elif overwrite or m2[f] != a or (backwards and not n[20:]):
132 elif overwrite or m2[f] != a or (backwards and not n[20:]):
133 ui.debug(_(" remote %s is newer, get\n") % f)
133 ui.debug(_(" remote %s is newer, get\n") % f)
134 action.append((f, "g", m2.execf(f), m2[f]))
134 action.append((f, "g", m2.execf(f), m2[f]))
135 queued = 1
135 queued = 1
136 elif n[20:] in ("u","a"):
136 elif n[20:] in ("u","a"):
137 # this unknown file is the same as the checkout
137 # this unknown file is the same as the checkout
138 # we need to reset the dirstate if the file was added
138 # we need to reset the dirstate if the file was added
139 action.append((f, "g", m2.execf(f), m2[f]))
139 action.append((f, "g", m2.execf(f), m2[f]))
140
140
141 # do we still need to look at mode bits?
141 # do we still need to look at mode bits?
142 if not queued and m1.execf(f) != m2.execf(f):
142 if not queued and m1.execf(f) != m2.execf(f):
143 if overwrite:
143 if overwrite:
144 ui.debug(_(" updating permissions for %s\n") % f)
144 ui.debug(_(" updating permissions for %s\n") % f)
145 action.append((f, "e", m2.execf(f)))
145 action.append((f, "e", m2.execf(f)))
146 else:
146 else:
147 mode = fmerge(f, m1, m2, ma)
147 mode = fmerge(f, m1, m2, ma)
148 if mode != m1.execf(f):
148 if mode != m1.execf(f):
149 ui.debug(_(" updating permissions for %s\n")
149 ui.debug(_(" updating permissions for %s\n")
150 % f)
150 % f)
151 action.append((f, "e", m2.execf(f)))
151 action.append((f, "e", m2.execf(f)))
152 del m2[f]
152 del m2[f]
153 elif f in ma:
153 elif f in ma:
154 if n != ma[f]:
154 if n != ma[f]:
155 r = _("d")
155 r = _("d")
156 if not overwrite:
156 if not overwrite:
157 r = ui.prompt(
157 r = ui.prompt(
158 (_(" local changed %s which remote deleted\n") % f) +
158 (_(" local changed %s which remote deleted\n") % f) +
159 _("(k)eep or (d)elete?"), _("[kd]"), _("k"))
159 _("(k)eep or (d)elete?"), _("[kd]"), _("k"))
160 if r == _("d"):
160 if r == _("d"):
161 action.append((f, "r"))
161 action.append((f, "r"))
162 else:
162 else:
163 ui.debug(_("other deleted %s\n") % f)
163 ui.debug(_("other deleted %s\n") % f)
164 action.append((f, "r"))
164 action.append((f, "r"))
165 else:
165 else:
166 # file is created on branch or in working directory
166 # file is created on branch or in working directory
167 if overwrite and n[20:] != "u":
167 if overwrite and n[20:] != "u":
168 ui.debug(_("remote deleted %s, clobbering\n") % f)
168 ui.debug(_("remote deleted %s, clobbering\n") % f)
169 action.append((f, "r"))
169 action.append((f, "r"))
170 elif not n[20:]: # same as parent
170 elif not n[20:]: # same as parent
171 if backwards:
171 if backwards:
172 ui.debug(_("remote deleted %s\n") % f)
172 ui.debug(_("remote deleted %s\n") % f)
173 action.append((f, "r"))
173 action.append((f, "r"))
174 else:
174 else:
175 ui.debug(_("local modified %s, keeping\n") % f)
175 ui.debug(_("local modified %s, keeping\n") % f)
176 else:
176 else:
177 ui.debug(_("working dir created %s, keeping\n") % f)
177 ui.debug(_("working dir created %s, keeping\n") % f)
178
178
179 for f, n in m2.iteritems():
179 for f, n in m2.iteritems():
180 if f[0] == "/":
180 if f[0] == "/":
181 continue
181 continue
182 if f in ma and n != ma[f]:
182 if f in ma and n != ma[f]:
183 r = _("k")
183 r = _("k")
184 if not overwrite:
184 if not overwrite:
185 r = ui.prompt(
185 r = ui.prompt(
186 (_("remote changed %s which local deleted\n") % f) +
186 (_("remote changed %s which local deleted\n") % f) +
187 _("(k)eep or (d)elete?"), _("[kd]"), _("k"))
187 _("(k)eep or (d)elete?"), _("[kd]"), _("k"))
188 if r == _("k"):
188 if r == _("k"):
189 action.append((f, "g", m2.execf(f), n))
189 action.append((f, "g", m2.execf(f), n))
190 elif f not in ma:
190 elif f not in ma:
191 ui.debug(_("remote created %s\n") % f)
191 ui.debug(_("remote created %s\n") % f)
192 action.append((f, "g", m2.execf(f), n))
192 action.append((f, "g", m2.execf(f), n))
193 else:
193 else:
194 if overwrite or backwards:
194 if overwrite or backwards:
195 ui.debug(_("local deleted %s, recreating\n") % f)
195 ui.debug(_("local deleted %s, recreating\n") % f)
196 action.append((f, "g", m2.execf(f), n))
196 action.append((f, "g", m2.execf(f), n))
197 else:
197 else:
198 ui.debug(_("local deleted %s\n") % f)
198 ui.debug(_("local deleted %s\n") % f)
199
199
200 return action
200 return action
201
201
202 def update(repo, node, branchmerge=False, force=False, partial=None,
202 def update(repo, node, branchmerge=False, force=False, partial=None,
203 wlock=None, show_stats=True, remind=True):
203 wlock=None, show_stats=True, remind=True):
204
204
205 overwrite = force and not branchmerge
205 overwrite = force and not branchmerge
206 forcemerge = force and branchmerge
206 forcemerge = force and branchmerge
207
207
208 if not wlock:
208 if not wlock:
209 wlock = repo.wlock()
209 wlock = repo.wlock()
210
210
211 ### check phase
211 ### check phase
212
212
213 pl = repo.dirstate.parents()
213 pl = repo.dirstate.parents()
214 if not overwrite and pl[1] != nullid:
214 if not overwrite and pl[1] != nullid:
215 raise util.Abort(_("outstanding uncommitted merges"))
215 raise util.Abort(_("outstanding uncommitted merges"))
216
216
217 p1, p2 = pl[0], node
217 p1, p2 = pl[0], node
218 pa = repo.changelog.ancestor(p1, p2)
218 pa = repo.changelog.ancestor(p1, p2)
219
219
220 # are we going backwards?
220 # are we going backwards?
221 backwards = (pa == p2)
221 backwards = (pa == p2)
222
222
223 # is there a linear path from p1 to p2?
223 # is there a linear path from p1 to p2?
224 linear = (pa == p1 or pa == p2)
224 if pa == p1 or pa == p2:
225 if branchmerge and linear:
225 if branchmerge:
226 raise util.Abort(_("there is nothing to merge, just use "
226 raise util.Abort(_("there is nothing to merge, just use "
227 "'hg update' or look at 'hg heads'"))
227 "'hg update' or look at 'hg heads'"))
228
228 elif not (overwrite or branchmerge):
229 if not linear and not (overwrite or branchmerge):
230 raise util.Abort(_("update spans branches, use 'hg merge' "
229 raise util.Abort(_("update spans branches, use 'hg merge' "
231 "or 'hg update -C' to lose changes"))
230 "or 'hg update -C' to lose changes"))
232
231
233 status = repo.status()
232 status = repo.status()
234 modified, added, removed, deleted, unknown = status[:5]
233 modified, added, removed, deleted, unknown = status[:5]
235 if branchmerge and not forcemerge:
234 if branchmerge and not forcemerge:
236 if modified or added or removed:
235 if modified or added or removed:
237 raise util.Abort(_("outstanding uncommitted changes"))
236 raise util.Abort(_("outstanding uncommitted changes"))
238
237
239 m1 = repo.changectx(p1).manifest().copy()
238 m1 = repo.changectx(p1).manifest().copy()
240 m2 = repo.changectx(p2).manifest().copy()
239 m2 = repo.changectx(p2).manifest().copy()
241 ma = repo.changectx(pa).manifest()
240 ma = repo.changectx(pa).manifest()
242
241
243 # resolve the manifest to determine which files
242 # resolve the manifest to determine which files
244 # we care about merging
243 # we care about merging
245 repo.ui.note(_("resolving manifests\n"))
244 repo.ui.note(_("resolving manifests\n"))
246 repo.ui.debug(_(" overwrite %s branchmerge %s partial %s linear %s\n") %
245 repo.ui.debug(_(" overwrite %s branchmerge %s partial %s\n") %
247 (overwrite, branchmerge, bool(partial), linear))
246 (overwrite, branchmerge, bool(partial)))
248 repo.ui.debug(_(" ancestor %s local %s remote %s\n") %
247 repo.ui.debug(_(" ancestor %s local %s remote %s\n") %
249 (short(p1), short(p2), short(pa)))
248 (short(p1), short(p2), short(pa)))
250
249
251 action = []
250 action = []
252 m1 = workingmanifest(repo, m1, status)
251 m1 = workingmanifest(repo, m1, status)
253
252
254 if not force:
253 if not force:
255 checkunknown(repo, m2, status)
254 checkunknown(repo, m2, status)
256 if linear:
255 if not branchmerge:
257 action += forgetremoved(m2, status)
256 action += forgetremoved(m2, status)
258 action += manifestmerge(repo.ui, m1, m2, ma, overwrite, backwards, partial)
257 action += manifestmerge(repo.ui, m1, m2, ma, overwrite, backwards, partial)
259 del m1, m2, ma
258 del m1, m2, ma
260
259
261 ### apply phase
260 ### apply phase
262
261
263 if linear or overwrite:
262 if not branchmerge:
264 # we don't need to do any magic, just jump to the new rev
263 # we don't need to do any magic, just jump to the new rev
265 p1, p2 = p2, nullid
264 p1, p2 = p2, nullid
266
265
267 xp1, xp2 = hex(p1), hex(p2)
266 xp1, xp2 = hex(p1), hex(p2)
268 if p2 == nullid: xp2 = ''
267 if p2 == nullid: xp2 = ''
269
268
270 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
269 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
271
270
272 # update files
271 # update files
273 updated, merged, removed, unresolved = 0, 0, 0, 0
272 updated, merged, removed, unresolved = 0, 0, 0, 0
274 action.sort()
273 action.sort()
275 for a in action:
274 for a in action:
276 f, m = a[:2]
275 f, m = a[:2]
277 if f[0] == "/":
276 if f[0] == "/":
278 continue
277 continue
279 if m == "r": # remove
278 if m == "r": # remove
280 repo.ui.note(_("removing %s\n") % f)
279 repo.ui.note(_("removing %s\n") % f)
281 util.audit_path(f)
280 util.audit_path(f)
282 try:
281 try:
283 util.unlink(repo.wjoin(f))
282 util.unlink(repo.wjoin(f))
284 except OSError, inst:
283 except OSError, inst:
285 if inst.errno != errno.ENOENT:
284 if inst.errno != errno.ENOENT:
286 repo.ui.warn(_("update failed to remove %s: %s!\n") %
285 repo.ui.warn(_("update failed to remove %s: %s!\n") %
287 (f, inst.strerror))
286 (f, inst.strerror))
288 removed +=1
287 removed +=1
289 elif m == "m": # merge
288 elif m == "m": # merge
290 flag, my, other = a[2:]
289 flag, my, other = a[2:]
291 repo.ui.status(_("merging %s\n") % f)
290 repo.ui.status(_("merging %s\n") % f)
292 if merge3(repo, f, my, other, xp1, xp2):
291 if merge3(repo, f, my, other, xp1, xp2):
293 unresolved += 1
292 unresolved += 1
294 util.set_exec(repo.wjoin(f), flag)
293 util.set_exec(repo.wjoin(f), flag)
295 merged += 1
294 merged += 1
296 elif m == "g": # get
295 elif m == "g": # get
297 flag, node = a[2:]
296 flag, node = a[2:]
298 repo.ui.note(_("getting %s\n") % f)
297 repo.ui.note(_("getting %s\n") % f)
299 t = repo.file(f).read(node)
298 t = repo.file(f).read(node)
300 repo.wwrite(f, t)
299 repo.wwrite(f, t)
301 util.set_exec(repo.wjoin(f), flag)
300 util.set_exec(repo.wjoin(f), flag)
302 updated += 1
301 updated += 1
303 elif m == "e": # exec
302 elif m == "e": # exec
304 flag = a[2:]
303 flag = a[2:]
305 util.set_exec(repo.wjoin(f), flag)
304 util.set_exec(repo.wjoin(f), flag)
306
305
307 # update dirstate
306 # update dirstate
308 if not partial:
307 if not partial:
309 repo.dirstate.setparents(p1, p2)
308 repo.dirstate.setparents(p1, p2)
310 for a in action:
309 for a in action:
311 f, m = a[:2]
310 f, m = a[:2]
312 if m == "r": # remove
311 if m == "r": # remove
313 if branchmerge:
312 if branchmerge:
314 repo.dirstate.update([f], 'r')
313 repo.dirstate.update([f], 'r')
315 else:
314 else:
316 repo.dirstate.forget([f])
315 repo.dirstate.forget([f])
317 elif m == "f": # forget
316 elif m == "f": # forget
318 repo.dirstate.forget([f])
317 repo.dirstate.forget([f])
319 elif m == "g": # get
318 elif m == "g": # get
320 if branchmerge:
319 if branchmerge:
321 repo.dirstate.update([f], 'n', st_mtime=-1)
320 repo.dirstate.update([f], 'n', st_mtime=-1)
322 else:
321 else:
323 repo.dirstate.update([f], 'n')
322 repo.dirstate.update([f], 'n')
324 elif m == "m": # merge
323 elif m == "m": # merge
325 flag, my, other = a[2:]
324 flag, my, other = a[2:]
326 if branchmerge:
325 if branchmerge:
327 # We've done a branch merge, mark this file as merged
326 # We've done a branch merge, mark this file as merged
328 # so that we properly record the merger later
327 # so that we properly record the merger later
329 repo.dirstate.update([f], 'm')
328 repo.dirstate.update([f], 'm')
330 else:
329 else:
331 # We've update-merged a locally modified file, so
330 # We've update-merged a locally modified file, so
332 # we set the dirstate to emulate a normal checkout
331 # we set the dirstate to emulate a normal checkout
333 # of that file some time in the past. Thus our
332 # of that file some time in the past. Thus our
334 # merge will appear as a normal local file
333 # merge will appear as a normal local file
335 # modification.
334 # modification.
336 fl = repo.file(f)
335 fl = repo.file(f)
337 f_len = fl.size(fl.rev(other))
336 f_len = fl.size(fl.rev(other))
338 repo.dirstate.update([f], 'n', st_size=f_len, st_mtime=-1)
337 repo.dirstate.update([f], 'n', st_size=f_len, st_mtime=-1)
339
338
340 if show_stats:
339 if show_stats:
341 stats = ((updated, _("updated")),
340 stats = ((updated, _("updated")),
342 (merged - unresolved, _("merged")),
341 (merged - unresolved, _("merged")),
343 (removed, _("removed")),
342 (removed, _("removed")),
344 (unresolved, _("unresolved")))
343 (unresolved, _("unresolved")))
345 note = ", ".join([_("%d files %s") % s for s in stats])
344 note = ", ".join([_("%d files %s") % s for s in stats])
346 repo.ui.status("%s\n" % note)
345 repo.ui.status("%s\n" % note)
347 if not partial:
346 if not partial:
348 if branchmerge:
347 if branchmerge:
349 if unresolved:
348 if unresolved:
350 repo.ui.status(_("There are unresolved merges,"
349 repo.ui.status(_("There are unresolved merges,"
351 " you can redo the full merge using:\n"
350 " you can redo the full merge using:\n"
352 " hg update -C %s\n"
351 " hg update -C %s\n"
353 " hg merge %s\n"
352 " hg merge %s\n"
354 % (repo.changelog.rev(p1),
353 % (repo.changelog.rev(p1),
355 repo.changelog.rev(p2))))
354 repo.changelog.rev(p2))))
356 elif remind:
355 elif remind:
357 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
356 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
358 elif unresolved:
357 elif unresolved:
359 repo.ui.status(_("There are unresolved merges with"
358 repo.ui.status(_("There are unresolved merges with"
360 " locally modified files.\n"))
359 " locally modified files.\n"))
361
360
362 repo.hook('update', parent1=xp1, parent2=xp2, error=unresolved)
361 repo.hook('update', parent1=xp1, parent2=xp2, error=unresolved)
363 return unresolved
362 return unresolved
364
363
@@ -1,78 +1,78
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 ../test-a
2 pulling from ../test-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 1 changesets with 1 changes to 1 files (+1 heads)
7 added 1 changesets with 1 changes to 1 files (+1 heads)
8 (run 'hg heads' to see heads, 'hg merge' to merge)
8 (run 'hg heads' to see heads, 'hg merge' to merge)
9 merge: warning: conflicts during merge
9 merge: warning: conflicts during merge
10 merging test.txt
10 merging test.txt
11 merging test.txt failed!
11 merging test.txt failed!
12 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
12 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
13 There are unresolved merges, you can redo the full merge using:
13 There are unresolved merges, you can redo the full merge using:
14 hg update -C 1
14 hg update -C 1
15 hg merge 2
15 hg merge 2
16 pulling from ../test-a
16 pulling from ../test-a
17 searching for changes
17 searching for changes
18 adding changesets
18 adding changesets
19 adding manifests
19 adding manifests
20 adding file changes
20 adding file changes
21 added 1 changesets with 1 changes to 1 files (+1 heads)
21 added 1 changesets with 1 changes to 1 files (+1 heads)
22 (run 'hg heads' to see heads, 'hg merge' to merge)
22 (run 'hg heads' to see heads, 'hg merge' to merge)
23 merge: warning: conflicts during merge
23 merge: warning: conflicts during merge
24 resolving manifests
24 resolving manifests
25 overwrite None branchmerge True partial False linear False
25 overwrite None branchmerge True partial False
26 ancestor 451c744aabcc local a070d41e8360 remote faaea63e63a9
26 ancestor 451c744aabcc local a070d41e8360 remote faaea63e63a9
27 test.txt versions differ, resolve
27 test.txt versions differ, resolve
28 merging test.txt
28 merging test.txt
29 resolving test.txt
29 resolving test.txt
30 file test.txt: my fc3148072371 other d40249267ae3 ancestor 8fe46a3eb557
30 file test.txt: my fc3148072371 other d40249267ae3 ancestor 8fe46a3eb557
31 merging test.txt failed!
31 merging test.txt failed!
32 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
32 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
33 There are unresolved merges, you can redo the full merge using:
33 There are unresolved merges, you can redo the full merge using:
34 hg update -C 3
34 hg update -C 3
35 hg merge 4
35 hg merge 4
36 one
36 one
37 <<<<<<<
37 <<<<<<<
38 two-point-five
38 two-point-five
39 =======
39 =======
40 two-point-one
40 two-point-one
41 >>>>>>>
41 >>>>>>>
42 three
42 three
43 rev offset length base linkrev nodeid p1 p2
43 rev offset length base linkrev nodeid p1 p2
44 0 0 7 0 0 01365c4cca56 000000000000 000000000000
44 0 0 7 0 0 01365c4cca56 000000000000 000000000000
45 1 7 9 1 1 7b013192566a 01365c4cca56 000000000000
45 1 7 9 1 1 7b013192566a 01365c4cca56 000000000000
46 2 16 15 2 2 8fe46a3eb557 01365c4cca56 000000000000
46 2 16 15 2 2 8fe46a3eb557 01365c4cca56 000000000000
47 3 31 27 2 3 fc3148072371 7b013192566a 8fe46a3eb557
47 3 31 27 2 3 fc3148072371 7b013192566a 8fe46a3eb557
48 4 58 25 4 4 d40249267ae3 8fe46a3eb557 000000000000
48 4 58 25 4 4 d40249267ae3 8fe46a3eb557 000000000000
49 changeset: 4:a070d41e8360
49 changeset: 4:a070d41e8360
50 tag: tip
50 tag: tip
51 parent: 2:faaea63e63a9
51 parent: 2:faaea63e63a9
52 user: test
52 user: test
53 date: Mon Jan 12 13:46:40 1970 +0000
53 date: Mon Jan 12 13:46:40 1970 +0000
54 summary: two -> two-point-one
54 summary: two -> two-point-one
55
55
56 changeset: 3:451c744aabcc
56 changeset: 3:451c744aabcc
57 parent: 1:e409be6afcc0
57 parent: 1:e409be6afcc0
58 parent: 2:faaea63e63a9
58 parent: 2:faaea63e63a9
59 user: test
59 user: test
60 date: Mon Jan 12 13:46:40 1970 +0000
60 date: Mon Jan 12 13:46:40 1970 +0000
61 summary: Merge 1
61 summary: Merge 1
62
62
63 changeset: 2:faaea63e63a9
63 changeset: 2:faaea63e63a9
64 parent: 0:095c92b91f1a
64 parent: 0:095c92b91f1a
65 user: test
65 user: test
66 date: Mon Jan 12 13:46:40 1970 +0000
66 date: Mon Jan 12 13:46:40 1970 +0000
67 summary: Numbers as words
67 summary: Numbers as words
68
68
69 changeset: 1:e409be6afcc0
69 changeset: 1:e409be6afcc0
70 user: test
70 user: test
71 date: Mon Jan 12 13:46:40 1970 +0000
71 date: Mon Jan 12 13:46:40 1970 +0000
72 summary: 2 -> 2.5
72 summary: 2 -> 2.5
73
73
74 changeset: 0:095c92b91f1a
74 changeset: 0:095c92b91f1a
75 user: test
75 user: test
76 date: Mon Jan 12 13:46:40 1970 +0000
76 date: Mon Jan 12 13:46:40 1970 +0000
77 summary: Initial
77 summary: Initial
78
78
@@ -1,141 +1,141
1 adding a
1 adding a
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 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 diff -r 33aaa84a386b a
4 diff -r 33aaa84a386b a
5 --- a/a
5 --- a/a
6 +++ b/a
6 +++ b/a
7 @@ -1,1 +1,1 @@ a
7 @@ -1,1 +1,1 @@ a
8 -a
8 -a
9 +abc
9 +abc
10 adding b
10 adding b
11 M a
11 M a
12 changeset: 0:33aaa84a386b
12 changeset: 0:33aaa84a386b
13 user: test
13 user: test
14 date: Mon Jan 12 13:46:40 1970 +0000
14 date: Mon Jan 12 13:46:40 1970 +0000
15 summary: 1
15 summary: 1
16
16
17 resolving manifests
17 resolving manifests
18 overwrite False branchmerge False partial False linear True
18 overwrite False branchmerge False partial False
19 ancestor 33aaa84a386b local 802f095af299 remote 33aaa84a386b
19 ancestor 33aaa84a386b local 802f095af299 remote 33aaa84a386b
20 a versions differ, resolve
20 a versions differ, resolve
21 remote created b
21 remote created b
22 merging a
22 merging a
23 resolving a
23 resolving a
24 file a: my b789fdd96dc2 other d730145abbf9 ancestor b789fdd96dc2
24 file a: my b789fdd96dc2 other d730145abbf9 ancestor b789fdd96dc2
25 getting b
25 getting b
26 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
26 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
27 changeset: 1:802f095af299
27 changeset: 1:802f095af299
28 tag: tip
28 tag: tip
29 user: test
29 user: test
30 date: Mon Jan 12 13:46:40 1970 +0000
30 date: Mon Jan 12 13:46:40 1970 +0000
31 summary: 2
31 summary: 2
32
32
33 resolving manifests
33 resolving manifests
34 overwrite False branchmerge False partial False linear True
34 overwrite False branchmerge False partial False
35 ancestor 802f095af299 local 33aaa84a386b remote 33aaa84a386b
35 ancestor 802f095af299 local 33aaa84a386b remote 33aaa84a386b
36 remote deleted b
36 remote deleted b
37 removing b
37 removing b
38 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
38 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
39 changeset: 0:33aaa84a386b
39 changeset: 0:33aaa84a386b
40 user: test
40 user: test
41 date: Mon Jan 12 13:46:40 1970 +0000
41 date: Mon Jan 12 13:46:40 1970 +0000
42 summary: 1
42 summary: 1
43
43
44 abort: there is nothing to merge - use "hg update" instead
44 abort: there is nothing to merge - use "hg update" instead
45 failed
45 failed
46 changeset: 0:33aaa84a386b
46 changeset: 0:33aaa84a386b
47 user: test
47 user: test
48 date: Mon Jan 12 13:46:40 1970 +0000
48 date: Mon Jan 12 13:46:40 1970 +0000
49 summary: 1
49 summary: 1
50
50
51 resolving manifests
51 resolving manifests
52 overwrite False branchmerge False partial False linear True
52 overwrite False branchmerge False partial False
53 ancestor 33aaa84a386b local 802f095af299 remote 33aaa84a386b
53 ancestor 33aaa84a386b local 802f095af299 remote 33aaa84a386b
54 a versions differ, resolve
54 a versions differ, resolve
55 remote created b
55 remote created b
56 merging a
56 merging a
57 resolving a
57 resolving a
58 file a: my b789fdd96dc2 other d730145abbf9 ancestor b789fdd96dc2
58 file a: my b789fdd96dc2 other d730145abbf9 ancestor b789fdd96dc2
59 getting b
59 getting b
60 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
60 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
61 changeset: 1:802f095af299
61 changeset: 1:802f095af299
62 tag: tip
62 tag: tip
63 user: test
63 user: test
64 date: Mon Jan 12 13:46:40 1970 +0000
64 date: Mon Jan 12 13:46:40 1970 +0000
65 summary: 2
65 summary: 2
66
66
67 changeset: 1:802f095af299
67 changeset: 1:802f095af299
68 tag: tip
68 tag: tip
69 user: test
69 user: test
70 date: Mon Jan 12 13:46:40 1970 +0000
70 date: Mon Jan 12 13:46:40 1970 +0000
71 files: a b
71 files: a b
72 description:
72 description:
73 2
73 2
74
74
75
75
76 changeset: 0:33aaa84a386b
76 changeset: 0:33aaa84a386b
77 user: test
77 user: test
78 date: Mon Jan 12 13:46:40 1970 +0000
78 date: Mon Jan 12 13:46:40 1970 +0000
79 files: a
79 files: a
80 description:
80 description:
81 1
81 1
82
82
83
83
84 diff -r 802f095af299 a
84 diff -r 802f095af299 a
85 --- a/a
85 --- a/a
86 +++ b/a
86 +++ b/a
87 @@ -1,1 +1,1 @@ a2
87 @@ -1,1 +1,1 @@ a2
88 -a2
88 -a2
89 +abc
89 +abc
90 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
90 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
91 adding b
91 adding b
92 M a
92 M a
93 changeset: 1:802f095af299
93 changeset: 1:802f095af299
94 user: test
94 user: test
95 date: Mon Jan 12 13:46:40 1970 +0000
95 date: Mon Jan 12 13:46:40 1970 +0000
96 summary: 2
96 summary: 2
97
97
98 abort: update spans branches, use 'hg merge' or 'hg update -C' to lose changes
98 abort: update spans branches, use 'hg merge' or 'hg update -C' to lose changes
99 failed
99 failed
100 abort: outstanding uncommitted changes
100 abort: outstanding uncommitted changes
101 failed
101 failed
102 resolving manifests
102 resolving manifests
103 overwrite False branchmerge True partial False linear False
103 overwrite False branchmerge True partial False
104 ancestor 802f095af299 local 030602aee63d remote 33aaa84a386b
104 ancestor 802f095af299 local 030602aee63d remote 33aaa84a386b
105 a versions differ, resolve
105 a versions differ, resolve
106 b versions differ, resolve
106 b versions differ, resolve
107 merging a
107 merging a
108 resolving a
108 resolving a
109 file a: my d730145abbf9 other 13e0d5f949fa ancestor b789fdd96dc2
109 file a: my d730145abbf9 other 13e0d5f949fa ancestor b789fdd96dc2
110 merging b
110 merging b
111 resolving b
111 resolving b
112 file b: my 1e88685f5dde other 61de8c7723ca ancestor 000000000000
112 file b: my 1e88685f5dde other 61de8c7723ca ancestor 000000000000
113 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
113 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
114 (branch merge, don't forget to commit)
114 (branch merge, don't forget to commit)
115 changeset: 1:802f095af299
115 changeset: 1:802f095af299
116 user: test
116 user: test
117 date: Mon Jan 12 13:46:40 1970 +0000
117 date: Mon Jan 12 13:46:40 1970 +0000
118 summary: 2
118 summary: 2
119
119
120 changeset: 2:030602aee63d
120 changeset: 2:030602aee63d
121 tag: tip
121 tag: tip
122 parent: 0:33aaa84a386b
122 parent: 0:33aaa84a386b
123 user: test
123 user: test
124 date: Mon Jan 12 13:46:40 1970 +0000
124 date: Mon Jan 12 13:46:40 1970 +0000
125 summary: 3
125 summary: 3
126
126
127 diff -r 802f095af299 a
127 diff -r 802f095af299 a
128 --- a/a
128 --- a/a
129 +++ b/a
129 +++ b/a
130 @@ -1,1 +1,1 @@ a2
130 @@ -1,1 +1,1 @@ a2
131 -a2
131 -a2
132 +abc
132 +abc
133 adding a
133 adding a
134 pulling from ../a
134 pulling from ../a
135 requesting all changes
135 requesting all changes
136 adding changesets
136 adding changesets
137 adding manifests
137 adding manifests
138 adding file changes
138 adding file changes
139 added 1 changesets with 1 changes to 1 files
139 added 1 changesets with 1 changes to 1 files
140 merging a
140 merging a
141 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
141 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
@@ -1,54 +1,54
1 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
2 Main should be gone
2 Main should be gone
3 a
3 a
4 changeset: 3:ded32b0db104
4 changeset: 3:ded32b0db104
5 tag: tip
5 tag: tip
6 user: test
6 user: test
7 date: Mon Jan 12 13:46:40 1970 +0000
7 date: Mon Jan 12 13:46:40 1970 +0000
8 summary: Added side2
8 summary: Added side2
9
9
10 changeset: 2:92a816cea698
10 changeset: 2:92a816cea698
11 parent: 0:537353581d3d
11 parent: 0:537353581d3d
12 user: test
12 user: test
13 date: Mon Jan 12 13:46:40 1970 +0000
13 date: Mon Jan 12 13:46:40 1970 +0000
14 summary: Added side1
14 summary: Added side1
15
15
16 changeset: 1:221226fb2bd8
16 changeset: 1:221226fb2bd8
17 user: test
17 user: test
18 date: Mon Jan 12 13:46:40 1970 +0000
18 date: Mon Jan 12 13:46:40 1970 +0000
19 summary: Added main
19 summary: Added main
20
20
21 changeset: 0:537353581d3d
21 changeset: 0:537353581d3d
22 user: test
22 user: test
23 date: Mon Jan 12 13:46:40 1970 +0000
23 date: Mon Jan 12 13:46:40 1970 +0000
24 summary: Added a
24 summary: Added a
25
25
26 Should have two heads, side2 and main
26 Should have two heads, side2 and main
27 changeset: 3:ded32b0db104
27 changeset: 3:ded32b0db104
28 tag: tip
28 tag: tip
29 user: test
29 user: test
30 date: Mon Jan 12 13:46:40 1970 +0000
30 date: Mon Jan 12 13:46:40 1970 +0000
31 summary: Added side2
31 summary: Added side2
32
32
33 changeset: 1:221226fb2bd8
33 changeset: 1:221226fb2bd8
34 user: test
34 user: test
35 date: Mon Jan 12 13:46:40 1970 +0000
35 date: Mon Jan 12 13:46:40 1970 +0000
36 summary: Added main
36 summary: Added main
37
37
38 Should show a side1 side2
38 Should show a side1 side2
39 a
39 a
40 side1
40 side1
41 side2
41 side2
42 resolving manifests
42 resolving manifests
43 overwrite True branchmerge False partial False linear False
43 overwrite True branchmerge False partial False
44 ancestor ded32b0db104 local 221226fb2bd8 remote 537353581d3d
44 ancestor ded32b0db104 local 221226fb2bd8 remote 537353581d3d
45 remote deleted side2, clobbering
45 remote deleted side2, clobbering
46 remote deleted side1, clobbering
46 remote deleted side1, clobbering
47 remote created main
47 remote created main
48 getting main
48 getting main
49 removing side1
49 removing side1
50 removing side2
50 removing side2
51 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
51 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
52 Should only show a main
52 Should only show a main
53 a
53 a
54 main
54 main
General Comments 0
You need to be logged in to leave comments. Login now