##// END OF EJS Templates
update: fix bare update to work on new branch...
liscju -
r28903:e1dd0de2 default
parent child Browse files
Show More
@@ -1,422 +1,418 b''
1 # destutil.py - Mercurial utility function for command destination
1 # destutil.py - Mercurial utility function for command destination
2 #
2 #
3 # Copyright Matt Mackall <mpm@selenic.com> and other
3 # Copyright Matt Mackall <mpm@selenic.com> and other
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 __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 from .i18n import _
10 from .i18n import _
11 from . import (
11 from . import (
12 bookmarks,
12 bookmarks,
13 error,
13 error,
14 obsolete,
14 obsolete,
15 )
15 )
16
16
17 def _destupdatevalidate(repo, rev, clean, check):
17 def _destupdatevalidate(repo, rev, clean, check):
18 """validate that the destination comply to various rules
18 """validate that the destination comply to various rules
19
19
20 This exists as its own function to help wrapping from extensions."""
20 This exists as its own function to help wrapping from extensions."""
21 wc = repo[None]
21 wc = repo[None]
22 p1 = wc.p1()
22 p1 = wc.p1()
23 if not clean:
23 if not clean:
24 # Check that the update is linear.
24 # Check that the update is linear.
25 #
25 #
26 # Mercurial do not allow update-merge for non linear pattern
26 # Mercurial do not allow update-merge for non linear pattern
27 # (that would be technically possible but was considered too confusing
27 # (that would be technically possible but was considered too confusing
28 # for user a long time ago)
28 # for user a long time ago)
29 #
29 #
30 # See mercurial.merge.update for details
30 # See mercurial.merge.update for details
31 if p1.rev() not in repo.changelog.ancestors([rev], inclusive=True):
31 if p1.rev() not in repo.changelog.ancestors([rev], inclusive=True):
32 dirty = wc.dirty(missing=True)
32 dirty = wc.dirty(missing=True)
33 foreground = obsolete.foreground(repo, [p1.node()])
33 foreground = obsolete.foreground(repo, [p1.node()])
34 if not repo[rev].node() in foreground:
34 if not repo[rev].node() in foreground:
35 if dirty:
35 if dirty:
36 msg = _("uncommitted changes")
36 msg = _("uncommitted changes")
37 hint = _("commit and merge, or update --clean to"
37 hint = _("commit and merge, or update --clean to"
38 " discard changes")
38 " discard changes")
39 raise error.UpdateAbort(msg, hint=hint)
39 raise error.UpdateAbort(msg, hint=hint)
40 elif not check: # destination is not a descendant.
40 elif not check: # destination is not a descendant.
41 msg = _("not a linear update")
41 msg = _("not a linear update")
42 hint = _("merge or update --check to force update")
42 hint = _("merge or update --check to force update")
43 raise error.UpdateAbort(msg, hint=hint)
43 raise error.UpdateAbort(msg, hint=hint)
44
44
45 def _destupdateobs(repo, clean, check):
45 def _destupdateobs(repo, clean, check):
46 """decide of an update destination from obsolescence markers"""
46 """decide of an update destination from obsolescence markers"""
47 node = None
47 node = None
48 wc = repo[None]
48 wc = repo[None]
49 p1 = wc.p1()
49 p1 = wc.p1()
50 movemark = None
50 movemark = None
51
51
52 if p1.obsolete() and not p1.children():
52 if p1.obsolete() and not p1.children():
53 # allow updating to successors
53 # allow updating to successors
54 successors = obsolete.successorssets(repo, p1.node())
54 successors = obsolete.successorssets(repo, p1.node())
55
55
56 # behavior of certain cases is as follows,
56 # behavior of certain cases is as follows,
57 #
57 #
58 # divergent changesets: update to highest rev, similar to what
58 # divergent changesets: update to highest rev, similar to what
59 # is currently done when there are more than one head
59 # is currently done when there are more than one head
60 # (i.e. 'tip')
60 # (i.e. 'tip')
61 #
61 #
62 # replaced changesets: same as divergent except we know there
62 # replaced changesets: same as divergent except we know there
63 # is no conflict
63 # is no conflict
64 #
64 #
65 # pruned changeset: no update is done; though, we could
65 # pruned changeset: no update is done; though, we could
66 # consider updating to the first non-obsolete parent,
66 # consider updating to the first non-obsolete parent,
67 # similar to what is current done for 'hg prune'
67 # similar to what is current done for 'hg prune'
68
68
69 if successors:
69 if successors:
70 # flatten the list here handles both divergent (len > 1)
70 # flatten the list here handles both divergent (len > 1)
71 # and the usual case (len = 1)
71 # and the usual case (len = 1)
72 successors = [n for sub in successors for n in sub]
72 successors = [n for sub in successors for n in sub]
73
73
74 # get the max revision for the given successors set,
74 # get the max revision for the given successors set,
75 # i.e. the 'tip' of a set
75 # i.e. the 'tip' of a set
76 node = repo.revs('max(%ln)', successors).first()
76 node = repo.revs('max(%ln)', successors).first()
77 if bookmarks.isactivewdirparent(repo):
77 if bookmarks.isactivewdirparent(repo):
78 movemark = repo['.'].node()
78 movemark = repo['.'].node()
79 return node, movemark, None
79 return node, movemark, None
80
80
81 def _destupdatebook(repo, clean, check):
81 def _destupdatebook(repo, clean, check):
82 """decide on an update destination from active bookmark"""
82 """decide on an update destination from active bookmark"""
83 # we also move the active bookmark, if any
83 # we also move the active bookmark, if any
84 activemark = None
84 activemark = None
85 node, movemark = bookmarks.calculateupdate(repo.ui, repo, None)
85 node, movemark = bookmarks.calculateupdate(repo.ui, repo, None)
86 if node is not None:
86 if node is not None:
87 activemark = node
87 activemark = node
88 return node, movemark, activemark
88 return node, movemark, activemark
89
89
90 def _destupdatebranch(repo, clean, check):
90 def _destupdatebranch(repo, clean, check):
91 """decide on an update destination from current branch
91 """decide on an update destination from current branch
92
92
93 This ignores closed branch heads.
93 This ignores closed branch heads.
94 """
94 """
95 wc = repo[None]
95 wc = repo[None]
96 movemark = node = None
96 movemark = node = None
97 currentbranch = wc.branch()
97 currentbranch = wc.branch()
98 if currentbranch in repo.branchmap():
98 if currentbranch in repo.branchmap():
99 heads = repo.branchheads(currentbranch)
99 heads = repo.branchheads(currentbranch)
100 if heads:
100 if heads:
101 node = repo.revs('max(.::(%ln))', heads).first()
101 node = repo.revs('max(.::(%ln))', heads).first()
102 if bookmarks.isactivewdirparent(repo):
102 if bookmarks.isactivewdirparent(repo):
103 movemark = repo['.'].node()
103 movemark = repo['.'].node()
104 else:
104 else:
105 if currentbranch == 'default': # no default branch!
105 node = repo['.'].node()
106 # update to the tipmost non-closed branch head
107 node = repo.revs('max(head() and not closed())').first()
108 else:
109 raise error.Abort(_("branch %s not found") % currentbranch)
110 return node, movemark, None
106 return node, movemark, None
111
107
112 def _destupdatebranchfallback(repo, clean, check):
108 def _destupdatebranchfallback(repo, clean, check):
113 """decide on an update destination from closed heads in current branch"""
109 """decide on an update destination from closed heads in current branch"""
114 wc = repo[None]
110 wc = repo[None]
115 currentbranch = wc.branch()
111 currentbranch = wc.branch()
116 movemark = None
112 movemark = None
117 if currentbranch in repo.branchmap():
113 if currentbranch in repo.branchmap():
118 # here, all descendant branch heads are closed
114 # here, all descendant branch heads are closed
119 heads = repo.branchheads(currentbranch, closed=True)
115 heads = repo.branchheads(currentbranch, closed=True)
120 assert heads, "any branch has at least one head"
116 assert heads, "any branch has at least one head"
121 node = repo.revs('max(.::(%ln))', heads).first()
117 node = repo.revs('max(.::(%ln))', heads).first()
122 assert node is not None, ("any revision has at least "
118 assert node is not None, ("any revision has at least "
123 "one descendant branch head")
119 "one descendant branch head")
124 if bookmarks.isactivewdirparent(repo):
120 if bookmarks.isactivewdirparent(repo):
125 movemark = repo['.'].node()
121 movemark = repo['.'].node()
126 else:
122 else:
127 # here, no "default" branch, and all branches are closed
123 # here, no "default" branch, and all branches are closed
128 node = repo.lookup('tip')
124 node = repo.lookup('tip')
129 assert node is not None, "'tip' exists even in empty repository"
125 assert node is not None, "'tip' exists even in empty repository"
130 return node, movemark, None
126 return node, movemark, None
131
127
132 # order in which each step should be evalutated
128 # order in which each step should be evalutated
133 # steps are run until one finds a destination
129 # steps are run until one finds a destination
134 destupdatesteps = ['evolution', 'bookmark', 'branch', 'branchfallback']
130 destupdatesteps = ['evolution', 'bookmark', 'branch', 'branchfallback']
135 # mapping to ease extension overriding steps.
131 # mapping to ease extension overriding steps.
136 destupdatestepmap = {'evolution': _destupdateobs,
132 destupdatestepmap = {'evolution': _destupdateobs,
137 'bookmark': _destupdatebook,
133 'bookmark': _destupdatebook,
138 'branch': _destupdatebranch,
134 'branch': _destupdatebranch,
139 'branchfallback': _destupdatebranchfallback,
135 'branchfallback': _destupdatebranchfallback,
140 }
136 }
141
137
142 def destupdate(repo, clean=False, check=False):
138 def destupdate(repo, clean=False, check=False):
143 """destination for bare update operation
139 """destination for bare update operation
144
140
145 return (rev, movemark, activemark)
141 return (rev, movemark, activemark)
146
142
147 - rev: the revision to update to,
143 - rev: the revision to update to,
148 - movemark: node to move the active bookmark from
144 - movemark: node to move the active bookmark from
149 (cf bookmark.calculate update),
145 (cf bookmark.calculate update),
150 - activemark: a bookmark to activate at the end of the update.
146 - activemark: a bookmark to activate at the end of the update.
151 """
147 """
152 node = movemark = activemark = None
148 node = movemark = activemark = None
153
149
154 for step in destupdatesteps:
150 for step in destupdatesteps:
155 node, movemark, activemark = destupdatestepmap[step](repo, clean, check)
151 node, movemark, activemark = destupdatestepmap[step](repo, clean, check)
156 if node is not None:
152 if node is not None:
157 break
153 break
158 rev = repo[node].rev()
154 rev = repo[node].rev()
159
155
160 _destupdatevalidate(repo, rev, clean, check)
156 _destupdatevalidate(repo, rev, clean, check)
161
157
162 return rev, movemark, activemark
158 return rev, movemark, activemark
163
159
164 msgdestmerge = {
160 msgdestmerge = {
165 # too many matching divergent bookmark
161 # too many matching divergent bookmark
166 'toomanybookmarks':
162 'toomanybookmarks':
167 {'merge':
163 {'merge':
168 (_("multiple matching bookmarks to merge -"
164 (_("multiple matching bookmarks to merge -"
169 " please merge with an explicit rev or bookmark"),
165 " please merge with an explicit rev or bookmark"),
170 _("run 'hg heads' to see all heads")),
166 _("run 'hg heads' to see all heads")),
171 'rebase':
167 'rebase':
172 (_("multiple matching bookmarks to rebase -"
168 (_("multiple matching bookmarks to rebase -"
173 " please rebase to an explicit rev or bookmark"),
169 " please rebase to an explicit rev or bookmark"),
174 _("run 'hg heads' to see all heads")),
170 _("run 'hg heads' to see all heads")),
175 },
171 },
176 # no other matching divergent bookmark
172 # no other matching divergent bookmark
177 'nootherbookmarks':
173 'nootherbookmarks':
178 {'merge':
174 {'merge':
179 (_("no matching bookmark to merge - "
175 (_("no matching bookmark to merge - "
180 "please merge with an explicit rev or bookmark"),
176 "please merge with an explicit rev or bookmark"),
181 _("run 'hg heads' to see all heads")),
177 _("run 'hg heads' to see all heads")),
182 'rebase':
178 'rebase':
183 (_("no matching bookmark to rebase - "
179 (_("no matching bookmark to rebase - "
184 "please rebase to an explicit rev or bookmark"),
180 "please rebase to an explicit rev or bookmark"),
185 _("run 'hg heads' to see all heads")),
181 _("run 'hg heads' to see all heads")),
186 },
182 },
187 # branch have too many unbookmarked heads, no obvious destination
183 # branch have too many unbookmarked heads, no obvious destination
188 'toomanyheads':
184 'toomanyheads':
189 {'merge':
185 {'merge':
190 (_("branch '%s' has %d heads - please merge with an explicit rev"),
186 (_("branch '%s' has %d heads - please merge with an explicit rev"),
191 _("run 'hg heads .' to see heads")),
187 _("run 'hg heads .' to see heads")),
192 'rebase':
188 'rebase':
193 (_("branch '%s' has %d heads - please rebase to an explicit rev"),
189 (_("branch '%s' has %d heads - please rebase to an explicit rev"),
194 _("run 'hg heads .' to see heads")),
190 _("run 'hg heads .' to see heads")),
195 },
191 },
196 # branch have no other unbookmarked heads
192 # branch have no other unbookmarked heads
197 'bookmarkedheads':
193 'bookmarkedheads':
198 {'merge':
194 {'merge':
199 (_("heads are bookmarked - please merge with an explicit rev"),
195 (_("heads are bookmarked - please merge with an explicit rev"),
200 _("run 'hg heads' to see all heads")),
196 _("run 'hg heads' to see all heads")),
201 'rebase':
197 'rebase':
202 (_("heads are bookmarked - please rebase to an explicit rev"),
198 (_("heads are bookmarked - please rebase to an explicit rev"),
203 _("run 'hg heads' to see all heads")),
199 _("run 'hg heads' to see all heads")),
204 },
200 },
205 # branch have just a single heads, but there is other branches
201 # branch have just a single heads, but there is other branches
206 'nootherbranchheads':
202 'nootherbranchheads':
207 {'merge':
203 {'merge':
208 (_("branch '%s' has one head - please merge with an explicit rev"),
204 (_("branch '%s' has one head - please merge with an explicit rev"),
209 _("run 'hg heads' to see all heads")),
205 _("run 'hg heads' to see all heads")),
210 'rebase':
206 'rebase':
211 (_("branch '%s' has one head - please rebase to an explicit rev"),
207 (_("branch '%s' has one head - please rebase to an explicit rev"),
212 _("run 'hg heads' to see all heads")),
208 _("run 'hg heads' to see all heads")),
213 },
209 },
214 # repository have a single head
210 # repository have a single head
215 'nootherheads':
211 'nootherheads':
216 {'merge':
212 {'merge':
217 (_('nothing to merge'),
213 (_('nothing to merge'),
218 None),
214 None),
219 'rebase':
215 'rebase':
220 (_('nothing to rebase'),
216 (_('nothing to rebase'),
221 None),
217 None),
222 },
218 },
223 # repository have a single head and we are not on it
219 # repository have a single head and we are not on it
224 'nootherheadsbehind':
220 'nootherheadsbehind':
225 {'merge':
221 {'merge':
226 (_('nothing to merge'),
222 (_('nothing to merge'),
227 _("use 'hg update' instead")),
223 _("use 'hg update' instead")),
228 'rebase':
224 'rebase':
229 (_('nothing to rebase'),
225 (_('nothing to rebase'),
230 _("use 'hg update' instead")),
226 _("use 'hg update' instead")),
231 },
227 },
232 # We are not on a head
228 # We are not on a head
233 'notatheads':
229 'notatheads':
234 {'merge':
230 {'merge':
235 (_('working directory not at a head revision'),
231 (_('working directory not at a head revision'),
236 _("use 'hg update' or merge with an explicit revision")),
232 _("use 'hg update' or merge with an explicit revision")),
237 'rebase':
233 'rebase':
238 (_('working directory not at a head revision'),
234 (_('working directory not at a head revision'),
239 _("use 'hg update' or rebase to an explicit revision"))
235 _("use 'hg update' or rebase to an explicit revision"))
240 },
236 },
241 'emptysourceset':
237 'emptysourceset':
242 {'merge':
238 {'merge':
243 (_('source set is empty'),
239 (_('source set is empty'),
244 None),
240 None),
245 'rebase':
241 'rebase':
246 (_('source set is empty'),
242 (_('source set is empty'),
247 None),
243 None),
248 },
244 },
249 'multiplebranchessourceset':
245 'multiplebranchessourceset':
250 {'merge':
246 {'merge':
251 (_('source set is rooted in multiple branches'),
247 (_('source set is rooted in multiple branches'),
252 None),
248 None),
253 'rebase':
249 'rebase':
254 (_('rebaseset is rooted in multiple named branches'),
250 (_('rebaseset is rooted in multiple named branches'),
255 _('specify an explicit destination with --dest')),
251 _('specify an explicit destination with --dest')),
256 },
252 },
257 }
253 }
258
254
259 def _destmergebook(repo, action='merge', sourceset=None):
255 def _destmergebook(repo, action='merge', sourceset=None):
260 """find merge destination in the active bookmark case"""
256 """find merge destination in the active bookmark case"""
261 node = None
257 node = None
262 bmheads = repo.bookmarkheads(repo._activebookmark)
258 bmheads = repo.bookmarkheads(repo._activebookmark)
263 curhead = repo[repo._activebookmark].node()
259 curhead = repo[repo._activebookmark].node()
264 if len(bmheads) == 2:
260 if len(bmheads) == 2:
265 if curhead == bmheads[0]:
261 if curhead == bmheads[0]:
266 node = bmheads[1]
262 node = bmheads[1]
267 else:
263 else:
268 node = bmheads[0]
264 node = bmheads[0]
269 elif len(bmheads) > 2:
265 elif len(bmheads) > 2:
270 msg, hint = msgdestmerge['toomanybookmarks'][action]
266 msg, hint = msgdestmerge['toomanybookmarks'][action]
271 raise error.ManyMergeDestAbort(msg, hint=hint)
267 raise error.ManyMergeDestAbort(msg, hint=hint)
272 elif len(bmheads) <= 1:
268 elif len(bmheads) <= 1:
273 msg, hint = msgdestmerge['nootherbookmarks'][action]
269 msg, hint = msgdestmerge['nootherbookmarks'][action]
274 raise error.NoMergeDestAbort(msg, hint=hint)
270 raise error.NoMergeDestAbort(msg, hint=hint)
275 assert node is not None
271 assert node is not None
276 return node
272 return node
277
273
278 def _destmergebranch(repo, action='merge', sourceset=None, onheadcheck=True):
274 def _destmergebranch(repo, action='merge', sourceset=None, onheadcheck=True):
279 """find merge destination based on branch heads"""
275 """find merge destination based on branch heads"""
280 node = None
276 node = None
281
277
282 if sourceset is None:
278 if sourceset is None:
283 sourceset = [repo[repo.dirstate.p1()].rev()]
279 sourceset = [repo[repo.dirstate.p1()].rev()]
284 branch = repo.dirstate.branch()
280 branch = repo.dirstate.branch()
285 elif not sourceset:
281 elif not sourceset:
286 msg, hint = msgdestmerge['emptysourceset'][action]
282 msg, hint = msgdestmerge['emptysourceset'][action]
287 raise error.NoMergeDestAbort(msg, hint=hint)
283 raise error.NoMergeDestAbort(msg, hint=hint)
288 else:
284 else:
289 branch = None
285 branch = None
290 for ctx in repo.set('roots(%ld::%ld)', sourceset, sourceset):
286 for ctx in repo.set('roots(%ld::%ld)', sourceset, sourceset):
291 if branch is not None and ctx.branch() != branch:
287 if branch is not None and ctx.branch() != branch:
292 msg, hint = msgdestmerge['multiplebranchessourceset'][action]
288 msg, hint = msgdestmerge['multiplebranchessourceset'][action]
293 raise error.ManyMergeDestAbort(msg, hint=hint)
289 raise error.ManyMergeDestAbort(msg, hint=hint)
294 branch = ctx.branch()
290 branch = ctx.branch()
295
291
296 bheads = repo.branchheads(branch)
292 bheads = repo.branchheads(branch)
297 onhead = repo.revs('%ld and %ln', sourceset, bheads)
293 onhead = repo.revs('%ld and %ln', sourceset, bheads)
298 if onheadcheck and not onhead:
294 if onheadcheck and not onhead:
299 # Case A: working copy if not on a head. (merge only)
295 # Case A: working copy if not on a head. (merge only)
300 #
296 #
301 # This is probably a user mistake We bailout pointing at 'hg update'
297 # This is probably a user mistake We bailout pointing at 'hg update'
302 if len(repo.heads()) <= 1:
298 if len(repo.heads()) <= 1:
303 msg, hint = msgdestmerge['nootherheadsbehind'][action]
299 msg, hint = msgdestmerge['nootherheadsbehind'][action]
304 else:
300 else:
305 msg, hint = msgdestmerge['notatheads'][action]
301 msg, hint = msgdestmerge['notatheads'][action]
306 raise error.Abort(msg, hint=hint)
302 raise error.Abort(msg, hint=hint)
307 # remove heads descendants of source from the set
303 # remove heads descendants of source from the set
308 bheads = list(repo.revs('%ln - (%ld::)', bheads, sourceset))
304 bheads = list(repo.revs('%ln - (%ld::)', bheads, sourceset))
309 # filters out bookmarked heads
305 # filters out bookmarked heads
310 nbhs = list(repo.revs('%ld - bookmark()', bheads))
306 nbhs = list(repo.revs('%ld - bookmark()', bheads))
311 if len(nbhs) > 1:
307 if len(nbhs) > 1:
312 # Case B: There is more than 1 other anonymous heads
308 # Case B: There is more than 1 other anonymous heads
313 #
309 #
314 # This means that there will be more than 1 candidate. This is
310 # This means that there will be more than 1 candidate. This is
315 # ambiguous. We abort asking the user to pick as explicit destination
311 # ambiguous. We abort asking the user to pick as explicit destination
316 # instead.
312 # instead.
317 msg, hint = msgdestmerge['toomanyheads'][action]
313 msg, hint = msgdestmerge['toomanyheads'][action]
318 msg %= (branch, len(bheads) + 1)
314 msg %= (branch, len(bheads) + 1)
319 raise error.ManyMergeDestAbort(msg, hint=hint)
315 raise error.ManyMergeDestAbort(msg, hint=hint)
320 elif not nbhs:
316 elif not nbhs:
321 # Case B: There is no other anonymous heads
317 # Case B: There is no other anonymous heads
322 #
318 #
323 # This means that there is no natural candidate to merge with.
319 # This means that there is no natural candidate to merge with.
324 # We abort, with various messages for various cases.
320 # We abort, with various messages for various cases.
325 if bheads:
321 if bheads:
326 msg, hint = msgdestmerge['bookmarkedheads'][action]
322 msg, hint = msgdestmerge['bookmarkedheads'][action]
327 elif len(repo.heads()) > 1:
323 elif len(repo.heads()) > 1:
328 msg, hint = msgdestmerge['nootherbranchheads'][action]
324 msg, hint = msgdestmerge['nootherbranchheads'][action]
329 msg %= branch
325 msg %= branch
330 elif not onhead:
326 elif not onhead:
331 # if 'onheadcheck == False' (rebase case),
327 # if 'onheadcheck == False' (rebase case),
332 # this was not caught in Case A.
328 # this was not caught in Case A.
333 msg, hint = msgdestmerge['nootherheadsbehind'][action]
329 msg, hint = msgdestmerge['nootherheadsbehind'][action]
334 else:
330 else:
335 msg, hint = msgdestmerge['nootherheads'][action]
331 msg, hint = msgdestmerge['nootherheads'][action]
336 raise error.NoMergeDestAbort(msg, hint=hint)
332 raise error.NoMergeDestAbort(msg, hint=hint)
337 else:
333 else:
338 node = nbhs[0]
334 node = nbhs[0]
339 assert node is not None
335 assert node is not None
340 return node
336 return node
341
337
342 def destmerge(repo, action='merge', sourceset=None, onheadcheck=True):
338 def destmerge(repo, action='merge', sourceset=None, onheadcheck=True):
343 """return the default destination for a merge
339 """return the default destination for a merge
344
340
345 (or raise exception about why it can't pick one)
341 (or raise exception about why it can't pick one)
346
342
347 :action: the action being performed, controls emitted error message
343 :action: the action being performed, controls emitted error message
348 """
344 """
349 if repo._activebookmark:
345 if repo._activebookmark:
350 node = _destmergebook(repo, action=action, sourceset=sourceset)
346 node = _destmergebook(repo, action=action, sourceset=sourceset)
351 else:
347 else:
352 node = _destmergebranch(repo, action=action, sourceset=sourceset,
348 node = _destmergebranch(repo, action=action, sourceset=sourceset,
353 onheadcheck=onheadcheck)
349 onheadcheck=onheadcheck)
354 return repo[node].rev()
350 return repo[node].rev()
355
351
356 histeditdefaultrevset = 'reverse(only(.) and not public() and not ::merge())'
352 histeditdefaultrevset = 'reverse(only(.) and not public() and not ::merge())'
357
353
358 def desthistedit(ui, repo):
354 def desthistedit(ui, repo):
359 """Default base revision to edit for `hg histedit`."""
355 """Default base revision to edit for `hg histedit`."""
360 # Avoid cycle: scmutil -> revset -> destutil
356 # Avoid cycle: scmutil -> revset -> destutil
361 from . import scmutil
357 from . import scmutil
362
358
363 default = ui.config('histedit', 'defaultrev', histeditdefaultrevset)
359 default = ui.config('histedit', 'defaultrev', histeditdefaultrevset)
364 if default:
360 if default:
365 revs = scmutil.revrange(repo, [default])
361 revs = scmutil.revrange(repo, [default])
366 if revs:
362 if revs:
367 # The revset supplied by the user may not be in ascending order nor
363 # The revset supplied by the user may not be in ascending order nor
368 # take the first revision. So do this manually.
364 # take the first revision. So do this manually.
369 revs.sort()
365 revs.sort()
370 return revs.first()
366 return revs.first()
371
367
372 return None
368 return None
373
369
374 def _statusotherbook(ui, repo):
370 def _statusotherbook(ui, repo):
375 bmheads = repo.bookmarkheads(repo._activebookmark)
371 bmheads = repo.bookmarkheads(repo._activebookmark)
376 curhead = repo[repo._activebookmark].node()
372 curhead = repo[repo._activebookmark].node()
377 if repo.revs('%n and parents()', curhead):
373 if repo.revs('%n and parents()', curhead):
378 # we are on the active bookmark
374 # we are on the active bookmark
379 bmheads = [b for b in bmheads if curhead != b]
375 bmheads = [b for b in bmheads if curhead != b]
380 if bmheads:
376 if bmheads:
381 msg = _('%i other divergent bookmarks for "%s"\n')
377 msg = _('%i other divergent bookmarks for "%s"\n')
382 ui.status(msg % (len(bmheads), repo._activebookmark))
378 ui.status(msg % (len(bmheads), repo._activebookmark))
383
379
384 def _statusotherbranchheads(ui, repo):
380 def _statusotherbranchheads(ui, repo):
385 currentbranch = repo.dirstate.branch()
381 currentbranch = repo.dirstate.branch()
386 allheads = repo.branchheads(currentbranch, closed=True)
382 allheads = repo.branchheads(currentbranch, closed=True)
387 heads = repo.branchheads(currentbranch)
383 heads = repo.branchheads(currentbranch)
388 if repo.revs('%ln and parents()', allheads):
384 if repo.revs('%ln and parents()', allheads):
389 # we are on a head, even though it might be closed
385 # we are on a head, even though it might be closed
390 #
386 #
391 # on closed otherheads
387 # on closed otherheads
392 # ========= ==========
388 # ========= ==========
393 # o 0 all heads for current branch are closed
389 # o 0 all heads for current branch are closed
394 # N only descendant branch heads are closed
390 # N only descendant branch heads are closed
395 # x 0 there is only one non-closed branch head
391 # x 0 there is only one non-closed branch head
396 # N there are some non-closed branch heads
392 # N there are some non-closed branch heads
397 # ========= ==========
393 # ========= ==========
398 otherheads = repo.revs('%ln - parents()', heads)
394 otherheads = repo.revs('%ln - parents()', heads)
399 if repo['.'].closesbranch():
395 if repo['.'].closesbranch():
400 ui.warn(_('no open descendant heads on branch "%s", '
396 ui.warn(_('no open descendant heads on branch "%s", '
401 'updating to a closed head\n') %
397 'updating to a closed head\n') %
402 (currentbranch))
398 (currentbranch))
403 if otherheads:
399 if otherheads:
404 ui.warn(_('(committing will reopen the head, '
400 ui.warn(_('(committing will reopen the head, '
405 'use `hg heads .` to see %i other heads)\n') %
401 'use `hg heads .` to see %i other heads)\n') %
406 (len(otherheads)))
402 (len(otherheads)))
407 else:
403 else:
408 ui.warn(_('(committing will reopen branch "%s")\n') %
404 ui.warn(_('(committing will reopen branch "%s")\n') %
409 (currentbranch))
405 (currentbranch))
410 elif otherheads:
406 elif otherheads:
411 ui.status(_('%i other heads for branch "%s"\n') %
407 ui.status(_('%i other heads for branch "%s"\n') %
412 (len(otherheads), currentbranch))
408 (len(otherheads), currentbranch))
413
409
414 def statusotherdests(ui, repo):
410 def statusotherdests(ui, repo):
415 """Print message about other head"""
411 """Print message about other head"""
416 # XXX we should probably include a hint:
412 # XXX we should probably include a hint:
417 # - about what to do
413 # - about what to do
418 # - how to see such heads
414 # - how to see such heads
419 if repo._activebookmark:
415 if repo._activebookmark:
420 _statusotherbook(ui, repo)
416 _statusotherbook(ui, repo)
421 else:
417 else:
422 _statusotherbranchheads(ui, repo)
418 _statusotherbranchheads(ui, repo)
@@ -1,347 +1,393 b''
1 $ branchcache=.hg/cache/branch2
1 $ branchcache=.hg/cache/branch2
2
2
3 $ listbranchcaches() {
3 $ listbranchcaches() {
4 > for f in .hg/cache/branch2*;
4 > for f in .hg/cache/branch2*;
5 > do echo === $f ===;
5 > do echo === $f ===;
6 > cat $f;
6 > cat $f;
7 > done;
7 > done;
8 > }
8 > }
9 $ purgebranchcaches() {
9 $ purgebranchcaches() {
10 > rm .hg/cache/branch2*
10 > rm .hg/cache/branch2*
11 > }
11 > }
12
12
13 $ hg init t
13 $ hg init t
14 $ cd t
14 $ cd t
15
15
16 $ hg branches
16 $ hg branches
17 $ echo foo > a
17 $ echo foo > a
18 $ hg add a
18 $ hg add a
19 $ hg ci -m "initial"
19 $ hg ci -m "initial"
20 $ hg branch foo
20 $ hg branch foo
21 marked working directory as branch foo
21 marked working directory as branch foo
22 (branches are permanent and global, did you want a bookmark?)
22 (branches are permanent and global, did you want a bookmark?)
23 $ hg branch
23 $ hg branch
24 foo
24 foo
25 $ hg ci -m "add branch name"
25 $ hg ci -m "add branch name"
26 $ hg branch bar
26 $ hg branch bar
27 marked working directory as branch bar
27 marked working directory as branch bar
28 $ hg ci -m "change branch name"
28 $ hg ci -m "change branch name"
29
29
30 Branch shadowing:
30 Branch shadowing:
31
31
32 $ hg branch default
32 $ hg branch default
33 abort: a branch of the same name already exists
33 abort: a branch of the same name already exists
34 (use 'hg update' to switch to it)
34 (use 'hg update' to switch to it)
35 [255]
35 [255]
36
36
37 $ hg branch -f default
37 $ hg branch -f default
38 marked working directory as branch default
38 marked working directory as branch default
39
39
40 $ hg ci -m "clear branch name"
40 $ hg ci -m "clear branch name"
41 created new head
41 created new head
42
42
43 There should be only one default branch head
43 There should be only one default branch head
44
44
45 $ hg heads .
45 $ hg heads .
46 changeset: 3:1c28f494dae6
46 changeset: 3:1c28f494dae6
47 tag: tip
47 tag: tip
48 user: test
48 user: test
49 date: Thu Jan 01 00:00:00 1970 +0000
49 date: Thu Jan 01 00:00:00 1970 +0000
50 summary: clear branch name
50 summary: clear branch name
51
51
52 Merging and branches
52 Merging and branches
53
53
54 $ hg co foo
54 $ hg co foo
55 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
55 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
56 $ hg branch
56 $ hg branch
57 foo
57 foo
58
58
59 set existing branch name fails unless force - setting existing parent branch works without force:
59 set existing branch name fails unless force - setting existing parent branch works without force:
60
60
61 $ hg branch bar
61 $ hg branch bar
62 abort: a branch of the same name already exists
62 abort: a branch of the same name already exists
63 (use 'hg update' to switch to it)
63 (use 'hg update' to switch to it)
64 [255]
64 [255]
65
65
66 $ hg branch -f bar
66 $ hg branch -f bar
67 marked working directory as branch bar
67 marked working directory as branch bar
68
68
69 $ hg branch foo
69 $ hg branch foo
70 marked working directory as branch foo
70 marked working directory as branch foo
71
71
72 $ echo bleah > a
72 $ echo bleah > a
73 $ hg ci -m "modify a branch"
73 $ hg ci -m "modify a branch"
74
74
75 $ hg merge default
75 $ hg merge default
76 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
76 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
77 (branch merge, don't forget to commit)
77 (branch merge, don't forget to commit)
78
78
79 $ hg branch
79 $ hg branch
80 foo
80 foo
81
81
82 set existing branch name where branch head is ancestor:
82 set existing branch name where branch head is ancestor:
83
83
84 $ hg branch bar
84 $ hg branch bar
85 abort: a branch of the same name already exists
85 abort: a branch of the same name already exists
86 (use 'hg update' to switch to it)
86 (use 'hg update' to switch to it)
87 [255]
87 [255]
88
88
89 set (other) parent branch as branch name
89 set (other) parent branch as branch name
90
90
91 $ hg branch default
91 $ hg branch default
92 marked working directory as branch default
92 marked working directory as branch default
93
93
94 set (first) parent branch as branch name
94 set (first) parent branch as branch name
95
95
96 $ hg branch foo
96 $ hg branch foo
97 marked working directory as branch foo
97 marked working directory as branch foo
98
98
99 $ hg ci -m "merge"
99 $ hg ci -m "merge"
100
100
101 $ hg log -G -T '{rev}:{node|short} {branch} {desc}\n'
101 $ hg log -G -T '{rev}:{node|short} {branch} {desc}\n'
102 @ 5:530046499edf foo merge
102 @ 5:530046499edf foo merge
103 |\
103 |\
104 | o 4:adf1a74a7f7b foo modify a branch
104 | o 4:adf1a74a7f7b foo modify a branch
105 | |
105 | |
106 o | 3:1c28f494dae6 default clear branch name
106 o | 3:1c28f494dae6 default clear branch name
107 | |
107 | |
108 o | 2:c21617b13b22 bar change branch name
108 o | 2:c21617b13b22 bar change branch name
109 |/
109 |/
110 o 1:6c0e42da283a foo add branch name
110 o 1:6c0e42da283a foo add branch name
111 |
111 |
112 o 0:db01e8ea3388 default initial
112 o 0:db01e8ea3388 default initial
113
113
114 $ hg branches
114 $ hg branches
115 foo 5:530046499edf
115 foo 5:530046499edf
116 default 3:1c28f494dae6 (inactive)
116 default 3:1c28f494dae6 (inactive)
117 bar 2:c21617b13b22 (inactive)
117 bar 2:c21617b13b22 (inactive)
118
118
119 $ hg branches -q
119 $ hg branches -q
120 foo
120 foo
121 default
121 default
122 bar
122 bar
123
123
124 Test for invalid branch cache:
124 Test for invalid branch cache:
125
125
126 $ hg rollback
126 $ hg rollback
127 repository tip rolled back to revision 4 (undo commit)
127 repository tip rolled back to revision 4 (undo commit)
128 working directory now based on revisions 4 and 3
128 working directory now based on revisions 4 and 3
129
129
130 $ cp ${branchcache}-served .hg/bc-invalid
130 $ cp ${branchcache}-served .hg/bc-invalid
131
131
132 $ hg log -r foo
132 $ hg log -r foo
133 changeset: 4:adf1a74a7f7b
133 changeset: 4:adf1a74a7f7b
134 branch: foo
134 branch: foo
135 tag: tip
135 tag: tip
136 parent: 1:6c0e42da283a
136 parent: 1:6c0e42da283a
137 user: test
137 user: test
138 date: Thu Jan 01 00:00:00 1970 +0000
138 date: Thu Jan 01 00:00:00 1970 +0000
139 summary: modify a branch
139 summary: modify a branch
140
140
141 $ cp .hg/bc-invalid $branchcache
141 $ cp .hg/bc-invalid $branchcache
142
142
143 $ hg --debug log -r foo
143 $ hg --debug log -r foo
144 changeset: 4:adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6
144 changeset: 4:adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6
145 branch: foo
145 branch: foo
146 tag: tip
146 tag: tip
147 phase: draft
147 phase: draft
148 parent: 1:6c0e42da283a56b5edc5b4fadb491365ec7f5fa8
148 parent: 1:6c0e42da283a56b5edc5b4fadb491365ec7f5fa8
149 parent: -1:0000000000000000000000000000000000000000
149 parent: -1:0000000000000000000000000000000000000000
150 manifest: 1:8c342a37dfba0b3d3ce073562a00d8a813c54ffe
150 manifest: 1:8c342a37dfba0b3d3ce073562a00d8a813c54ffe
151 user: test
151 user: test
152 date: Thu Jan 01 00:00:00 1970 +0000
152 date: Thu Jan 01 00:00:00 1970 +0000
153 files: a
153 files: a
154 extra: branch=foo
154 extra: branch=foo
155 description:
155 description:
156 modify a branch
156 modify a branch
157
157
158
158
159 $ purgebranchcaches
159 $ purgebranchcaches
160 $ echo corrupted > $branchcache
160 $ echo corrupted > $branchcache
161
161
162 $ hg log -qr foo
162 $ hg log -qr foo
163 4:adf1a74a7f7b
163 4:adf1a74a7f7b
164
164
165 $ listbranchcaches
165 $ listbranchcaches
166 === .hg/cache/branch2 ===
166 === .hg/cache/branch2 ===
167 corrupted
167 corrupted
168 === .hg/cache/branch2-served ===
168 === .hg/cache/branch2-served ===
169 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 4
169 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 4
170 c21617b13b220988e7a2e26290fbe4325ffa7139 o bar
170 c21617b13b220988e7a2e26290fbe4325ffa7139 o bar
171 1c28f494dae69a2f8fc815059d257eccf3fcfe75 o default
171 1c28f494dae69a2f8fc815059d257eccf3fcfe75 o default
172 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 o foo
172 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 o foo
173
173
174 Push should update the branch cache:
174 Push should update the branch cache:
175
175
176 $ hg init ../target
176 $ hg init ../target
177
177
178 Pushing just rev 0:
178 Pushing just rev 0:
179
179
180 $ hg push -qr 0 ../target
180 $ hg push -qr 0 ../target
181
181
182 $ (cd ../target/; listbranchcaches)
182 $ (cd ../target/; listbranchcaches)
183 === .hg/cache/branch2-base ===
183 === .hg/cache/branch2-base ===
184 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 0
184 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 0
185 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 o default
185 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 o default
186
186
187 Pushing everything:
187 Pushing everything:
188
188
189 $ hg push -qf ../target
189 $ hg push -qf ../target
190
190
191 $ (cd ../target/; listbranchcaches)
191 $ (cd ../target/; listbranchcaches)
192 === .hg/cache/branch2-base ===
192 === .hg/cache/branch2-base ===
193 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 4
193 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 4
194 c21617b13b220988e7a2e26290fbe4325ffa7139 o bar
194 c21617b13b220988e7a2e26290fbe4325ffa7139 o bar
195 1c28f494dae69a2f8fc815059d257eccf3fcfe75 o default
195 1c28f494dae69a2f8fc815059d257eccf3fcfe75 o default
196 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 o foo
196 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 o foo
197
197
198 Update with no arguments: tipmost revision of the current branch:
198 Update with no arguments: tipmost revision of the current branch:
199
199
200 $ hg up -q -C 0
200 $ hg up -q -C 0
201 $ hg up -q
201 $ hg up -q
202 $ hg id
202 $ hg id
203 1c28f494dae6
203 1c28f494dae6
204
204
205 $ hg up -q 1
205 $ hg up -q 1
206 $ hg up -q
206 $ hg up -q
207 $ hg id
207 $ hg id
208 adf1a74a7f7b (foo) tip
208 adf1a74a7f7b (foo) tip
209
209
210 $ hg branch foobar
210 $ hg branch foobar
211 marked working directory as branch foobar
211 marked working directory as branch foobar
212
212
213 $ hg up
213 $ hg up
214 abort: branch foobar not found
214 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
215 [255]
216
215
217 Fast-forward merge:
216 Fast-forward merge:
218
217
219 $ hg branch ff
218 $ hg branch ff
220 marked working directory as branch ff
219 marked working directory as branch ff
221
220
222 $ echo ff > ff
221 $ echo ff > ff
223 $ hg ci -Am'fast forward'
222 $ hg ci -Am'fast forward'
224 adding ff
223 adding ff
225
224
226 $ hg up foo
225 $ hg up foo
227 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
226 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
228
227
229 $ hg merge ff
228 $ hg merge ff
230 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
229 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
231 (branch merge, don't forget to commit)
230 (branch merge, don't forget to commit)
232
231
233 $ hg branch
232 $ hg branch
234 foo
233 foo
235 $ hg commit -m'Merge ff into foo'
234 $ hg commit -m'Merge ff into foo'
236 $ hg parents
235 $ hg parents
237 changeset: 6:185ffbfefa30
236 changeset: 6:185ffbfefa30
238 branch: foo
237 branch: foo
239 tag: tip
238 tag: tip
240 parent: 4:adf1a74a7f7b
239 parent: 4:adf1a74a7f7b
241 parent: 5:1a3c27dc5e11
240 parent: 5:1a3c27dc5e11
242 user: test
241 user: test
243 date: Thu Jan 01 00:00:00 1970 +0000
242 date: Thu Jan 01 00:00:00 1970 +0000
244 summary: Merge ff into foo
243 summary: Merge ff into foo
245
244
246 $ hg manifest
245 $ hg manifest
247 a
246 a
248 ff
247 ff
249
248
250
249
251 Test merging, add 3 default heads and one test head:
250 Test merging, add 3 default heads and one test head:
252
251
253 $ cd ..
252 $ cd ..
254 $ hg init merges
253 $ hg init merges
255 $ cd merges
254 $ cd merges
256 $ echo a > a
255 $ echo a > a
257 $ hg ci -Ama
256 $ hg ci -Ama
258 adding a
257 adding a
259
258
260 $ echo b > b
259 $ echo b > b
261 $ hg ci -Amb
260 $ hg ci -Amb
262 adding b
261 adding b
263
262
264 $ hg up 0
263 $ hg up 0
265 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
264 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
266 $ echo c > c
265 $ echo c > c
267 $ hg ci -Amc
266 $ hg ci -Amc
268 adding c
267 adding c
269 created new head
268 created new head
270
269
271 $ hg up 0
270 $ hg up 0
272 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
271 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
273 $ echo d > d
272 $ echo d > d
274 $ hg ci -Amd
273 $ hg ci -Amd
275 adding d
274 adding d
276 created new head
275 created new head
277
276
278 $ hg up 0
277 $ hg up 0
279 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
278 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
280 $ hg branch test
279 $ hg branch test
281 marked working directory as branch test
280 marked working directory as branch test
282 (branches are permanent and global, did you want a bookmark?)
281 (branches are permanent and global, did you want a bookmark?)
283 $ echo e >> e
282 $ echo e >> e
284 $ hg ci -Ame
283 $ hg ci -Ame
285 adding e
284 adding e
286
285
287 $ hg log
286 $ hg log
288 changeset: 4:3a1e01ed1df4
287 changeset: 4:3a1e01ed1df4
289 branch: test
288 branch: test
290 tag: tip
289 tag: tip
291 parent: 0:cb9a9f314b8b
290 parent: 0:cb9a9f314b8b
292 user: test
291 user: test
293 date: Thu Jan 01 00:00:00 1970 +0000
292 date: Thu Jan 01 00:00:00 1970 +0000
294 summary: e
293 summary: e
295
294
296 changeset: 3:980f7dc84c29
295 changeset: 3:980f7dc84c29
297 parent: 0:cb9a9f314b8b
296 parent: 0:cb9a9f314b8b
298 user: test
297 user: test
299 date: Thu Jan 01 00:00:00 1970 +0000
298 date: Thu Jan 01 00:00:00 1970 +0000
300 summary: d
299 summary: d
301
300
302 changeset: 2:d36c0562f908
301 changeset: 2:d36c0562f908
303 parent: 0:cb9a9f314b8b
302 parent: 0:cb9a9f314b8b
304 user: test
303 user: test
305 date: Thu Jan 01 00:00:00 1970 +0000
304 date: Thu Jan 01 00:00:00 1970 +0000
306 summary: c
305 summary: c
307
306
308 changeset: 1:d2ae7f538514
307 changeset: 1:d2ae7f538514
309 user: test
308 user: test
310 date: Thu Jan 01 00:00:00 1970 +0000
309 date: Thu Jan 01 00:00:00 1970 +0000
311 summary: b
310 summary: b
312
311
313 changeset: 0:cb9a9f314b8b
312 changeset: 0:cb9a9f314b8b
314 user: test
313 user: test
315 date: Thu Jan 01 00:00:00 1970 +0000
314 date: Thu Jan 01 00:00:00 1970 +0000
316 summary: a
315 summary: a
317
316
318 Implicit merge with test branch as parent:
317 Implicit merge with test branch as parent:
319
318
320 $ hg merge
319 $ hg merge
321 abort: branch 'test' has one head - please merge with an explicit rev
320 abort: branch 'test' has one head - please merge with an explicit rev
322 (run 'hg heads' to see all heads)
321 (run 'hg heads' to see all heads)
323 [255]
322 [255]
324 $ hg up -C default
323 $ hg up -C default
325 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
324 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
326
325
327 Implicit merge with default branch as parent:
326 Implicit merge with default branch as parent:
328
327
329 $ hg merge
328 $ hg merge
330 abort: branch 'default' has 3 heads - please merge with an explicit rev
329 abort: branch 'default' has 3 heads - please merge with an explicit rev
331 (run 'hg heads .' to see heads)
330 (run 'hg heads .' to see heads)
332 [255]
331 [255]
333
332
334 3 branch heads, explicit merge required:
333 3 branch heads, explicit merge required:
335
334
336 $ hg merge 2
335 $ hg merge 2
337 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
336 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
338 (branch merge, don't forget to commit)
337 (branch merge, don't forget to commit)
339 $ hg ci -m merge
338 $ hg ci -m merge
340
339
341 2 branch heads, implicit merge works:
340 2 branch heads, implicit merge works:
342
341
343 $ hg merge
342 $ hg merge
344 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
343 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
345 (branch merge, don't forget to commit)
344 (branch merge, don't forget to commit)
346
345
347 $ cd ..
346 $ cd ..
347
348 We expect that bare update on new branch, updates to parent
349
350 $ hg init bareupdateonnewbranch
351 $ cd bareupdateonnewbranch
352 $ hg update
353 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
354 $ touch a
355 $ hg commit -A -m "a"
356 adding a
357 $ touch b
358 $ hg commit -A -m "b"
359 adding b
360 $ touch c
361 $ hg commit -A -m "c"
362 adding c
363 $ hg update -r 1
364 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
365 $ hg log -G
366 o changeset: 2:991a3460af53
367 | tag: tip
368 | user: test
369 | date: Thu Jan 01 00:00:00 1970 +0000
370 | summary: c
371 |
372 @ changeset: 1:0e067c57feba
373 | user: test
374 | date: Thu Jan 01 00:00:00 1970 +0000
375 | summary: b
376 |
377 o changeset: 0:3903775176ed
378 user: test
379 date: Thu Jan 01 00:00:00 1970 +0000
380 summary: a
381
382 $ hg branch dev
383 marked working directory as branch dev
384 (branches are permanent and global, did you want a bookmark?)
385 $ hg update
386 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
387 $ hg summary
388 parent: 1:0e067c57feba
389 b
390 branch: dev
391 commit: (new branch)
392 update: (current)
393 phases: 3 draft
General Comments 0
You need to be logged in to leave comments. Login now