##// END OF EJS Templates
merge: back out single-parent fast-forward merge...
Matt Mackall -
r13550:1792b8a9 stable
parent child Browse files
Show More
@@ -1,560 +1,560
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, 2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import nullid, nullrev, hex, bin
8 from node import nullid, nullrev, hex, bin
9 from i18n import _
9 from i18n import _
10 import util, filemerge, copies, subrepo
10 import util, filemerge, copies, subrepo
11 import errno, os, shutil
11 import errno, os, shutil
12
12
13 class mergestate(object):
13 class mergestate(object):
14 '''track 3-way merge state of individual files'''
14 '''track 3-way merge state of individual files'''
15 def __init__(self, repo):
15 def __init__(self, repo):
16 self._repo = repo
16 self._repo = repo
17 self._dirty = False
17 self._dirty = False
18 self._read()
18 self._read()
19 def reset(self, node=None):
19 def reset(self, node=None):
20 self._state = {}
20 self._state = {}
21 if node:
21 if node:
22 self._local = node
22 self._local = node
23 shutil.rmtree(self._repo.join("merge"), True)
23 shutil.rmtree(self._repo.join("merge"), True)
24 self._dirty = False
24 self._dirty = False
25 def _read(self):
25 def _read(self):
26 self._state = {}
26 self._state = {}
27 try:
27 try:
28 f = self._repo.opener("merge/state")
28 f = self._repo.opener("merge/state")
29 for i, l in enumerate(f):
29 for i, l in enumerate(f):
30 if i == 0:
30 if i == 0:
31 self._local = bin(l[:-1])
31 self._local = bin(l[:-1])
32 else:
32 else:
33 bits = l[:-1].split("\0")
33 bits = l[:-1].split("\0")
34 self._state[bits[0]] = bits[1:]
34 self._state[bits[0]] = bits[1:]
35 f.close()
35 f.close()
36 except IOError, err:
36 except IOError, err:
37 if err.errno != errno.ENOENT:
37 if err.errno != errno.ENOENT:
38 raise
38 raise
39 self._dirty = False
39 self._dirty = False
40 def commit(self):
40 def commit(self):
41 if self._dirty:
41 if self._dirty:
42 f = self._repo.opener("merge/state", "w")
42 f = self._repo.opener("merge/state", "w")
43 f.write(hex(self._local) + "\n")
43 f.write(hex(self._local) + "\n")
44 for d, v in self._state.iteritems():
44 for d, v in self._state.iteritems():
45 f.write("\0".join([d] + v) + "\n")
45 f.write("\0".join([d] + v) + "\n")
46 f.close()
46 f.close()
47 self._dirty = False
47 self._dirty = False
48 def add(self, fcl, fco, fca, fd, flags):
48 def add(self, fcl, fco, fca, fd, flags):
49 hash = util.sha1(fcl.path()).hexdigest()
49 hash = util.sha1(fcl.path()).hexdigest()
50 self._repo.opener("merge/" + hash, "w").write(fcl.data())
50 self._repo.opener("merge/" + hash, "w").write(fcl.data())
51 self._state[fd] = ['u', hash, fcl.path(), fca.path(),
51 self._state[fd] = ['u', hash, fcl.path(), fca.path(),
52 hex(fca.filenode()), fco.path(), flags]
52 hex(fca.filenode()), fco.path(), flags]
53 self._dirty = True
53 self._dirty = True
54 def __contains__(self, dfile):
54 def __contains__(self, dfile):
55 return dfile in self._state
55 return dfile in self._state
56 def __getitem__(self, dfile):
56 def __getitem__(self, dfile):
57 return self._state[dfile][0]
57 return self._state[dfile][0]
58 def __iter__(self):
58 def __iter__(self):
59 l = self._state.keys()
59 l = self._state.keys()
60 l.sort()
60 l.sort()
61 for f in l:
61 for f in l:
62 yield f
62 yield f
63 def mark(self, dfile, state):
63 def mark(self, dfile, state):
64 self._state[dfile][0] = state
64 self._state[dfile][0] = state
65 self._dirty = True
65 self._dirty = True
66 def resolve(self, dfile, wctx, octx):
66 def resolve(self, dfile, wctx, octx):
67 if self[dfile] == 'r':
67 if self[dfile] == 'r':
68 return 0
68 return 0
69 state, hash, lfile, afile, anode, ofile, flags = self._state[dfile]
69 state, hash, lfile, afile, anode, ofile, flags = self._state[dfile]
70 f = self._repo.opener("merge/" + hash)
70 f = self._repo.opener("merge/" + hash)
71 self._repo.wwrite(dfile, f.read(), flags)
71 self._repo.wwrite(dfile, f.read(), flags)
72 f.close()
72 f.close()
73 fcd = wctx[dfile]
73 fcd = wctx[dfile]
74 fco = octx[ofile]
74 fco = octx[ofile]
75 fca = self._repo.filectx(afile, fileid=anode)
75 fca = self._repo.filectx(afile, fileid=anode)
76 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
76 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
77 if r is None:
77 if r is None:
78 # no real conflict
78 # no real conflict
79 del self._state[dfile]
79 del self._state[dfile]
80 elif not r:
80 elif not r:
81 self.mark(dfile, 'r')
81 self.mark(dfile, 'r')
82 return r
82 return r
83
83
84 def _checkunknown(wctx, mctx):
84 def _checkunknown(wctx, mctx):
85 "check for collisions between unknown files and files in mctx"
85 "check for collisions between unknown files and files in mctx"
86 for f in wctx.unknown():
86 for f in wctx.unknown():
87 if f in mctx and mctx[f].cmp(wctx[f]):
87 if f in mctx and mctx[f].cmp(wctx[f]):
88 raise util.Abort(_("untracked file in working directory differs"
88 raise util.Abort(_("untracked file in working directory differs"
89 " from file in requested revision: '%s'") % f)
89 " from file in requested revision: '%s'") % f)
90
90
91 def _checkcollision(mctx):
91 def _checkcollision(mctx):
92 "check for case folding collisions in the destination context"
92 "check for case folding collisions in the destination context"
93 folded = {}
93 folded = {}
94 for fn in mctx:
94 for fn in mctx:
95 fold = fn.lower()
95 fold = fn.lower()
96 if fold in folded:
96 if fold in folded:
97 raise util.Abort(_("case-folding collision between %s and %s")
97 raise util.Abort(_("case-folding collision between %s and %s")
98 % (fn, folded[fold]))
98 % (fn, folded[fold]))
99 folded[fold] = fn
99 folded[fold] = fn
100
100
101 def _forgetremoved(wctx, mctx, branchmerge):
101 def _forgetremoved(wctx, mctx, branchmerge):
102 """
102 """
103 Forget removed files
103 Forget removed files
104
104
105 If we're jumping between revisions (as opposed to merging), and if
105 If we're jumping between revisions (as opposed to merging), and if
106 neither the working directory nor the target rev has the file,
106 neither the working directory nor the target rev has the file,
107 then we need to remove it from the dirstate, to prevent the
107 then we need to remove it from the dirstate, to prevent the
108 dirstate from listing the file when it is no longer in the
108 dirstate from listing the file when it is no longer in the
109 manifest.
109 manifest.
110
110
111 If we're merging, and the other revision has removed a file
111 If we're merging, and the other revision has removed a file
112 that is not present in the working directory, we need to mark it
112 that is not present in the working directory, we need to mark it
113 as removed.
113 as removed.
114 """
114 """
115
115
116 action = []
116 action = []
117 state = branchmerge and 'r' or 'f'
117 state = branchmerge and 'r' or 'f'
118 for f in wctx.deleted():
118 for f in wctx.deleted():
119 if f not in mctx:
119 if f not in mctx:
120 action.append((f, state))
120 action.append((f, state))
121
121
122 if not branchmerge:
122 if not branchmerge:
123 for f in wctx.removed():
123 for f in wctx.removed():
124 if f not in mctx:
124 if f not in mctx:
125 action.append((f, "f"))
125 action.append((f, "f"))
126
126
127 return action
127 return action
128
128
129 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
129 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
130 """
130 """
131 Merge p1 and p2 with ancestor pa and generate merge action list
131 Merge p1 and p2 with ancestor pa and generate merge action list
132
132
133 overwrite = whether we clobber working files
133 overwrite = whether we clobber working files
134 partial = function to filter file lists
134 partial = function to filter file lists
135 """
135 """
136
136
137 def fmerge(f, f2, fa):
137 def fmerge(f, f2, fa):
138 """merge flags"""
138 """merge flags"""
139 a, m, n = ma.flags(fa), m1.flags(f), m2.flags(f2)
139 a, m, n = ma.flags(fa), m1.flags(f), m2.flags(f2)
140 if m == n: # flags agree
140 if m == n: # flags agree
141 return m # unchanged
141 return m # unchanged
142 if m and n and not a: # flags set, don't agree, differ from parent
142 if m and n and not a: # flags set, don't agree, differ from parent
143 r = repo.ui.promptchoice(
143 r = repo.ui.promptchoice(
144 _(" conflicting flags for %s\n"
144 _(" conflicting flags for %s\n"
145 "(n)one, e(x)ec or sym(l)ink?") % f,
145 "(n)one, e(x)ec or sym(l)ink?") % f,
146 (_("&None"), _("E&xec"), _("Sym&link")), 0)
146 (_("&None"), _("E&xec"), _("Sym&link")), 0)
147 if r == 1:
147 if r == 1:
148 return "x" # Exec
148 return "x" # Exec
149 if r == 2:
149 if r == 2:
150 return "l" # Symlink
150 return "l" # Symlink
151 return ""
151 return ""
152 if m and m != a: # changed from a to m
152 if m and m != a: # changed from a to m
153 return m
153 return m
154 if n and n != a: # changed from a to n
154 if n and n != a: # changed from a to n
155 return n
155 return n
156 return '' # flag was cleared
156 return '' # flag was cleared
157
157
158 def act(msg, m, f, *args):
158 def act(msg, m, f, *args):
159 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
159 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
160 action.append((f, m) + args)
160 action.append((f, m) + args)
161
161
162 action, copy = [], {}
162 action, copy = [], {}
163
163
164 if overwrite:
164 if overwrite:
165 pa = p1
165 pa = p1
166 elif pa == p2: # backwards
166 elif pa == p2: # backwards
167 pa = p1.p1()
167 pa = p1.p1()
168 elif pa and repo.ui.configbool("merge", "followcopies", True):
168 elif pa and repo.ui.configbool("merge", "followcopies", True):
169 dirs = repo.ui.configbool("merge", "followdirs", True)
169 dirs = repo.ui.configbool("merge", "followdirs", True)
170 copy, diverge = copies.copies(repo, p1, p2, pa, dirs)
170 copy, diverge = copies.copies(repo, p1, p2, pa, dirs)
171 for of, fl in diverge.iteritems():
171 for of, fl in diverge.iteritems():
172 act("divergent renames", "dr", of, fl)
172 act("divergent renames", "dr", of, fl)
173
173
174 repo.ui.note(_("resolving manifests\n"))
174 repo.ui.note(_("resolving manifests\n"))
175 repo.ui.debug(" overwrite %s partial %s\n" % (overwrite, bool(partial)))
175 repo.ui.debug(" overwrite %s partial %s\n" % (overwrite, bool(partial)))
176 repo.ui.debug(" ancestor %s local %s remote %s\n" % (pa, p1, p2))
176 repo.ui.debug(" ancestor %s local %s remote %s\n" % (pa, p1, p2))
177
177
178 m1, m2, ma = p1.manifest(), p2.manifest(), pa.manifest()
178 m1, m2, ma = p1.manifest(), p2.manifest(), pa.manifest()
179 copied = set(copy.values())
179 copied = set(copy.values())
180
180
181 if '.hgsubstate' in m1:
181 if '.hgsubstate' in m1:
182 # check whether sub state is modified
182 # check whether sub state is modified
183 for s in p1.substate:
183 for s in p1.substate:
184 if p1.sub(s).dirty():
184 if p1.sub(s).dirty():
185 m1['.hgsubstate'] += "+"
185 m1['.hgsubstate'] += "+"
186 break
186 break
187
187
188 # Compare manifests
188 # Compare manifests
189 for f, n in m1.iteritems():
189 for f, n in m1.iteritems():
190 if partial and not partial(f):
190 if partial and not partial(f):
191 continue
191 continue
192 if f in m2:
192 if f in m2:
193 rflags = fmerge(f, f, f)
193 rflags = fmerge(f, f, f)
194 a = ma.get(f, nullid)
194 a = ma.get(f, nullid)
195 if n == m2[f] or m2[f] == a: # same or local newer
195 if n == m2[f] or m2[f] == a: # same or local newer
196 # is file locally modified or flags need changing?
196 # is file locally modified or flags need changing?
197 # dirstate flags may need to be made current
197 # dirstate flags may need to be made current
198 if m1.flags(f) != rflags or n[20:]:
198 if m1.flags(f) != rflags or n[20:]:
199 act("update permissions", "e", f, rflags)
199 act("update permissions", "e", f, rflags)
200 elif n == a: # remote newer
200 elif n == a: # remote newer
201 act("remote is newer", "g", f, rflags)
201 act("remote is newer", "g", f, rflags)
202 else: # both changed
202 else: # both changed
203 act("versions differ", "m", f, f, f, rflags, False)
203 act("versions differ", "m", f, f, f, rflags, False)
204 elif f in copied: # files we'll deal with on m2 side
204 elif f in copied: # files we'll deal with on m2 side
205 pass
205 pass
206 elif f in copy:
206 elif f in copy:
207 f2 = copy[f]
207 f2 = copy[f]
208 if f2 not in m2: # directory rename
208 if f2 not in m2: # directory rename
209 act("remote renamed directory to " + f2, "d",
209 act("remote renamed directory to " + f2, "d",
210 f, None, f2, m1.flags(f))
210 f, None, f2, m1.flags(f))
211 else: # case 2 A,B/B/B or case 4,21 A/B/B
211 else: # case 2 A,B/B/B or case 4,21 A/B/B
212 act("local copied/moved to " + f2, "m",
212 act("local copied/moved to " + f2, "m",
213 f, f2, f, fmerge(f, f2, f2), False)
213 f, f2, f, fmerge(f, f2, f2), False)
214 elif f in ma: # clean, a different, no remote
214 elif f in ma: # clean, a different, no remote
215 if n != ma[f]:
215 if n != ma[f]:
216 if repo.ui.promptchoice(
216 if repo.ui.promptchoice(
217 _(" local changed %s which remote deleted\n"
217 _(" local changed %s which remote deleted\n"
218 "use (c)hanged version or (d)elete?") % f,
218 "use (c)hanged version or (d)elete?") % f,
219 (_("&Changed"), _("&Delete")), 0):
219 (_("&Changed"), _("&Delete")), 0):
220 act("prompt delete", "r", f)
220 act("prompt delete", "r", f)
221 else:
221 else:
222 act("prompt keep", "a", f)
222 act("prompt keep", "a", f)
223 elif n[20:] == "a": # added, no remote
223 elif n[20:] == "a": # added, no remote
224 act("remote deleted", "f", f)
224 act("remote deleted", "f", f)
225 elif n[20:] != "u":
225 elif n[20:] != "u":
226 act("other deleted", "r", f)
226 act("other deleted", "r", f)
227
227
228 for f, n in m2.iteritems():
228 for f, n in m2.iteritems():
229 if partial and not partial(f):
229 if partial and not partial(f):
230 continue
230 continue
231 if f in m1 or f in copied: # files already visited
231 if f in m1 or f in copied: # files already visited
232 continue
232 continue
233 if f in copy:
233 if f in copy:
234 f2 = copy[f]
234 f2 = copy[f]
235 if f2 not in m1: # directory rename
235 if f2 not in m1: # directory rename
236 act("local renamed directory to " + f2, "d",
236 act("local renamed directory to " + f2, "d",
237 None, f, f2, m2.flags(f))
237 None, f, f2, m2.flags(f))
238 elif f2 in m2: # rename case 1, A/A,B/A
238 elif f2 in m2: # rename case 1, A/A,B/A
239 act("remote copied to " + f, "m",
239 act("remote copied to " + f, "m",
240 f2, f, f, fmerge(f2, f, f2), False)
240 f2, f, f, fmerge(f2, f, f2), False)
241 else: # case 3,20 A/B/A
241 else: # case 3,20 A/B/A
242 act("remote moved to " + f, "m",
242 act("remote moved to " + f, "m",
243 f2, f, f, fmerge(f2, f, f2), True)
243 f2, f, f, fmerge(f2, f, f2), True)
244 elif f not in ma:
244 elif f not in ma:
245 act("remote created", "g", f, m2.flags(f))
245 act("remote created", "g", f, m2.flags(f))
246 elif n != ma[f]:
246 elif n != ma[f]:
247 if repo.ui.promptchoice(
247 if repo.ui.promptchoice(
248 _("remote changed %s which local deleted\n"
248 _("remote changed %s which local deleted\n"
249 "use (c)hanged version or leave (d)eleted?") % f,
249 "use (c)hanged version or leave (d)eleted?") % f,
250 (_("&Changed"), _("&Deleted")), 0) == 0:
250 (_("&Changed"), _("&Deleted")), 0) == 0:
251 act("prompt recreating", "g", f, m2.flags(f))
251 act("prompt recreating", "g", f, m2.flags(f))
252
252
253 return action
253 return action
254
254
255 def actionkey(a):
255 def actionkey(a):
256 return a[1] == 'r' and -1 or 0, a
256 return a[1] == 'r' and -1 or 0, a
257
257
258 def applyupdates(repo, action, wctx, mctx, actx, overwrite):
258 def applyupdates(repo, action, wctx, mctx, actx, overwrite):
259 """apply the merge action list to the working directory
259 """apply the merge action list to the working directory
260
260
261 wctx is the working copy context
261 wctx is the working copy context
262 mctx is the context to be merged into the working copy
262 mctx is the context to be merged into the working copy
263 actx is the context of the common ancestor
263 actx is the context of the common ancestor
264
264
265 Return a tuple of counts (updated, merged, removed, unresolved) that
265 Return a tuple of counts (updated, merged, removed, unresolved) that
266 describes how many files were affected by the update.
266 describes how many files were affected by the update.
267 """
267 """
268
268
269 updated, merged, removed, unresolved = 0, 0, 0, 0
269 updated, merged, removed, unresolved = 0, 0, 0, 0
270 ms = mergestate(repo)
270 ms = mergestate(repo)
271 ms.reset(wctx.parents()[0].node())
271 ms.reset(wctx.parents()[0].node())
272 moves = []
272 moves = []
273 action.sort(key=actionkey)
273 action.sort(key=actionkey)
274 substate = wctx.substate # prime
274 substate = wctx.substate # prime
275
275
276 # prescan for merges
276 # prescan for merges
277 u = repo.ui
277 u = repo.ui
278 for a in action:
278 for a in action:
279 f, m = a[:2]
279 f, m = a[:2]
280 if m == 'm': # merge
280 if m == 'm': # merge
281 f2, fd, flags, move = a[2:]
281 f2, fd, flags, move = a[2:]
282 if f == '.hgsubstate': # merged internally
282 if f == '.hgsubstate': # merged internally
283 continue
283 continue
284 repo.ui.debug("preserving %s for resolve of %s\n" % (f, fd))
284 repo.ui.debug("preserving %s for resolve of %s\n" % (f, fd))
285 fcl = wctx[f]
285 fcl = wctx[f]
286 fco = mctx[f2]
286 fco = mctx[f2]
287 if mctx == actx: # backwards, use working dir parent as ancestor
287 if mctx == actx: # backwards, use working dir parent as ancestor
288 if fcl.parents():
288 if fcl.parents():
289 fca = fcl.parents()[0]
289 fca = fcl.parents()[0]
290 else:
290 else:
291 fca = repo.filectx(f, fileid=nullrev)
291 fca = repo.filectx(f, fileid=nullrev)
292 else:
292 else:
293 fca = fcl.ancestor(fco, actx)
293 fca = fcl.ancestor(fco, actx)
294 if not fca:
294 if not fca:
295 fca = repo.filectx(f, fileid=nullrev)
295 fca = repo.filectx(f, fileid=nullrev)
296 ms.add(fcl, fco, fca, fd, flags)
296 ms.add(fcl, fco, fca, fd, flags)
297 if f != fd and move:
297 if f != fd and move:
298 moves.append(f)
298 moves.append(f)
299
299
300 # remove renamed files after safely stored
300 # remove renamed files after safely stored
301 for f in moves:
301 for f in moves:
302 if os.path.lexists(repo.wjoin(f)):
302 if os.path.lexists(repo.wjoin(f)):
303 repo.ui.debug("removing %s\n" % f)
303 repo.ui.debug("removing %s\n" % f)
304 os.unlink(repo.wjoin(f))
304 os.unlink(repo.wjoin(f))
305
305
306 audit_path = util.path_auditor(repo.root)
306 audit_path = util.path_auditor(repo.root)
307
307
308 numupdates = len(action)
308 numupdates = len(action)
309 for i, a in enumerate(action):
309 for i, a in enumerate(action):
310 f, m = a[:2]
310 f, m = a[:2]
311 u.progress(_('updating'), i + 1, item=f, total=numupdates,
311 u.progress(_('updating'), i + 1, item=f, total=numupdates,
312 unit=_('files'))
312 unit=_('files'))
313 if f and f[0] == "/":
313 if f and f[0] == "/":
314 continue
314 continue
315 if m == "r": # remove
315 if m == "r": # remove
316 repo.ui.note(_("removing %s\n") % f)
316 repo.ui.note(_("removing %s\n") % f)
317 audit_path(f)
317 audit_path(f)
318 if f == '.hgsubstate': # subrepo states need updating
318 if f == '.hgsubstate': # subrepo states need updating
319 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
319 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
320 try:
320 try:
321 util.unlinkpath(repo.wjoin(f))
321 util.unlinkpath(repo.wjoin(f))
322 except OSError, inst:
322 except OSError, inst:
323 if inst.errno != errno.ENOENT:
323 if inst.errno != errno.ENOENT:
324 repo.ui.warn(_("update failed to remove %s: %s!\n") %
324 repo.ui.warn(_("update failed to remove %s: %s!\n") %
325 (f, inst.strerror))
325 (f, inst.strerror))
326 removed += 1
326 removed += 1
327 elif m == "m": # merge
327 elif m == "m": # merge
328 if f == '.hgsubstate': # subrepo states need updating
328 if f == '.hgsubstate': # subrepo states need updating
329 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), overwrite)
329 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), overwrite)
330 continue
330 continue
331 f2, fd, flags, move = a[2:]
331 f2, fd, flags, move = a[2:]
332 r = ms.resolve(fd, wctx, mctx)
332 r = ms.resolve(fd, wctx, mctx)
333 if r is not None and r > 0:
333 if r is not None and r > 0:
334 unresolved += 1
334 unresolved += 1
335 else:
335 else:
336 if r is None:
336 if r is None:
337 updated += 1
337 updated += 1
338 else:
338 else:
339 merged += 1
339 merged += 1
340 util.set_flags(repo.wjoin(fd), 'l' in flags, 'x' in flags)
340 util.set_flags(repo.wjoin(fd), 'l' in flags, 'x' in flags)
341 if f != fd and move and os.path.lexists(repo.wjoin(f)):
341 if f != fd and move and os.path.lexists(repo.wjoin(f)):
342 repo.ui.debug("removing %s\n" % f)
342 repo.ui.debug("removing %s\n" % f)
343 os.unlink(repo.wjoin(f))
343 os.unlink(repo.wjoin(f))
344 elif m == "g": # get
344 elif m == "g": # get
345 flags = a[2]
345 flags = a[2]
346 repo.ui.note(_("getting %s\n") % f)
346 repo.ui.note(_("getting %s\n") % f)
347 t = mctx.filectx(f).data()
347 t = mctx.filectx(f).data()
348 repo.wwrite(f, t, flags)
348 repo.wwrite(f, t, flags)
349 t = None
349 t = None
350 updated += 1
350 updated += 1
351 if f == '.hgsubstate': # subrepo states need updating
351 if f == '.hgsubstate': # subrepo states need updating
352 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
352 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
353 elif m == "d": # directory rename
353 elif m == "d": # directory rename
354 f2, fd, flags = a[2:]
354 f2, fd, flags = a[2:]
355 if f:
355 if f:
356 repo.ui.note(_("moving %s to %s\n") % (f, fd))
356 repo.ui.note(_("moving %s to %s\n") % (f, fd))
357 t = wctx.filectx(f).data()
357 t = wctx.filectx(f).data()
358 repo.wwrite(fd, t, flags)
358 repo.wwrite(fd, t, flags)
359 util.unlinkpath(repo.wjoin(f))
359 util.unlinkpath(repo.wjoin(f))
360 if f2:
360 if f2:
361 repo.ui.note(_("getting %s to %s\n") % (f2, fd))
361 repo.ui.note(_("getting %s to %s\n") % (f2, fd))
362 t = mctx.filectx(f2).data()
362 t = mctx.filectx(f2).data()
363 repo.wwrite(fd, t, flags)
363 repo.wwrite(fd, t, flags)
364 updated += 1
364 updated += 1
365 elif m == "dr": # divergent renames
365 elif m == "dr": # divergent renames
366 fl = a[2]
366 fl = a[2]
367 repo.ui.warn(_("note: possible conflict - %s was renamed "
367 repo.ui.warn(_("note: possible conflict - %s was renamed "
368 "multiple times to:\n") % f)
368 "multiple times to:\n") % f)
369 for nf in fl:
369 for nf in fl:
370 repo.ui.warn(" %s\n" % nf)
370 repo.ui.warn(" %s\n" % nf)
371 elif m == "e": # exec
371 elif m == "e": # exec
372 flags = a[2]
372 flags = a[2]
373 util.set_flags(repo.wjoin(f), 'l' in flags, 'x' in flags)
373 util.set_flags(repo.wjoin(f), 'l' in flags, 'x' in flags)
374 ms.commit()
374 ms.commit()
375 u.progress(_('updating'), None, total=numupdates, unit=_('files'))
375 u.progress(_('updating'), None, total=numupdates, unit=_('files'))
376
376
377 return updated, merged, removed, unresolved
377 return updated, merged, removed, unresolved
378
378
379 def recordupdates(repo, action, branchmerge):
379 def recordupdates(repo, action, branchmerge):
380 "record merge actions to the dirstate"
380 "record merge actions to the dirstate"
381
381
382 for a in action:
382 for a in action:
383 f, m = a[:2]
383 f, m = a[:2]
384 if m == "r": # remove
384 if m == "r": # remove
385 if branchmerge:
385 if branchmerge:
386 repo.dirstate.remove(f)
386 repo.dirstate.remove(f)
387 else:
387 else:
388 repo.dirstate.forget(f)
388 repo.dirstate.forget(f)
389 elif m == "a": # re-add
389 elif m == "a": # re-add
390 if not branchmerge:
390 if not branchmerge:
391 repo.dirstate.add(f)
391 repo.dirstate.add(f)
392 elif m == "f": # forget
392 elif m == "f": # forget
393 repo.dirstate.forget(f)
393 repo.dirstate.forget(f)
394 elif m == "e": # exec change
394 elif m == "e": # exec change
395 repo.dirstate.normallookup(f)
395 repo.dirstate.normallookup(f)
396 elif m == "g": # get
396 elif m == "g": # get
397 if branchmerge:
397 if branchmerge:
398 repo.dirstate.otherparent(f)
398 repo.dirstate.otherparent(f)
399 else:
399 else:
400 repo.dirstate.normal(f)
400 repo.dirstate.normal(f)
401 elif m == "m": # merge
401 elif m == "m": # merge
402 f2, fd, flag, move = a[2:]
402 f2, fd, flag, move = a[2:]
403 if branchmerge:
403 if branchmerge:
404 # We've done a branch merge, mark this file as merged
404 # We've done a branch merge, mark this file as merged
405 # so that we properly record the merger later
405 # so that we properly record the merger later
406 repo.dirstate.merge(fd)
406 repo.dirstate.merge(fd)
407 if f != f2: # copy/rename
407 if f != f2: # copy/rename
408 if move:
408 if move:
409 repo.dirstate.remove(f)
409 repo.dirstate.remove(f)
410 if f != fd:
410 if f != fd:
411 repo.dirstate.copy(f, fd)
411 repo.dirstate.copy(f, fd)
412 else:
412 else:
413 repo.dirstate.copy(f2, fd)
413 repo.dirstate.copy(f2, fd)
414 else:
414 else:
415 # We've update-merged a locally modified file, so
415 # We've update-merged a locally modified file, so
416 # we set the dirstate to emulate a normal checkout
416 # we set the dirstate to emulate a normal checkout
417 # of that file some time in the past. Thus our
417 # of that file some time in the past. Thus our
418 # merge will appear as a normal local file
418 # merge will appear as a normal local file
419 # modification.
419 # modification.
420 if f2 == fd: # file not locally copied/moved
420 if f2 == fd: # file not locally copied/moved
421 repo.dirstate.normallookup(fd)
421 repo.dirstate.normallookup(fd)
422 if move:
422 if move:
423 repo.dirstate.forget(f)
423 repo.dirstate.forget(f)
424 elif m == "d": # directory rename
424 elif m == "d": # directory rename
425 f2, fd, flag = a[2:]
425 f2, fd, flag = a[2:]
426 if not f2 and f not in repo.dirstate:
426 if not f2 and f not in repo.dirstate:
427 # untracked file moved
427 # untracked file moved
428 continue
428 continue
429 if branchmerge:
429 if branchmerge:
430 repo.dirstate.add(fd)
430 repo.dirstate.add(fd)
431 if f:
431 if f:
432 repo.dirstate.remove(f)
432 repo.dirstate.remove(f)
433 repo.dirstate.copy(f, fd)
433 repo.dirstate.copy(f, fd)
434 if f2:
434 if f2:
435 repo.dirstate.copy(f2, fd)
435 repo.dirstate.copy(f2, fd)
436 else:
436 else:
437 repo.dirstate.normal(fd)
437 repo.dirstate.normal(fd)
438 if f:
438 if f:
439 repo.dirstate.forget(f)
439 repo.dirstate.forget(f)
440
440
441 def update(repo, node, branchmerge, force, partial):
441 def update(repo, node, branchmerge, force, partial):
442 """
442 """
443 Perform a merge between the working directory and the given node
443 Perform a merge between the working directory and the given node
444
444
445 node = the node to update to, or None if unspecified
445 node = the node to update to, or None if unspecified
446 branchmerge = whether to merge between branches
446 branchmerge = whether to merge between branches
447 force = whether to force branch merging or file overwriting
447 force = whether to force branch merging or file overwriting
448 partial = a function to filter file lists (dirstate not updated)
448 partial = a function to filter file lists (dirstate not updated)
449
449
450 The table below shows all the behaviors of the update command
450 The table below shows all the behaviors of the update command
451 given the -c and -C or no options, whether the working directory
451 given the -c and -C or no options, whether the working directory
452 is dirty, whether a revision is specified, and the relationship of
452 is dirty, whether a revision is specified, and the relationship of
453 the parent rev to the target rev (linear, on the same named
453 the parent rev to the target rev (linear, on the same named
454 branch, or on another named branch).
454 branch, or on another named branch).
455
455
456 This logic is tested by test-update-branches.t.
456 This logic is tested by test-update-branches.t.
457
457
458 -c -C dirty rev | linear same cross
458 -c -C dirty rev | linear same cross
459 n n n n | ok (1) x
459 n n n n | ok (1) x
460 n n n y | ok ok ok
460 n n n y | ok ok ok
461 n n y * | merge (2) (2)
461 n n y * | merge (2) (2)
462 n y * * | --- discard ---
462 n y * * | --- discard ---
463 y n y * | --- (3) ---
463 y n y * | --- (3) ---
464 y n n * | --- ok ---
464 y n n * | --- ok ---
465 y y * * | --- (4) ---
465 y y * * | --- (4) ---
466
466
467 x = can't happen
467 x = can't happen
468 * = don't-care
468 * = don't-care
469 1 = abort: crosses branches (use 'hg merge' or 'hg update -c')
469 1 = abort: crosses branches (use 'hg merge' or 'hg update -c')
470 2 = abort: crosses branches (use 'hg merge' to merge or
470 2 = abort: crosses branches (use 'hg merge' to merge or
471 use 'hg update -C' to discard changes)
471 use 'hg update -C' to discard changes)
472 3 = abort: uncommitted local changes
472 3 = abort: uncommitted local changes
473 4 = incompatible options (checked in commands.py)
473 4 = incompatible options (checked in commands.py)
474
474
475 Return the same tuple as applyupdates().
475 Return the same tuple as applyupdates().
476 """
476 """
477
477
478 onode = node
478 onode = node
479 wlock = repo.wlock()
479 wlock = repo.wlock()
480 try:
480 try:
481 wc = repo[None]
481 wc = repo[None]
482 if node is None:
482 if node is None:
483 # tip of current branch
483 # tip of current branch
484 try:
484 try:
485 node = repo.branchtags()[wc.branch()]
485 node = repo.branchtags()[wc.branch()]
486 except KeyError:
486 except KeyError:
487 if wc.branch() == "default": # no default branch!
487 if wc.branch() == "default": # no default branch!
488 node = repo.lookup("tip") # update to tip
488 node = repo.lookup("tip") # update to tip
489 else:
489 else:
490 raise util.Abort(_("branch %s not found") % wc.branch())
490 raise util.Abort(_("branch %s not found") % wc.branch())
491 overwrite = force and not branchmerge
491 overwrite = force and not branchmerge
492 pl = wc.parents()
492 pl = wc.parents()
493 p1, p2 = pl[0], repo[node]
493 p1, p2 = pl[0], repo[node]
494 pa = p1.ancestor(p2)
494 pa = p1.ancestor(p2)
495 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
495 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
496 fastforward = False
496 fastforward = False
497
497
498 ### check phase
498 ### check phase
499 if not overwrite and len(pl) > 1:
499 if not overwrite and len(pl) > 1:
500 raise util.Abort(_("outstanding uncommitted merges"))
500 raise util.Abort(_("outstanding uncommitted merges"))
501 if branchmerge:
501 if branchmerge:
502 if pa == p2:
502 if pa == p2:
503 raise util.Abort(_("merging with a working directory ancestor"
503 raise util.Abort(_("merging with a working directory ancestor"
504 " has no effect"))
504 " has no effect"))
505 elif pa == p1:
505 elif pa == p1:
506 if p1.branch() != p2.branch():
506 if p1.branch() != p2.branch():
507 fastforward = True
507 fastforward = True
508 else:
508 else:
509 raise util.Abort(_("nothing to merge (use 'hg update'"
509 raise util.Abort(_("nothing to merge (use 'hg update'"
510 " or check 'hg heads')"))
510 " or check 'hg heads')"))
511 if not force and (wc.files() or wc.deleted()):
511 if not force and (wc.files() or wc.deleted()):
512 raise util.Abort(_("outstanding uncommitted changes "
512 raise util.Abort(_("outstanding uncommitted changes "
513 "(use 'hg status' to list changes)"))
513 "(use 'hg status' to list changes)"))
514 for s in wc.substate:
514 for s in wc.substate:
515 if wc.sub(s).dirty():
515 if wc.sub(s).dirty():
516 raise util.Abort(_("outstanding uncommitted changes in "
516 raise util.Abort(_("outstanding uncommitted changes in "
517 "subrepository '%s'") % s)
517 "subrepository '%s'") % s)
518
518
519 elif not overwrite:
519 elif not overwrite:
520 if pa == p1 or pa == p2: # linear
520 if pa == p1 or pa == p2: # linear
521 pass # all good
521 pass # all good
522 elif wc.files() or wc.deleted():
522 elif wc.files() or wc.deleted():
523 raise util.Abort(_("crosses branches (merge branches or use"
523 raise util.Abort(_("crosses branches (merge branches or use"
524 " --clean to discard changes)"))
524 " --clean to discard changes)"))
525 elif onode is None:
525 elif onode is None:
526 raise util.Abort(_("crosses branches (merge branches or use"
526 raise util.Abort(_("crosses branches (merge branches or use"
527 " --check to force update)"))
527 " --check to force update)"))
528 else:
528 else:
529 # Allow jumping branches if clean and specific rev given
529 # Allow jumping branches if clean and specific rev given
530 overwrite = True
530 overwrite = True
531
531
532 ### calculate phase
532 ### calculate phase
533 action = []
533 action = []
534 wc.status(unknown=True) # prime cache
534 wc.status(unknown=True) # prime cache
535 if not force:
535 if not force:
536 _checkunknown(wc, p2)
536 _checkunknown(wc, p2)
537 if not util.checkcase(repo.path):
537 if not util.checkcase(repo.path):
538 _checkcollision(p2)
538 _checkcollision(p2)
539 action += _forgetremoved(wc, p2, branchmerge)
539 action += _forgetremoved(wc, p2, branchmerge)
540 action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
540 action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
541
541
542 ### apply phase
542 ### apply phase
543 if not branchmerge or fastforward: # just jump to the new rev
543 if not branchmerge: # just jump to the new rev
544 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
544 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
545 if not partial:
545 if not partial:
546 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
546 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
547
547
548 stats = applyupdates(repo, action, wc, p2, pa, overwrite)
548 stats = applyupdates(repo, action, wc, p2, pa, overwrite)
549
549
550 if not partial:
550 if not partial:
551 repo.dirstate.setparents(fp1, fp2)
551 repo.dirstate.setparents(fp1, fp2)
552 recordupdates(repo, action, branchmerge and not fastforward)
552 recordupdates(repo, action, branchmerge)
553 if not branchmerge and not fastforward:
553 if not branchmerge and not fastforward:
554 repo.dirstate.setbranch(p2.branch())
554 repo.dirstate.setbranch(p2.branch())
555 finally:
555 finally:
556 wlock.release()
556 wlock.release()
557
557
558 if not partial:
558 if not partial:
559 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
559 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
560 return stats
560 return stats
@@ -1,34 +1,29
1 http://mercurial.selenic.com/bts/issue619
1 http://mercurial.selenic.com/bts/issue619
2
2
3 $ hg init
3 $ hg init
4 $ echo a > a
4 $ echo a > a
5 $ hg ci -Ama
5 $ hg ci -Ama
6 adding a
6 adding a
7
7
8 $ echo b > b
8 $ echo b > b
9 $ hg branch b
9 $ hg branch b
10 marked working directory as branch b
10 marked working directory as branch b
11 $ hg ci -Amb
11 $ hg ci -Amb
12 adding b
12 adding b
13
13
14 $ hg co -C 0
14 $ hg co -C 0
15 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
15 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
16
16
17 Fast-forward:
17 Fast-forward:
18
18
19 $ hg merge b
19 $ hg merge b
20 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
20 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
21 (branch merge, don't forget to commit)
21 (branch merge, don't forget to commit)
22 $ hg branch
23 default
24 $ hg parent --template '{rev}:{node|short} {branches}: {desc}\n'
25 1:06c2121185be b: b
26 $ hg ci -Ammerge
22 $ hg ci -Ammerge
27 created new head
28
23
29 Bogus fast-forward should fail:
24 Bogus fast-forward should fail:
30
25
31 $ hg merge b
26 $ hg merge b
32 abort: merging with a working directory ancestor has no effect
27 abort: merging with a working directory ancestor has no effect
33 [255]
28 [255]
34
29
@@ -1,320 +1,321
1 $ branchcache=.hg/cache/branchheads
1 $ branchcache=.hg/cache/branchheads
2
2
3 $ hg init t
3 $ hg init t
4 $ cd t
4 $ cd t
5
5
6 $ hg branches
6 $ hg branches
7 $ echo foo > a
7 $ echo foo > a
8 $ hg add a
8 $ hg add a
9 $ hg ci -m "initial"
9 $ hg ci -m "initial"
10 $ hg branch foo
10 $ hg branch foo
11 marked working directory as branch foo
11 marked working directory as branch foo
12 $ hg branch
12 $ hg branch
13 foo
13 foo
14 $ hg ci -m "add branch name"
14 $ hg ci -m "add branch name"
15 $ hg branch bar
15 $ hg branch bar
16 marked working directory as branch bar
16 marked working directory as branch bar
17 $ hg ci -m "change branch name"
17 $ hg ci -m "change branch name"
18
18
19 Branch shadowing:
19 Branch shadowing:
20
20
21 $ hg branch default
21 $ hg branch default
22 abort: a branch of the same name already exists (use 'hg update' to switch to it)
22 abort: a branch of the same name already exists (use 'hg update' to switch to it)
23 [255]
23 [255]
24
24
25 $ hg branch -f default
25 $ hg branch -f default
26 marked working directory as branch default
26 marked working directory as branch default
27
27
28 $ hg ci -m "clear branch name"
28 $ hg ci -m "clear branch name"
29 created new head
29 created new head
30
30
31 There should be only one default branch head
31 There should be only one default branch head
32
32
33 $ hg heads .
33 $ hg heads .
34 changeset: 3:9d567d0b51f9
34 changeset: 3:9d567d0b51f9
35 tag: tip
35 tag: tip
36 user: test
36 user: test
37 date: Thu Jan 01 00:00:00 1970 +0000
37 date: Thu Jan 01 00:00:00 1970 +0000
38 summary: clear branch name
38 summary: clear branch name
39
39
40
40
41 $ hg co foo
41 $ hg co foo
42 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
43 $ hg branch
43 $ hg branch
44 foo
44 foo
45 $ echo bleah > a
45 $ echo bleah > a
46 $ hg ci -m "modify a branch"
46 $ hg ci -m "modify a branch"
47
47
48 $ hg merge default
48 $ hg merge default
49 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
49 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
50 (branch merge, don't forget to commit)
50 (branch merge, don't forget to commit)
51
51
52 $ hg branch
52 $ hg branch
53 foo
53 foo
54 $ hg ci -m "merge"
54 $ hg ci -m "merge"
55
55
56 $ hg log
56 $ hg log
57 changeset: 5:dc140083783b
57 changeset: 5:dc140083783b
58 branch: foo
58 branch: foo
59 tag: tip
59 tag: tip
60 parent: 4:98d14f698afe
60 parent: 4:98d14f698afe
61 parent: 3:9d567d0b51f9
61 parent: 3:9d567d0b51f9
62 user: test
62 user: test
63 date: Thu Jan 01 00:00:00 1970 +0000
63 date: Thu Jan 01 00:00:00 1970 +0000
64 summary: merge
64 summary: merge
65
65
66 changeset: 4:98d14f698afe
66 changeset: 4:98d14f698afe
67 branch: foo
67 branch: foo
68 parent: 1:0079f24813e2
68 parent: 1:0079f24813e2
69 user: test
69 user: test
70 date: Thu Jan 01 00:00:00 1970 +0000
70 date: Thu Jan 01 00:00:00 1970 +0000
71 summary: modify a branch
71 summary: modify a branch
72
72
73 changeset: 3:9d567d0b51f9
73 changeset: 3:9d567d0b51f9
74 user: test
74 user: test
75 date: Thu Jan 01 00:00:00 1970 +0000
75 date: Thu Jan 01 00:00:00 1970 +0000
76 summary: clear branch name
76 summary: clear branch name
77
77
78 changeset: 2:ed2bbf4e0102
78 changeset: 2:ed2bbf4e0102
79 branch: bar
79 branch: bar
80 user: test
80 user: test
81 date: Thu Jan 01 00:00:00 1970 +0000
81 date: Thu Jan 01 00:00:00 1970 +0000
82 summary: change branch name
82 summary: change branch name
83
83
84 changeset: 1:0079f24813e2
84 changeset: 1:0079f24813e2
85 branch: foo
85 branch: foo
86 user: test
86 user: test
87 date: Thu Jan 01 00:00:00 1970 +0000
87 date: Thu Jan 01 00:00:00 1970 +0000
88 summary: add branch name
88 summary: add branch name
89
89
90 changeset: 0:db01e8ea3388
90 changeset: 0:db01e8ea3388
91 user: test
91 user: test
92 date: Thu Jan 01 00:00:00 1970 +0000
92 date: Thu Jan 01 00:00:00 1970 +0000
93 summary: initial
93 summary: initial
94
94
95 $ hg branches
95 $ hg branches
96 foo 5:dc140083783b
96 foo 5:dc140083783b
97 default 3:9d567d0b51f9 (inactive)
97 default 3:9d567d0b51f9 (inactive)
98 bar 2:ed2bbf4e0102 (inactive)
98 bar 2:ed2bbf4e0102 (inactive)
99
99
100 $ hg branches -q
100 $ hg branches -q
101 foo
101 foo
102 default
102 default
103 bar
103 bar
104
104
105 Test for invalid branch cache:
105 Test for invalid branch cache:
106
106
107 $ hg rollback
107 $ hg rollback
108 repository tip rolled back to revision 4 (undo commit)
108 repository tip rolled back to revision 4 (undo commit)
109 working directory now based on revisions 4 and 3
109 working directory now based on revisions 4 and 3
110
110
111 $ cp $branchcache .hg/bc-invalid
111 $ cp $branchcache .hg/bc-invalid
112
112
113 $ hg log -r foo
113 $ hg log -r foo
114 changeset: 4:98d14f698afe
114 changeset: 4:98d14f698afe
115 branch: foo
115 branch: foo
116 tag: tip
116 tag: tip
117 parent: 1:0079f24813e2
117 parent: 1:0079f24813e2
118 user: test
118 user: test
119 date: Thu Jan 01 00:00:00 1970 +0000
119 date: Thu Jan 01 00:00:00 1970 +0000
120 summary: modify a branch
120 summary: modify a branch
121
121
122 $ cp .hg/bc-invalid $branchcache
122 $ cp .hg/bc-invalid $branchcache
123
123
124 $ hg --debug log -r foo
124 $ hg --debug log -r foo
125 invalidating branch cache (tip differs)
125 invalidating branch cache (tip differs)
126 changeset: 4:98d14f698afeaff8cb612dcf215ce95e639effc3
126 changeset: 4:98d14f698afeaff8cb612dcf215ce95e639effc3
127 branch: foo
127 branch: foo
128 tag: tip
128 tag: tip
129 parent: 1:0079f24813e2b73a891577c243684c5066347bc8
129 parent: 1:0079f24813e2b73a891577c243684c5066347bc8
130 parent: -1:0000000000000000000000000000000000000000
130 parent: -1:0000000000000000000000000000000000000000
131 manifest: 4:d01b250baaa05909152f7ae07d7a649deea0df9a
131 manifest: 4:d01b250baaa05909152f7ae07d7a649deea0df9a
132 user: test
132 user: test
133 date: Thu Jan 01 00:00:00 1970 +0000
133 date: Thu Jan 01 00:00:00 1970 +0000
134 files: a
134 files: a
135 extra: branch=foo
135 extra: branch=foo
136 description:
136 description:
137 modify a branch
137 modify a branch
138
138
139
139
140 $ rm $branchcache
140 $ rm $branchcache
141 $ echo corrupted > $branchcache
141 $ echo corrupted > $branchcache
142
142
143 $ hg log -qr foo
143 $ hg log -qr foo
144 4:98d14f698afe
144 4:98d14f698afe
145
145
146 $ cat $branchcache
146 $ cat $branchcache
147 98d14f698afeaff8cb612dcf215ce95e639effc3 4
147 98d14f698afeaff8cb612dcf215ce95e639effc3 4
148 9d567d0b51f9e2068b054e1948e1a927f99b5874 default
148 9d567d0b51f9e2068b054e1948e1a927f99b5874 default
149 98d14f698afeaff8cb612dcf215ce95e639effc3 foo
149 98d14f698afeaff8cb612dcf215ce95e639effc3 foo
150 ed2bbf4e01029020711be82ca905283e883f0e11 bar
150 ed2bbf4e01029020711be82ca905283e883f0e11 bar
151
151
152 Push should update the branch cache:
152 Push should update the branch cache:
153
153
154 $ hg init ../target
154 $ hg init ../target
155
155
156 Pushing just rev 0:
156 Pushing just rev 0:
157
157
158 $ hg push -qr 0 ../target
158 $ hg push -qr 0 ../target
159
159
160 $ cat ../target/$branchcache
160 $ cat ../target/$branchcache
161 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 0
161 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 0
162 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 default
162 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 default
163
163
164 Pushing everything:
164 Pushing everything:
165
165
166 $ hg push -qf ../target
166 $ hg push -qf ../target
167
167
168 $ cat ../target/$branchcache
168 $ cat ../target/$branchcache
169 98d14f698afeaff8cb612dcf215ce95e639effc3 4
169 98d14f698afeaff8cb612dcf215ce95e639effc3 4
170 9d567d0b51f9e2068b054e1948e1a927f99b5874 default
170 9d567d0b51f9e2068b054e1948e1a927f99b5874 default
171 98d14f698afeaff8cb612dcf215ce95e639effc3 foo
171 98d14f698afeaff8cb612dcf215ce95e639effc3 foo
172 ed2bbf4e01029020711be82ca905283e883f0e11 bar
172 ed2bbf4e01029020711be82ca905283e883f0e11 bar
173
173
174 Update with no arguments: tipmost revision of the current branch:
174 Update with no arguments: tipmost revision of the current branch:
175
175
176 $ hg up -q -C 0
176 $ hg up -q -C 0
177 $ hg up -q
177 $ hg up -q
178 $ hg id
178 $ hg id
179 9d567d0b51f9
179 9d567d0b51f9
180
180
181 $ hg up -q 1
181 $ hg up -q 1
182 $ hg up -q
182 $ hg up -q
183 $ hg id
183 $ hg id
184 98d14f698afe (foo) tip
184 98d14f698afe (foo) tip
185
185
186 $ hg branch foobar
186 $ hg branch foobar
187 marked working directory as branch foobar
187 marked working directory as branch foobar
188
188
189 $ hg up
189 $ hg up
190 abort: branch foobar not found
190 abort: branch foobar not found
191 [255]
191 [255]
192
192
193 Fastforward merge:
193 Fastforward merge:
194
194
195 $ hg branch ff
195 $ hg branch ff
196 marked working directory as branch ff
196 marked working directory as branch ff
197
197
198 $ echo ff > ff
198 $ echo ff > ff
199 $ hg ci -Am'fast forward'
199 $ hg ci -Am'fast forward'
200 adding ff
200 adding ff
201
201
202 $ hg up foo
202 $ hg up foo
203 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
203 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
204
204
205 $ hg merge ff
205 $ hg merge ff
206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
207 (branch merge, don't forget to commit)
207 (branch merge, don't forget to commit)
208
208
209 $ hg branch
209 $ hg branch
210 foo
210 foo
211 $ hg commit -m'Merge ff into foo'
211 $ hg commit -m'Merge ff into foo'
212 created new head
213 $ hg parents
212 $ hg parents
214 changeset: 6:6af8030670c9
213 changeset: 6:917eb54e1b4b
215 branch: foo
214 branch: foo
216 tag: tip
215 tag: tip
216 parent: 4:98d14f698afe
217 parent: 5:6683a60370cb
217 user: test
218 user: test
218 date: Thu Jan 01 00:00:00 1970 +0000
219 date: Thu Jan 01 00:00:00 1970 +0000
219 summary: Merge ff into foo
220 summary: Merge ff into foo
220
221
221 $ hg manifest
222 $ hg manifest
222 a
223 a
223 ff
224 ff
224
225
225
226
226 Test merging, add 3 default heads and one test head:
227 Test merging, add 3 default heads and one test head:
227
228
228 $ cd ..
229 $ cd ..
229 $ hg init merges
230 $ hg init merges
230 $ cd merges
231 $ cd merges
231 $ echo a > a
232 $ echo a > a
232 $ hg ci -Ama
233 $ hg ci -Ama
233 adding a
234 adding a
234
235
235 $ echo b > b
236 $ echo b > b
236 $ hg ci -Amb
237 $ hg ci -Amb
237 adding b
238 adding b
238
239
239 $ hg up 0
240 $ hg up 0
240 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
241 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
241 $ echo c > c
242 $ echo c > c
242 $ hg ci -Amc
243 $ hg ci -Amc
243 adding c
244 adding c
244 created new head
245 created new head
245
246
246 $ hg up 0
247 $ hg up 0
247 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
248 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
248 $ echo d > d
249 $ echo d > d
249 $ hg ci -Amd
250 $ hg ci -Amd
250 adding d
251 adding d
251 created new head
252 created new head
252
253
253 $ hg up 0
254 $ hg up 0
254 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
255 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
255 $ hg branch test
256 $ hg branch test
256 marked working directory as branch test
257 marked working directory as branch test
257 $ echo e >> e
258 $ echo e >> e
258 $ hg ci -Ame
259 $ hg ci -Ame
259 adding e
260 adding e
260
261
261 $ hg log
262 $ hg log
262 changeset: 4:3a1e01ed1df4
263 changeset: 4:3a1e01ed1df4
263 branch: test
264 branch: test
264 tag: tip
265 tag: tip
265 parent: 0:cb9a9f314b8b
266 parent: 0:cb9a9f314b8b
266 user: test
267 user: test
267 date: Thu Jan 01 00:00:00 1970 +0000
268 date: Thu Jan 01 00:00:00 1970 +0000
268 summary: e
269 summary: e
269
270
270 changeset: 3:980f7dc84c29
271 changeset: 3:980f7dc84c29
271 parent: 0:cb9a9f314b8b
272 parent: 0:cb9a9f314b8b
272 user: test
273 user: test
273 date: Thu Jan 01 00:00:00 1970 +0000
274 date: Thu Jan 01 00:00:00 1970 +0000
274 summary: d
275 summary: d
275
276
276 changeset: 2:d36c0562f908
277 changeset: 2:d36c0562f908
277 parent: 0:cb9a9f314b8b
278 parent: 0:cb9a9f314b8b
278 user: test
279 user: test
279 date: Thu Jan 01 00:00:00 1970 +0000
280 date: Thu Jan 01 00:00:00 1970 +0000
280 summary: c
281 summary: c
281
282
282 changeset: 1:d2ae7f538514
283 changeset: 1:d2ae7f538514
283 user: test
284 user: test
284 date: Thu Jan 01 00:00:00 1970 +0000
285 date: Thu Jan 01 00:00:00 1970 +0000
285 summary: b
286 summary: b
286
287
287 changeset: 0:cb9a9f314b8b
288 changeset: 0:cb9a9f314b8b
288 user: test
289 user: test
289 date: Thu Jan 01 00:00:00 1970 +0000
290 date: Thu Jan 01 00:00:00 1970 +0000
290 summary: a
291 summary: a
291
292
292 Implicit merge with test branch as parent:
293 Implicit merge with test branch as parent:
293
294
294 $ hg merge
295 $ hg merge
295 abort: branch 'test' has one head - please merge with an explicit rev
296 abort: branch 'test' has one head - please merge with an explicit rev
296 (run 'hg heads' to see all heads)
297 (run 'hg heads' to see all heads)
297 [255]
298 [255]
298 $ hg up -C default
299 $ hg up -C default
299 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
300 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
300
301
301 Implicit merge with default branch as parent:
302 Implicit merge with default branch as parent:
302
303
303 $ hg merge
304 $ hg merge
304 abort: branch 'default' has 3 heads - please merge with an explicit rev
305 abort: branch 'default' has 3 heads - please merge with an explicit rev
305 (run 'hg heads .' to see heads)
306 (run 'hg heads .' to see heads)
306 [255]
307 [255]
307
308
308 3 branch heads, explicit merge required:
309 3 branch heads, explicit merge required:
309
310
310 $ hg merge 2
311 $ hg merge 2
311 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
312 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
312 (branch merge, don't forget to commit)
313 (branch merge, don't forget to commit)
313 $ hg ci -m merge
314 $ hg ci -m merge
314
315
315 2 branch heads, implicit merge works:
316 2 branch heads, implicit merge works:
316
317
317 $ hg merge
318 $ hg merge
318 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
319 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
319 (branch merge, don't forget to commit)
320 (branch merge, don't forget to commit)
320
321
@@ -1,719 +1,718
1 $ echo "[extensions]" >> $HGRCPATH
1 $ echo "[extensions]" >> $HGRCPATH
2 $ echo "graphlog=" >> $HGRCPATH
2 $ echo "graphlog=" >> $HGRCPATH
3
3
4 $ mkdir a
4 $ mkdir a
5 $ cd a
5 $ cd a
6 $ hg init
6 $ hg init
7 $ echo foo > t1
7 $ echo foo > t1
8 $ hg add t1
8 $ hg add t1
9 $ hg commit -m "1"
9 $ hg commit -m "1"
10
10
11 $ cd ..
11 $ cd ..
12 $ hg clone a b
12 $ hg clone a b
13 updating to branch default
13 updating to branch default
14 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
14 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
15
15
16 $ cd a
16 $ cd a
17 $ echo foo > t2
17 $ echo foo > t2
18 $ hg add t2
18 $ hg add t2
19 $ hg commit -m "2"
19 $ hg commit -m "2"
20
20
21 $ cd ../b
21 $ cd ../b
22 $ echo foo > t3
22 $ echo foo > t3
23 $ hg add t3
23 $ hg add t3
24 $ hg commit -m "3"
24 $ hg commit -m "3"
25
25
26 $ hg push ../a
26 $ hg push ../a
27 pushing to ../a
27 pushing to ../a
28 searching for changes
28 searching for changes
29 abort: push creates new remote heads on branch 'default'!
29 abort: push creates new remote heads on branch 'default'!
30 (you should pull and merge or use push -f to force)
30 (you should pull and merge or use push -f to force)
31 [255]
31 [255]
32
32
33 $ hg push --debug ../a
33 $ hg push --debug ../a
34 pushing to ../a
34 pushing to ../a
35 searching for changes
35 searching for changes
36 examining 1c9246a22a0a:d8d565842d04
36 examining 1c9246a22a0a:d8d565842d04
37 found incomplete branch 1c9246a22a0a:d8d565842d04
37 found incomplete branch 1c9246a22a0a:d8d565842d04
38 searching: 1 queries
38 searching: 1 queries
39 narrowing 1:1 d8d565842d04
39 narrowing 1:1 d8d565842d04
40 found new branch changeset 1c9246a22a0a
40 found new branch changeset 1c9246a22a0a
41 found new changesets starting at 1c9246a22a0a
41 found new changesets starting at 1c9246a22a0a
42 1 total queries
42 1 total queries
43 common changesets up to d8d565842d04
43 common changesets up to d8d565842d04
44 new remote heads on branch 'default'
44 new remote heads on branch 'default'
45 new remote head 1e108cc5548c
45 new remote head 1e108cc5548c
46 abort: push creates new remote heads on branch 'default'!
46 abort: push creates new remote heads on branch 'default'!
47 (you should pull and merge or use push -f to force)
47 (you should pull and merge or use push -f to force)
48 [255]
48 [255]
49
49
50 $ hg pull ../a
50 $ hg pull ../a
51 pulling from ../a
51 pulling from ../a
52 searching for changes
52 searching for changes
53 adding changesets
53 adding changesets
54 adding manifests
54 adding manifests
55 adding file changes
55 adding file changes
56 added 1 changesets with 1 changes to 1 files (+1 heads)
56 added 1 changesets with 1 changes to 1 files (+1 heads)
57 (run 'hg heads' to see heads, 'hg merge' to merge)
57 (run 'hg heads' to see heads, 'hg merge' to merge)
58
58
59 $ hg push ../a
59 $ hg push ../a
60 pushing to ../a
60 pushing to ../a
61 searching for changes
61 searching for changes
62 abort: push creates new remote heads on branch 'default'!
62 abort: push creates new remote heads on branch 'default'!
63 (did you forget to merge? use push -f to force)
63 (did you forget to merge? use push -f to force)
64 [255]
64 [255]
65
65
66 $ hg merge
66 $ hg merge
67 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
68 (branch merge, don't forget to commit)
68 (branch merge, don't forget to commit)
69
69
70 $ hg commit -m "4"
70 $ hg commit -m "4"
71 $ hg push ../a
71 $ hg push ../a
72 pushing to ../a
72 pushing to ../a
73 searching for changes
73 searching for changes
74 adding changesets
74 adding changesets
75 adding manifests
75 adding manifests
76 adding file changes
76 adding file changes
77 added 2 changesets with 1 changes to 1 files
77 added 2 changesets with 1 changes to 1 files
78
78
79 $ cd ..
79 $ cd ..
80
80
81 $ hg init c
81 $ hg init c
82 $ cd c
82 $ cd c
83 $ for i in 0 1 2; do
83 $ for i in 0 1 2; do
84 > echo $i >> foo
84 > echo $i >> foo
85 > hg ci -Am $i
85 > hg ci -Am $i
86 > done
86 > done
87 adding foo
87 adding foo
88 $ cd ..
88 $ cd ..
89
89
90 $ hg clone c d
90 $ hg clone c d
91 updating to branch default
91 updating to branch default
92 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
92 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
93
93
94 $ cd d
94 $ cd d
95 $ for i in 0 1; do
95 $ for i in 0 1; do
96 > hg co -C $i
96 > hg co -C $i
97 > echo d-$i >> foo
97 > echo d-$i >> foo
98 > hg ci -m d-$i
98 > hg ci -m d-$i
99 > done
99 > done
100 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
100 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
101 created new head
101 created new head
102 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
102 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
103 created new head
103 created new head
104
104
105 $ HGMERGE=true hg merge 3
105 $ HGMERGE=true hg merge 3
106 merging foo
106 merging foo
107 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
107 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
108 (branch merge, don't forget to commit)
108 (branch merge, don't forget to commit)
109
109
110 $ hg ci -m c-d
110 $ hg ci -m c-d
111
111
112 $ hg push ../c
112 $ hg push ../c
113 pushing to ../c
113 pushing to ../c
114 searching for changes
114 searching for changes
115 abort: push creates new remote heads on branch 'default'!
115 abort: push creates new remote heads on branch 'default'!
116 (did you forget to merge? use push -f to force)
116 (did you forget to merge? use push -f to force)
117 [255]
117 [255]
118
118
119 $ hg push -r 2 ../c
119 $ hg push -r 2 ../c
120 pushing to ../c
120 pushing to ../c
121 searching for changes
121 searching for changes
122 no changes found
122 no changes found
123
123
124 $ hg push -r 3 ../c
124 $ hg push -r 3 ../c
125 pushing to ../c
125 pushing to ../c
126 searching for changes
126 searching for changes
127 abort: push creates new remote heads on branch 'default'!
127 abort: push creates new remote heads on branch 'default'!
128 (did you forget to merge? use push -f to force)
128 (did you forget to merge? use push -f to force)
129 [255]
129 [255]
130
130
131 $ hg push -r 3 -r 4 ../c
131 $ hg push -r 3 -r 4 ../c
132 pushing to ../c
132 pushing to ../c
133 searching for changes
133 searching for changes
134 abort: push creates new remote heads on branch 'default'!
134 abort: push creates new remote heads on branch 'default'!
135 (did you forget to merge? use push -f to force)
135 (did you forget to merge? use push -f to force)
136 [255]
136 [255]
137
137
138 $ hg push -f -r 3 -r 4 ../c
138 $ hg push -f -r 3 -r 4 ../c
139 pushing to ../c
139 pushing to ../c
140 searching for changes
140 searching for changes
141 adding changesets
141 adding changesets
142 adding manifests
142 adding manifests
143 adding file changes
143 adding file changes
144 added 2 changesets with 2 changes to 1 files (+2 heads)
144 added 2 changesets with 2 changes to 1 files (+2 heads)
145
145
146 $ hg push -r 5 ../c
146 $ hg push -r 5 ../c
147 pushing to ../c
147 pushing to ../c
148 searching for changes
148 searching for changes
149 adding changesets
149 adding changesets
150 adding manifests
150 adding manifests
151 adding file changes
151 adding file changes
152 added 1 changesets with 1 changes to 1 files (-1 heads)
152 added 1 changesets with 1 changes to 1 files (-1 heads)
153
153
154 $ hg in ../c
154 $ hg in ../c
155 comparing with ../c
155 comparing with ../c
156 searching for changes
156 searching for changes
157 no changes found
157 no changes found
158 [1]
158 [1]
159
159
160
160
161 Issue450: push -r warns about remote head creation even if no heads
161 Issue450: push -r warns about remote head creation even if no heads
162 will be created
162 will be created
163
163
164 $ hg init ../e
164 $ hg init ../e
165 $ hg push -r 0 ../e
165 $ hg push -r 0 ../e
166 pushing to ../e
166 pushing to ../e
167 searching for changes
167 searching for changes
168 adding changesets
168 adding changesets
169 adding manifests
169 adding manifests
170 adding file changes
170 adding file changes
171 added 1 changesets with 1 changes to 1 files
171 added 1 changesets with 1 changes to 1 files
172
172
173 $ hg push -r 1 ../e
173 $ hg push -r 1 ../e
174 pushing to ../e
174 pushing to ../e
175 searching for changes
175 searching for changes
176 adding changesets
176 adding changesets
177 adding manifests
177 adding manifests
178 adding file changes
178 adding file changes
179 added 1 changesets with 1 changes to 1 files
179 added 1 changesets with 1 changes to 1 files
180
180
181 $ cd ..
181 $ cd ..
182
182
183
183
184 Issue736: named branches are not considered for detection of
184 Issue736: named branches are not considered for detection of
185 unmerged heads in "hg push"
185 unmerged heads in "hg push"
186
186
187 $ hg init f
187 $ hg init f
188 $ cd f
188 $ cd f
189 $ hg -q branch a
189 $ hg -q branch a
190 $ echo 0 > foo
190 $ echo 0 > foo
191 $ hg -q ci -Am 0
191 $ hg -q ci -Am 0
192 $ echo 1 > foo
192 $ echo 1 > foo
193 $ hg -q ci -m 1
193 $ hg -q ci -m 1
194 $ hg -q up 0
194 $ hg -q up 0
195 $ echo 2 > foo
195 $ echo 2 > foo
196 $ hg -q ci -m 2
196 $ hg -q ci -m 2
197 $ hg -q up 0
197 $ hg -q up 0
198 $ hg -q branch b
198 $ hg -q branch b
199 $ echo 3 > foo
199 $ echo 3 > foo
200 $ hg -q ci -m 3
200 $ hg -q ci -m 3
201 $ cd ..
201 $ cd ..
202
202
203 $ hg -q clone f g
203 $ hg -q clone f g
204 $ cd g
204 $ cd g
205
205
206 Push on existing branch and new branch:
206 Push on existing branch and new branch:
207
207
208 $ hg -q up 1
208 $ hg -q up 1
209 $ echo 4 > foo
209 $ echo 4 > foo
210 $ hg -q ci -m 4
210 $ hg -q ci -m 4
211 $ hg -q up 0
211 $ hg -q up 0
212 $ echo 5 > foo
212 $ echo 5 > foo
213 $ hg -q branch c
213 $ hg -q branch c
214 $ hg -q ci -m 5
214 $ hg -q ci -m 5
215
215
216 $ hg push ../f
216 $ hg push ../f
217 pushing to ../f
217 pushing to ../f
218 searching for changes
218 searching for changes
219 abort: push creates new remote branches: c!
219 abort: push creates new remote branches: c!
220 (use 'hg push --new-branch' to create new remote branches)
220 (use 'hg push --new-branch' to create new remote branches)
221 [255]
221 [255]
222
222
223 $ hg push -r 4 -r 5 ../f
223 $ hg push -r 4 -r 5 ../f
224 pushing to ../f
224 pushing to ../f
225 searching for changes
225 searching for changes
226 abort: push creates new remote branches: c!
226 abort: push creates new remote branches: c!
227 (use 'hg push --new-branch' to create new remote branches)
227 (use 'hg push --new-branch' to create new remote branches)
228 [255]
228 [255]
229
229
230
230
231 Multiple new branches:
231 Multiple new branches:
232
232
233 $ hg -q branch d
233 $ hg -q branch d
234 $ echo 6 > foo
234 $ echo 6 > foo
235 $ hg -q ci -m 6
235 $ hg -q ci -m 6
236
236
237 $ hg push ../f
237 $ hg push ../f
238 pushing to ../f
238 pushing to ../f
239 searching for changes
239 searching for changes
240 abort: push creates new remote branches: c, d!
240 abort: push creates new remote branches: c, d!
241 (use 'hg push --new-branch' to create new remote branches)
241 (use 'hg push --new-branch' to create new remote branches)
242 [255]
242 [255]
243
243
244 $ hg push -r 4 -r 6 ../f
244 $ hg push -r 4 -r 6 ../f
245 pushing to ../f
245 pushing to ../f
246 searching for changes
246 searching for changes
247 abort: push creates new remote branches: c, d!
247 abort: push creates new remote branches: c, d!
248 (use 'hg push --new-branch' to create new remote branches)
248 (use 'hg push --new-branch' to create new remote branches)
249 [255]
249 [255]
250
250
251 $ cd ../g
251 $ cd ../g
252
252
253
253
254 Fail on multiple head push:
254 Fail on multiple head push:
255
255
256 $ hg -q up 1
256 $ hg -q up 1
257 $ echo 7 > foo
257 $ echo 7 > foo
258 $ hg -q ci -m 7
258 $ hg -q ci -m 7
259
259
260 $ hg push -r 4 -r 7 ../f
260 $ hg push -r 4 -r 7 ../f
261 pushing to ../f
261 pushing to ../f
262 searching for changes
262 searching for changes
263 abort: push creates new remote heads on branch 'a'!
263 abort: push creates new remote heads on branch 'a'!
264 (did you forget to merge? use push -f to force)
264 (did you forget to merge? use push -f to force)
265 [255]
265 [255]
266
266
267 Push replacement head on existing branches:
267 Push replacement head on existing branches:
268
268
269 $ hg -q up 3
269 $ hg -q up 3
270 $ echo 8 > foo
270 $ echo 8 > foo
271 $ hg -q ci -m 8
271 $ hg -q ci -m 8
272
272
273 $ hg push -r 7 -r 8 ../f
273 $ hg push -r 7 -r 8 ../f
274 pushing to ../f
274 pushing to ../f
275 searching for changes
275 searching for changes
276 adding changesets
276 adding changesets
277 adding manifests
277 adding manifests
278 adding file changes
278 adding file changes
279 added 2 changesets with 2 changes to 1 files
279 added 2 changesets with 2 changes to 1 files
280
280
281
281
282 Merge of branch a to other branch b followed by unrelated push
282 Merge of branch a to other branch b followed by unrelated push
283 on branch a:
283 on branch a:
284
284
285 $ hg -q up 7
285 $ hg -q up 7
286 $ HGMERGE=true hg -q merge 8
286 $ HGMERGE=true hg -q merge 8
287 $ hg -q ci -m 9
287 $ hg -q ci -m 9
288 $ hg -q up 8
288 $ hg -q up 8
289 $ echo 10 > foo
289 $ echo 10 > foo
290 $ hg -q ci -m 10
290 $ hg -q ci -m 10
291
291
292 $ hg push -r 9 ../f
292 $ hg push -r 9 ../f
293 pushing to ../f
293 pushing to ../f
294 searching for changes
294 searching for changes
295 adding changesets
295 adding changesets
296 adding manifests
296 adding manifests
297 adding file changes
297 adding file changes
298 added 1 changesets with 1 changes to 1 files (-1 heads)
298 added 1 changesets with 1 changes to 1 files (-1 heads)
299
299
300 $ hg push -r 10 ../f
300 $ hg push -r 10 ../f
301 pushing to ../f
301 pushing to ../f
302 searching for changes
302 searching for changes
303 adding changesets
303 adding changesets
304 adding manifests
304 adding manifests
305 adding file changes
305 adding file changes
306 added 1 changesets with 1 changes to 1 files (+1 heads)
306 added 1 changesets with 1 changes to 1 files (+1 heads)
307
307
308
308
309 Cheating the counting algorithm:
309 Cheating the counting algorithm:
310
310
311 $ hg -q up 9
311 $ hg -q up 9
312 $ HGMERGE=true hg -q merge 2
312 $ HGMERGE=true hg -q merge 2
313 $ hg -q ci -m 11
313 $ hg -q ci -m 11
314 $ hg -q up 1
314 $ hg -q up 1
315 $ echo 12 > foo
315 $ echo 12 > foo
316 $ hg -q ci -m 12
316 $ hg -q ci -m 12
317
317
318 $ hg push -r 11 -r 12 ../f
318 $ hg push -r 11 -r 12 ../f
319 pushing to ../f
319 pushing to ../f
320 searching for changes
320 searching for changes
321 adding changesets
321 adding changesets
322 adding manifests
322 adding manifests
323 adding file changes
323 adding file changes
324 added 2 changesets with 2 changes to 1 files
324 added 2 changesets with 2 changes to 1 files
325
325
326
326
327 Failed push of new named branch:
327 Failed push of new named branch:
328
328
329 $ echo 12 > foo
329 $ echo 12 > foo
330 $ hg -q ci -m 12a
330 $ hg -q ci -m 12a
331 [1]
331 [1]
332 $ hg -q up 11
332 $ hg -q up 11
333 $ echo 13 > foo
333 $ echo 13 > foo
334 $ hg -q branch e
334 $ hg -q branch e
335 $ hg -q ci -m 13d
335 $ hg -q ci -m 13d
336
336
337 $ hg push -r 12 -r 13 ../f
337 $ hg push -r 12 -r 13 ../f
338 pushing to ../f
338 pushing to ../f
339 searching for changes
339 searching for changes
340 abort: push creates new remote branches: e!
340 abort: push creates new remote branches: e!
341 (use 'hg push --new-branch' to create new remote branches)
341 (use 'hg push --new-branch' to create new remote branches)
342 [255]
342 [255]
343
343
344
344
345 Using --new-branch to push new named branch:
345 Using --new-branch to push new named branch:
346
346
347 $ hg push --new-branch -r 12 -r 13 ../f
347 $ hg push --new-branch -r 12 -r 13 ../f
348 pushing to ../f
348 pushing to ../f
349 searching for changes
349 searching for changes
350 adding changesets
350 adding changesets
351 adding manifests
351 adding manifests
352 adding file changes
352 adding file changes
353 added 1 changesets with 1 changes to 1 files
353 added 1 changesets with 1 changes to 1 files
354
354
355
355
356 Checking prepush logic does not allow silently pushing
356 Checking prepush logic does not allow silently pushing
357 multiple new heads:
357 multiple new heads:
358
358
359 $ cd ..
359 $ cd ..
360 $ hg init h
360 $ hg init h
361 $ echo init > h/init
361 $ echo init > h/init
362 $ hg -R h ci -Am init
362 $ hg -R h ci -Am init
363 adding init
363 adding init
364 $ echo a > h/a
364 $ echo a > h/a
365 $ hg -R h ci -Am a
365 $ hg -R h ci -Am a
366 adding a
366 adding a
367 $ hg clone h i
367 $ hg clone h i
368 updating to branch default
368 updating to branch default
369 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
369 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
370 $ hg -R h up 0
370 $ hg -R h up 0
371 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
371 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
372 $ echo b > h/b
372 $ echo b > h/b
373 $ hg -R h ci -Am b
373 $ hg -R h ci -Am b
374 adding b
374 adding b
375 created new head
375 created new head
376 $ hg -R i up 0
376 $ hg -R i up 0
377 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
377 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
378 $ echo c > i/c
378 $ echo c > i/c
379 $ hg -R i ci -Am c
379 $ hg -R i ci -Am c
380 adding c
380 adding c
381 created new head
381 created new head
382
382
383 $ hg -R i push h
383 $ hg -R i push h
384 pushing to h
384 pushing to h
385 searching for changes
385 searching for changes
386 abort: push creates new remote heads on branch 'default'!
386 abort: push creates new remote heads on branch 'default'!
387 (you should pull and merge or use push -f to force)
387 (you should pull and merge or use push -f to force)
388 [255]
388 [255]
389
389
390
390
391 Check prepush logic with merged branches:
391 Check prepush logic with merged branches:
392
392
393 $ hg init j
393 $ hg init j
394 $ hg -R j branch a
394 $ hg -R j branch a
395 marked working directory as branch a
395 marked working directory as branch a
396 $ echo init > j/foo
396 $ echo init > j/foo
397 $ hg -R j ci -Am init
397 $ hg -R j ci -Am init
398 adding foo
398 adding foo
399 $ hg clone j k
399 $ hg clone j k
400 updating to branch a
400 updating to branch a
401 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
401 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
402 $ echo a1 > j/foo
402 $ echo a1 > j/foo
403 $ hg -R j ci -m a1
403 $ hg -R j ci -m a1
404 $ hg -R k branch b
404 $ hg -R k branch b
405 marked working directory as branch b
405 marked working directory as branch b
406 $ echo b > k/foo
406 $ echo b > k/foo
407 $ hg -R k ci -m b
407 $ hg -R k ci -m b
408 $ hg -R k up 0
408 $ hg -R k up 0
409 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
409 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
410
410
411 $ hg -R k merge b
411 $ hg -R k merge b
412 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
412 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
413 (branch merge, don't forget to commit)
413 (branch merge, don't forget to commit)
414
414
415 $ hg -R k ci -m merge
415 $ hg -R k ci -m merge
416 created new head
417
416
418 $ hg -R k push -r a j
417 $ hg -R k push -r a j
419 pushing to j
418 pushing to j
420 searching for changes
419 searching for changes
421 abort: push creates new remote branches: b!
420 abort: push creates new remote branches: b!
422 (use 'hg push --new-branch' to create new remote branches)
421 (use 'hg push --new-branch' to create new remote branches)
423 [255]
422 [255]
424
423
425
424
426 Prepush -r should not allow you to sneak in new heads:
425 Prepush -r should not allow you to sneak in new heads:
427
426
428 $ hg init l
427 $ hg init l
429 $ cd l
428 $ cd l
430 $ echo a >> foo
429 $ echo a >> foo
431 $ hg -q add foo
430 $ hg -q add foo
432 $ hg -q branch a
431 $ hg -q branch a
433 $ hg -q ci -ma
432 $ hg -q ci -ma
434 $ hg -q up null
433 $ hg -q up null
435 $ echo a >> foo
434 $ echo a >> foo
436 $ hg -q add foo
435 $ hg -q add foo
437 $ hg -q branch b
436 $ hg -q branch b
438 $ hg -q ci -mb
437 $ hg -q ci -mb
439 $ cd ..
438 $ cd ..
440 $ hg -q clone l m -u a
439 $ hg -q clone l m -u a
441 $ cd m
440 $ cd m
442 $ hg -q merge b
441 $ hg -q merge b
443 $ hg -q ci -mmb
442 $ hg -q ci -mmb
444 $ hg -q up 0
443 $ hg -q up 0
445 $ echo a >> foo
444 $ echo a >> foo
446 $ hg -q ci -ma2
445 $ hg -q ci -ma2
447 $ hg -q up 2
446 $ hg -q up 2
448 $ echo a >> foo
447 $ echo a >> foo
449 $ hg -q branch -f b
448 $ hg -q branch -f b
450 $ hg -q ci -mb2
449 $ hg -q ci -mb2
451 $ hg -q merge 3
450 $ hg -q merge 3
452 $ hg -q ci -mma
451 $ hg -q ci -mma
453
452
454 $ hg push ../l -b b
453 $ hg push ../l -b b
455 pushing to ../l
454 pushing to ../l
456 searching for changes
455 searching for changes
457 abort: push creates new remote heads on branch 'a'!
456 abort: push creates new remote heads on branch 'a'!
458 (did you forget to merge? use push -f to force)
457 (did you forget to merge? use push -f to force)
459 [255]
458 [255]
460
459
461 $ cd ..
460 $ cd ..
462
461
463
462
464 Check prepush with new branch head on former topo non-head:
463 Check prepush with new branch head on former topo non-head:
465
464
466 $ hg init n
465 $ hg init n
467 $ cd n
466 $ cd n
468 $ hg branch A
467 $ hg branch A
469 marked working directory as branch A
468 marked working directory as branch A
470 $ echo a >a
469 $ echo a >a
471 $ hg ci -Ama
470 $ hg ci -Ama
472 adding a
471 adding a
473 $ hg branch B
472 $ hg branch B
474 marked working directory as branch B
473 marked working directory as branch B
475 $ echo b >b
474 $ echo b >b
476 $ hg ci -Amb
475 $ hg ci -Amb
477 adding b
476 adding b
478
477
479 b is now branch head of B, and a topological head
478 b is now branch head of B, and a topological head
480 a is now branch head of A, but not a topological head
479 a is now branch head of A, but not a topological head
481
480
482 $ hg clone . inner
481 $ hg clone . inner
483 updating to branch B
482 updating to branch B
484 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
483 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
485 $ cd inner
484 $ cd inner
486 $ hg up B
485 $ hg up B
487 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
486 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
488 $ echo b1 >b1
487 $ echo b1 >b1
489 $ hg ci -Amb1
488 $ hg ci -Amb1
490 adding b1
489 adding b1
491
490
492 in the clone b1 is now the head of B
491 in the clone b1 is now the head of B
493
492
494 $ cd ..
493 $ cd ..
495 $ hg up 0
494 $ hg up 0
496 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
495 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
497 $ echo a2 >a2
496 $ echo a2 >a2
498 $ hg ci -Ama2
497 $ hg ci -Ama2
499 adding a2
498 adding a2
500
499
501 a2 is now the new branch head of A, and a new topological head
500 a2 is now the new branch head of A, and a new topological head
502 it replaces a former inner branch head, so it should at most warn about
501 it replaces a former inner branch head, so it should at most warn about
503 A, not B
502 A, not B
504
503
505 glog of local:
504 glog of local:
506
505
507 $ hg glog --template "{rev}: {branches} {desc}\n"
506 $ hg glog --template "{rev}: {branches} {desc}\n"
508 @ 2: A a2
507 @ 2: A a2
509 |
508 |
510 | o 1: B b
509 | o 1: B b
511 |/
510 |/
512 o 0: A a
511 o 0: A a
513
512
514 glog of remote:
513 glog of remote:
515
514
516 $ hg glog -R inner --template "{rev}: {branches} {desc}\n"
515 $ hg glog -R inner --template "{rev}: {branches} {desc}\n"
517 @ 2: B b1
516 @ 2: B b1
518 |
517 |
519 o 1: B b
518 o 1: B b
520 |
519 |
521 o 0: A a
520 o 0: A a
522
521
523 outgoing:
522 outgoing:
524
523
525 $ hg out inner --template "{rev}: {branches} {desc}\n"
524 $ hg out inner --template "{rev}: {branches} {desc}\n"
526 comparing with inner
525 comparing with inner
527 searching for changes
526 searching for changes
528 2: A a2
527 2: A a2
529
528
530 $ hg push inner
529 $ hg push inner
531 pushing to inner
530 pushing to inner
532 searching for changes
531 searching for changes
533 adding changesets
532 adding changesets
534 adding manifests
533 adding manifests
535 adding file changes
534 adding file changes
536 added 1 changesets with 1 changes to 1 files (+1 heads)
535 added 1 changesets with 1 changes to 1 files (+1 heads)
537
536
538 $ cd ..
537 $ cd ..
539
538
540
539
541 Check prepush with new branch head on former topo head:
540 Check prepush with new branch head on former topo head:
542
541
543 $ hg init o
542 $ hg init o
544 $ cd o
543 $ cd o
545 $ hg branch A
544 $ hg branch A
546 marked working directory as branch A
545 marked working directory as branch A
547 $ echo a >a
546 $ echo a >a
548 $ hg ci -Ama
547 $ hg ci -Ama
549 adding a
548 adding a
550 $ hg branch B
549 $ hg branch B
551 marked working directory as branch B
550 marked working directory as branch B
552 $ echo b >b
551 $ echo b >b
553 $ hg ci -Amb
552 $ hg ci -Amb
554 adding b
553 adding b
555
554
556 b is now branch head of B, and a topological head
555 b is now branch head of B, and a topological head
557
556
558 $ hg up 0
557 $ hg up 0
559 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
558 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
560 $ echo a1 >a1
559 $ echo a1 >a1
561 $ hg ci -Ama1
560 $ hg ci -Ama1
562 adding a1
561 adding a1
563
562
564 a1 is now branch head of A, and a topological head
563 a1 is now branch head of A, and a topological head
565
564
566 $ hg clone . inner
565 $ hg clone . inner
567 updating to branch A
566 updating to branch A
568 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
567 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
569 $ cd inner
568 $ cd inner
570 $ hg up B
569 $ hg up B
571 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
570 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
572 $ echo b1 >b1
571 $ echo b1 >b1
573 $ hg ci -Amb1
572 $ hg ci -Amb1
574 adding b1
573 adding b1
575
574
576 in the clone b1 is now the head of B
575 in the clone b1 is now the head of B
577
576
578 $ cd ..
577 $ cd ..
579 $ echo a2 >a2
578 $ echo a2 >a2
580 $ hg ci -Ama2
579 $ hg ci -Ama2
581 adding a2
580 adding a2
582
581
583 a2 is now the new branch head of A, and a topological head
582 a2 is now the new branch head of A, and a topological head
584 it replaces a former topological and branch head, so this should not warn
583 it replaces a former topological and branch head, so this should not warn
585
584
586 glog of local:
585 glog of local:
587
586
588 $ hg glog --template "{rev}: {branches} {desc}\n"
587 $ hg glog --template "{rev}: {branches} {desc}\n"
589 @ 3: A a2
588 @ 3: A a2
590 |
589 |
591 o 2: A a1
590 o 2: A a1
592 |
591 |
593 | o 1: B b
592 | o 1: B b
594 |/
593 |/
595 o 0: A a
594 o 0: A a
596
595
597 glog of remote:
596 glog of remote:
598
597
599 $ hg glog -R inner --template "{rev}: {branches} {desc}\n"
598 $ hg glog -R inner --template "{rev}: {branches} {desc}\n"
600 @ 3: B b1
599 @ 3: B b1
601 |
600 |
602 | o 2: A a1
601 | o 2: A a1
603 | |
602 | |
604 o | 1: B b
603 o | 1: B b
605 |/
604 |/
606 o 0: A a
605 o 0: A a
607
606
608 outgoing:
607 outgoing:
609
608
610 $ hg out inner --template "{rev}: {branches} {desc}\n"
609 $ hg out inner --template "{rev}: {branches} {desc}\n"
611 comparing with inner
610 comparing with inner
612 searching for changes
611 searching for changes
613 3: A a2
612 3: A a2
614
613
615 $ hg push inner
614 $ hg push inner
616 pushing to inner
615 pushing to inner
617 searching for changes
616 searching for changes
618 adding changesets
617 adding changesets
619 adding manifests
618 adding manifests
620 adding file changes
619 adding file changes
621 added 1 changesets with 1 changes to 1 files
620 added 1 changesets with 1 changes to 1 files
622
621
623 $ cd ..
622 $ cd ..
624
623
625
624
626 Check prepush with new branch head and new child of former branch head
625 Check prepush with new branch head and new child of former branch head
627 but child is on different branch:
626 but child is on different branch:
628
627
629 $ hg init p
628 $ hg init p
630 $ cd p
629 $ cd p
631 $ hg branch A
630 $ hg branch A
632 marked working directory as branch A
631 marked working directory as branch A
633 $ echo a0 >a
632 $ echo a0 >a
634 $ hg ci -Ama0
633 $ hg ci -Ama0
635 adding a
634 adding a
636 $ echo a1 >a
635 $ echo a1 >a
637 $ hg ci -ma1
636 $ hg ci -ma1
638 $ hg up null
637 $ hg up null
639 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
638 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
640 $ hg branch B
639 $ hg branch B
641 marked working directory as branch B
640 marked working directory as branch B
642 $ echo b0 >b
641 $ echo b0 >b
643 $ hg ci -Amb0
642 $ hg ci -Amb0
644 adding b
643 adding b
645 $ echo b1 >b
644 $ echo b1 >b
646 $ hg ci -mb1
645 $ hg ci -mb1
647
646
648 $ hg clone . inner
647 $ hg clone . inner
649 updating to branch B
648 updating to branch B
650 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
649 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
651
650
652 $ hg up A
651 $ hg up A
653 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
652 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
654 $ hg branch -f B
653 $ hg branch -f B
655 marked working directory as branch B
654 marked working directory as branch B
656 $ echo a3 >a
655 $ echo a3 >a
657 $ hg ci -ma3
656 $ hg ci -ma3
658 created new head
657 created new head
659 $ hg up 3
658 $ hg up 3
660 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
659 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
661 $ hg branch -f A
660 $ hg branch -f A
662 marked working directory as branch A
661 marked working directory as branch A
663 $ echo b3 >b
662 $ echo b3 >b
664 $ hg ci -mb3
663 $ hg ci -mb3
665 created new head
664 created new head
666
665
667 glog of local:
666 glog of local:
668
667
669 $ hg glog --template "{rev}: {branches} {desc}\n"
668 $ hg glog --template "{rev}: {branches} {desc}\n"
670 @ 5: A b3
669 @ 5: A b3
671 |
670 |
672 | o 4: B a3
671 | o 4: B a3
673 | |
672 | |
674 o | 3: B b1
673 o | 3: B b1
675 | |
674 | |
676 o | 2: B b0
675 o | 2: B b0
677 /
676 /
678 o 1: A a1
677 o 1: A a1
679 |
678 |
680 o 0: A a0
679 o 0: A a0
681
680
682 glog of remote:
681 glog of remote:
683
682
684 $ hg glog -R inner --template "{rev}: {branches} {desc}\n"
683 $ hg glog -R inner --template "{rev}: {branches} {desc}\n"
685 @ 3: B b1
684 @ 3: B b1
686 |
685 |
687 o 2: B b0
686 o 2: B b0
688
687
689 o 1: A a1
688 o 1: A a1
690 |
689 |
691 o 0: A a0
690 o 0: A a0
692
691
693 outgoing:
692 outgoing:
694
693
695 $ hg out inner --template "{rev}: {branches} {desc}\n"
694 $ hg out inner --template "{rev}: {branches} {desc}\n"
696 comparing with inner
695 comparing with inner
697 searching for changes
696 searching for changes
698 4: B a3
697 4: B a3
699 5: A b3
698 5: A b3
700
699
701 $ hg push inner
700 $ hg push inner
702 pushing to inner
701 pushing to inner
703 searching for changes
702 searching for changes
704 abort: push creates new remote heads on branch 'A'!
703 abort: push creates new remote heads on branch 'A'!
705 (did you forget to merge? use push -f to force)
704 (did you forget to merge? use push -f to force)
706 [255]
705 [255]
707
706
708 $ hg push inner -r4 -r5
707 $ hg push inner -r4 -r5
709 pushing to inner
708 pushing to inner
710 searching for changes
709 searching for changes
711 abort: push creates new remote heads on branch 'A'!
710 abort: push creates new remote heads on branch 'A'!
712 (did you forget to merge? use push -f to force)
711 (did you forget to merge? use push -f to force)
713 [255]
712 [255]
714
713
715 $ hg in inner
714 $ hg in inner
716 comparing with inner
715 comparing with inner
717 searching for changes
716 searching for changes
718 no changes found
717 no changes found
719 [1]
718 [1]
General Comments 0
You need to be logged in to leave comments. Login now