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