##// END OF EJS Templates
unamend: error out when running on merge commit...
Martin von Zweigbergk -
r49517:4f01821f stable
parent child Browse files
Show More
@@ -1,316 +1,318 b''
1 # uncommit - undo the actions of a commit
1 # uncommit - undo the actions of a commit
2 #
2 #
3 # Copyright 2011 Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
3 # Copyright 2011 Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
4 # Logilab SA <contact@logilab.fr>
4 # Logilab SA <contact@logilab.fr>
5 # Pierre-Yves David <pierre-yves.david@ens-lyon.org>
5 # Pierre-Yves David <pierre-yves.david@ens-lyon.org>
6 # Patrick Mezard <patrick@mezard.eu>
6 # Patrick Mezard <patrick@mezard.eu>
7 # Copyright 2016 Facebook, Inc.
7 # Copyright 2016 Facebook, Inc.
8 #
8 #
9 # This software may be used and distributed according to the terms of the
9 # This software may be used and distributed according to the terms of the
10 # GNU General Public License version 2 or any later version.
10 # GNU General Public License version 2 or any later version.
11
11
12 """uncommit part or all of a local changeset (EXPERIMENTAL)
12 """uncommit part or all of a local changeset (EXPERIMENTAL)
13
13
14 This command undoes the effect of a local commit, returning the affected
14 This command undoes the effect of a local commit, returning the affected
15 files to their uncommitted state. This means that files modified, added or
15 files to their uncommitted state. This means that files modified, added or
16 removed in the changeset will be left unchanged, and so will remain modified,
16 removed in the changeset will be left unchanged, and so will remain modified,
17 added and removed in the working directory.
17 added and removed in the working directory.
18 """
18 """
19
19
20 from __future__ import absolute_import
20 from __future__ import absolute_import
21
21
22 from mercurial.i18n import _
22 from mercurial.i18n import _
23
23
24 from mercurial import (
24 from mercurial import (
25 cmdutil,
25 cmdutil,
26 commands,
26 commands,
27 context,
27 context,
28 copies as copiesmod,
28 copies as copiesmod,
29 error,
29 error,
30 obsutil,
30 obsutil,
31 pathutil,
31 pathutil,
32 pycompat,
32 pycompat,
33 registrar,
33 registrar,
34 rewriteutil,
34 rewriteutil,
35 scmutil,
35 scmutil,
36 )
36 )
37
37
38 cmdtable = {}
38 cmdtable = {}
39 command = registrar.command(cmdtable)
39 command = registrar.command(cmdtable)
40
40
41 configtable = {}
41 configtable = {}
42 configitem = registrar.configitem(configtable)
42 configitem = registrar.configitem(configtable)
43
43
44 configitem(
44 configitem(
45 b'experimental',
45 b'experimental',
46 b'uncommitondirtywdir',
46 b'uncommitondirtywdir',
47 default=False,
47 default=False,
48 )
48 )
49 configitem(
49 configitem(
50 b'experimental',
50 b'experimental',
51 b'uncommit.keep',
51 b'uncommit.keep',
52 default=False,
52 default=False,
53 )
53 )
54
54
55 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
55 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
56 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
56 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
57 # be specifying the version(s) of Mercurial they are tested with, or
57 # be specifying the version(s) of Mercurial they are tested with, or
58 # leave the attribute unspecified.
58 # leave the attribute unspecified.
59 testedwith = b'ships-with-hg-core'
59 testedwith = b'ships-with-hg-core'
60
60
61
61
62 def _commitfiltered(
62 def _commitfiltered(
63 repo, ctx, match, keepcommit, message=None, user=None, date=None
63 repo, ctx, match, keepcommit, message=None, user=None, date=None
64 ):
64 ):
65 """Recommit ctx with changed files not in match. Return the new
65 """Recommit ctx with changed files not in match. Return the new
66 node identifier, or None if nothing changed.
66 node identifier, or None if nothing changed.
67 """
67 """
68 base = ctx.p1()
68 base = ctx.p1()
69 # ctx
69 # ctx
70 initialfiles = set(ctx.files())
70 initialfiles = set(ctx.files())
71 exclude = {f for f in initialfiles if match(f)}
71 exclude = {f for f in initialfiles if match(f)}
72
72
73 # No files matched commit, so nothing excluded
73 # No files matched commit, so nothing excluded
74 if not exclude:
74 if not exclude:
75 return None
75 return None
76
76
77 # return the p1 so that we don't create an obsmarker later
77 # return the p1 so that we don't create an obsmarker later
78 if not keepcommit:
78 if not keepcommit:
79 return ctx.p1().node()
79 return ctx.p1().node()
80
80
81 files = initialfiles - exclude
81 files = initialfiles - exclude
82 # Filter copies
82 # Filter copies
83 copied = copiesmod.pathcopies(base, ctx)
83 copied = copiesmod.pathcopies(base, ctx)
84 copied = {
84 copied = {
85 dst: src for dst, src in pycompat.iteritems(copied) if dst in files
85 dst: src for dst, src in pycompat.iteritems(copied) if dst in files
86 }
86 }
87
87
88 def filectxfn(repo, memctx, path, contentctx=ctx, redirect=()):
88 def filectxfn(repo, memctx, path, contentctx=ctx, redirect=()):
89 if path not in contentctx:
89 if path not in contentctx:
90 return None
90 return None
91 fctx = contentctx[path]
91 fctx = contentctx[path]
92 mctx = context.memfilectx(
92 mctx = context.memfilectx(
93 repo,
93 repo,
94 memctx,
94 memctx,
95 fctx.path(),
95 fctx.path(),
96 fctx.data(),
96 fctx.data(),
97 fctx.islink(),
97 fctx.islink(),
98 fctx.isexec(),
98 fctx.isexec(),
99 copysource=copied.get(path),
99 copysource=copied.get(path),
100 )
100 )
101 return mctx
101 return mctx
102
102
103 if not files:
103 if not files:
104 repo.ui.status(_(b"note: keeping empty commit\n"))
104 repo.ui.status(_(b"note: keeping empty commit\n"))
105
105
106 if message is None:
106 if message is None:
107 message = ctx.description()
107 message = ctx.description()
108 if not user:
108 if not user:
109 user = ctx.user()
109 user = ctx.user()
110 if not date:
110 if not date:
111 date = ctx.date()
111 date = ctx.date()
112
112
113 new = context.memctx(
113 new = context.memctx(
114 repo,
114 repo,
115 parents=[base.node(), repo.nullid],
115 parents=[base.node(), repo.nullid],
116 text=message,
116 text=message,
117 files=files,
117 files=files,
118 filectxfn=filectxfn,
118 filectxfn=filectxfn,
119 user=user,
119 user=user,
120 date=date,
120 date=date,
121 extra=ctx.extra(),
121 extra=ctx.extra(),
122 )
122 )
123 return repo.commitctx(new)
123 return repo.commitctx(new)
124
124
125
125
126 @command(
126 @command(
127 b'uncommit',
127 b'uncommit',
128 [
128 [
129 (b'', b'keep', None, _(b'allow an empty commit after uncommitting')),
129 (b'', b'keep', None, _(b'allow an empty commit after uncommitting')),
130 (
130 (
131 b'',
131 b'',
132 b'allow-dirty-working-copy',
132 b'allow-dirty-working-copy',
133 False,
133 False,
134 _(b'allow uncommit with outstanding changes'),
134 _(b'allow uncommit with outstanding changes'),
135 ),
135 ),
136 (b'n', b'note', b'', _(b'store a note on uncommit'), _(b'TEXT')),
136 (b'n', b'note', b'', _(b'store a note on uncommit'), _(b'TEXT')),
137 ]
137 ]
138 + commands.walkopts
138 + commands.walkopts
139 + commands.commitopts
139 + commands.commitopts
140 + commands.commitopts2
140 + commands.commitopts2
141 + commands.commitopts3,
141 + commands.commitopts3,
142 _(b'[OPTION]... [FILE]...'),
142 _(b'[OPTION]... [FILE]...'),
143 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
143 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
144 )
144 )
145 def uncommit(ui, repo, *pats, **opts):
145 def uncommit(ui, repo, *pats, **opts):
146 """uncommit part or all of a local changeset
146 """uncommit part or all of a local changeset
147
147
148 This command undoes the effect of a local commit, returning the affected
148 This command undoes the effect of a local commit, returning the affected
149 files to their uncommitted state. This means that files modified or
149 files to their uncommitted state. This means that files modified or
150 deleted in the changeset will be left unchanged, and so will remain
150 deleted in the changeset will be left unchanged, and so will remain
151 modified in the working directory.
151 modified in the working directory.
152
152
153 If no files are specified, the commit will be pruned, unless --keep is
153 If no files are specified, the commit will be pruned, unless --keep is
154 given.
154 given.
155 """
155 """
156 cmdutil.check_note_size(opts)
156 cmdutil.check_note_size(opts)
157 cmdutil.resolve_commit_options(ui, opts)
157 cmdutil.resolve_commit_options(ui, opts)
158 opts = pycompat.byteskwargs(opts)
158 opts = pycompat.byteskwargs(opts)
159
159
160 with repo.wlock(), repo.lock():
160 with repo.wlock(), repo.lock():
161
161
162 st = repo.status()
162 st = repo.status()
163 m, a, r, d = st.modified, st.added, st.removed, st.deleted
163 m, a, r, d = st.modified, st.added, st.removed, st.deleted
164 isdirtypath = any(set(m + a + r + d) & set(pats))
164 isdirtypath = any(set(m + a + r + d) & set(pats))
165 allowdirtywcopy = opts[
165 allowdirtywcopy = opts[
166 b'allow_dirty_working_copy'
166 b'allow_dirty_working_copy'
167 ] or repo.ui.configbool(b'experimental', b'uncommitondirtywdir')
167 ] or repo.ui.configbool(b'experimental', b'uncommitondirtywdir')
168 if not allowdirtywcopy and (not pats or isdirtypath):
168 if not allowdirtywcopy and (not pats or isdirtypath):
169 cmdutil.bailifchanged(
169 cmdutil.bailifchanged(
170 repo,
170 repo,
171 hint=_(b'requires --allow-dirty-working-copy to uncommit'),
171 hint=_(b'requires --allow-dirty-working-copy to uncommit'),
172 )
172 )
173 old = repo[b'.']
173 old = repo[b'.']
174 rewriteutil.precheck(repo, [old.rev()], b'uncommit')
174 rewriteutil.precheck(repo, [old.rev()], b'uncommit')
175 if len(old.parents()) > 1:
175 if len(old.parents()) > 1:
176 raise error.InputError(_(b"cannot uncommit merge changeset"))
176 raise error.InputError(_(b"cannot uncommit merge changeset"))
177
177
178 match = scmutil.match(old, pats, opts)
178 match = scmutil.match(old, pats, opts)
179
179
180 # Check all explicitly given files; abort if there's a problem.
180 # Check all explicitly given files; abort if there's a problem.
181 if match.files():
181 if match.files():
182 s = old.status(old.p1(), match, listclean=True)
182 s = old.status(old.p1(), match, listclean=True)
183 eligible = set(s.added) | set(s.modified) | set(s.removed)
183 eligible = set(s.added) | set(s.modified) | set(s.removed)
184
184
185 badfiles = set(match.files()) - eligible
185 badfiles = set(match.files()) - eligible
186
186
187 # Naming a parent directory of an eligible file is OK, even
187 # Naming a parent directory of an eligible file is OK, even
188 # if not everything tracked in that directory can be
188 # if not everything tracked in that directory can be
189 # uncommitted.
189 # uncommitted.
190 if badfiles:
190 if badfiles:
191 badfiles -= {f for f in pathutil.dirs(eligible)}
191 badfiles -= {f for f in pathutil.dirs(eligible)}
192
192
193 for f in sorted(badfiles):
193 for f in sorted(badfiles):
194 if f in s.clean:
194 if f in s.clean:
195 hint = _(
195 hint = _(
196 b"file was not changed in working directory parent"
196 b"file was not changed in working directory parent"
197 )
197 )
198 elif repo.wvfs.exists(f):
198 elif repo.wvfs.exists(f):
199 hint = _(b"file was untracked in working directory parent")
199 hint = _(b"file was untracked in working directory parent")
200 else:
200 else:
201 hint = _(b"file does not exist")
201 hint = _(b"file does not exist")
202
202
203 raise error.InputError(
203 raise error.InputError(
204 _(b'cannot uncommit "%s"') % scmutil.getuipathfn(repo)(f),
204 _(b'cannot uncommit "%s"') % scmutil.getuipathfn(repo)(f),
205 hint=hint,
205 hint=hint,
206 )
206 )
207
207
208 with repo.transaction(b'uncommit'):
208 with repo.transaction(b'uncommit'):
209 if not (opts[b'message'] or opts[b'logfile']):
209 if not (opts[b'message'] or opts[b'logfile']):
210 opts[b'message'] = old.description()
210 opts[b'message'] = old.description()
211 message = cmdutil.logmessage(ui, opts)
211 message = cmdutil.logmessage(ui, opts)
212
212
213 keepcommit = pats
213 keepcommit = pats
214 if not keepcommit:
214 if not keepcommit:
215 if opts.get(b'keep') is not None:
215 if opts.get(b'keep') is not None:
216 keepcommit = opts.get(b'keep')
216 keepcommit = opts.get(b'keep')
217 else:
217 else:
218 keepcommit = ui.configbool(
218 keepcommit = ui.configbool(
219 b'experimental', b'uncommit.keep'
219 b'experimental', b'uncommit.keep'
220 )
220 )
221 newid = _commitfiltered(
221 newid = _commitfiltered(
222 repo,
222 repo,
223 old,
223 old,
224 match,
224 match,
225 keepcommit,
225 keepcommit,
226 message=message,
226 message=message,
227 user=opts.get(b'user'),
227 user=opts.get(b'user'),
228 date=opts.get(b'date'),
228 date=opts.get(b'date'),
229 )
229 )
230 if newid is None:
230 if newid is None:
231 ui.status(_(b"nothing to uncommit\n"))
231 ui.status(_(b"nothing to uncommit\n"))
232 return 1
232 return 1
233
233
234 mapping = {}
234 mapping = {}
235 if newid != old.p1().node():
235 if newid != old.p1().node():
236 # Move local changes on filtered changeset
236 # Move local changes on filtered changeset
237 mapping[old.node()] = (newid,)
237 mapping[old.node()] = (newid,)
238 else:
238 else:
239 # Fully removed the old commit
239 # Fully removed the old commit
240 mapping[old.node()] = ()
240 mapping[old.node()] = ()
241
241
242 with repo.dirstate.parentchange():
242 with repo.dirstate.parentchange():
243 scmutil.movedirstate(repo, repo[newid], match)
243 scmutil.movedirstate(repo, repo[newid], match)
244
244
245 scmutil.cleanupnodes(repo, mapping, b'uncommit', fixphase=True)
245 scmutil.cleanupnodes(repo, mapping, b'uncommit', fixphase=True)
246
246
247
247
248 def predecessormarkers(ctx):
248 def predecessormarkers(ctx):
249 """yields the obsolete markers marking the given changeset as a successor"""
249 """yields the obsolete markers marking the given changeset as a successor"""
250 for data in ctx.repo().obsstore.predecessors.get(ctx.node(), ()):
250 for data in ctx.repo().obsstore.predecessors.get(ctx.node(), ()):
251 yield obsutil.marker(ctx.repo(), data)
251 yield obsutil.marker(ctx.repo(), data)
252
252
253
253
254 @command(
254 @command(
255 b'unamend',
255 b'unamend',
256 [],
256 [],
257 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
257 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
258 helpbasic=True,
258 helpbasic=True,
259 )
259 )
260 def unamend(ui, repo, **opts):
260 def unamend(ui, repo, **opts):
261 """undo the most recent amend operation on a current changeset
261 """undo the most recent amend operation on a current changeset
262
262
263 This command will roll back to the previous version of a changeset,
263 This command will roll back to the previous version of a changeset,
264 leaving working directory in state in which it was before running
264 leaving working directory in state in which it was before running
265 `hg amend` (e.g. files modified as part of an amend will be
265 `hg amend` (e.g. files modified as part of an amend will be
266 marked as modified `hg status`)
266 marked as modified `hg status`)
267 """
267 """
268
268
269 unfi = repo.unfiltered()
269 unfi = repo.unfiltered()
270 with repo.wlock(), repo.lock(), repo.transaction(b'unamend'):
270 with repo.wlock(), repo.lock(), repo.transaction(b'unamend'):
271
271
272 # identify the commit from which to unamend
272 # identify the commit from which to unamend
273 curctx = repo[b'.']
273 curctx = repo[b'.']
274
274
275 rewriteutil.precheck(repo, [curctx.rev()], b'unamend')
275 rewriteutil.precheck(repo, [curctx.rev()], b'unamend')
276 if len(curctx.parents()) > 1:
277 raise error.InputError(_(b"cannot unamend merge changeset"))
276
278
277 # identify the commit to which to unamend
279 # identify the commit to which to unamend
278 markers = list(predecessormarkers(curctx))
280 markers = list(predecessormarkers(curctx))
279 if len(markers) != 1:
281 if len(markers) != 1:
280 e = _(b"changeset must have one predecessor, found %i predecessors")
282 e = _(b"changeset must have one predecessor, found %i predecessors")
281 raise error.InputError(e % len(markers))
283 raise error.InputError(e % len(markers))
282
284
283 prednode = markers[0].prednode()
285 prednode = markers[0].prednode()
284 predctx = unfi[prednode]
286 predctx = unfi[prednode]
285
287
286 # add an extra so that we get a new hash
288 # add an extra so that we get a new hash
287 # note: allowing unamend to undo an unamend is an intentional feature
289 # note: allowing unamend to undo an unamend is an intentional feature
288 extras = predctx.extra()
290 extras = predctx.extra()
289 extras[b'unamend_source'] = curctx.hex()
291 extras[b'unamend_source'] = curctx.hex()
290
292
291 def filectxfn(repo, ctx_, path):
293 def filectxfn(repo, ctx_, path):
292 try:
294 try:
293 return predctx.filectx(path)
295 return predctx.filectx(path)
294 except KeyError:
296 except KeyError:
295 return None
297 return None
296
298
297 # Make a new commit same as predctx
299 # Make a new commit same as predctx
298 newctx = context.memctx(
300 newctx = context.memctx(
299 repo,
301 repo,
300 parents=(predctx.p1(), predctx.p2()),
302 parents=(predctx.p1(), predctx.p2()),
301 text=predctx.description(),
303 text=predctx.description(),
302 files=predctx.files(),
304 files=predctx.files(),
303 filectxfn=filectxfn,
305 filectxfn=filectxfn,
304 user=predctx.user(),
306 user=predctx.user(),
305 date=predctx.date(),
307 date=predctx.date(),
306 extra=extras,
308 extra=extras,
307 )
309 )
308 newprednode = repo.commitctx(newctx)
310 newprednode = repo.commitctx(newctx)
309 newpredctx = repo[newprednode]
311 newpredctx = repo[newprednode]
310 dirstate = repo.dirstate
312 dirstate = repo.dirstate
311
313
312 with dirstate.parentchange():
314 with dirstate.parentchange():
313 scmutil.movedirstate(repo, newpredctx)
315 scmutil.movedirstate(repo, newpredctx)
314
316
315 mapping = {curctx.node(): (newprednode,)}
317 mapping = {curctx.node(): (newprednode,)}
316 scmutil.cleanupnodes(repo, mapping, b'unamend', fixphase=True)
318 scmutil.cleanupnodes(repo, mapping, b'unamend', fixphase=True)
@@ -1,450 +1,447 b''
1 Test for command `hg unamend` which lives in uncommit extension
1 Test for command `hg unamend` which lives in uncommit extension
2 ===============================================================
2 ===============================================================
3
3
4 $ cat >> $HGRCPATH << EOF
4 $ cat >> $HGRCPATH << EOF
5 > [alias]
5 > [alias]
6 > glog = log -G -T '{rev}:{node|short} {desc}'
6 > glog = log -G -T '{rev}:{node|short} {desc}'
7 > [experimental]
7 > [experimental]
8 > evolution = createmarkers, allowunstable
8 > evolution = createmarkers, allowunstable
9 > evolution.allowdivergence = true
9 > evolution.allowdivergence = true
10 > [extensions]
10 > [extensions]
11 > rebase =
11 > rebase =
12 > amend =
12 > amend =
13 > uncommit =
13 > uncommit =
14 > EOF
14 > EOF
15
15
16 Repo Setup
16 Repo Setup
17
17
18 $ hg init repo
18 $ hg init repo
19 $ cd repo
19 $ cd repo
20 $ for ch in a b c d e f g h; do touch $ch; echo "foo" >> $ch; hg ci -Aqm "Added "$ch; done
20 $ for ch in a b c d e f g h; do touch $ch; echo "foo" >> $ch; hg ci -Aqm "Added "$ch; done
21
21
22 $ hg glog
22 $ hg glog
23 @ 7:ec2426147f0e Added h
23 @ 7:ec2426147f0e Added h
24 |
24 |
25 o 6:87d6d6676308 Added g
25 o 6:87d6d6676308 Added g
26 |
26 |
27 o 5:825660c69f0c Added f
27 o 5:825660c69f0c Added f
28 |
28 |
29 o 4:aa98ab95a928 Added e
29 o 4:aa98ab95a928 Added e
30 |
30 |
31 o 3:62615734edd5 Added d
31 o 3:62615734edd5 Added d
32 |
32 |
33 o 2:28ad74487de9 Added c
33 o 2:28ad74487de9 Added c
34 |
34 |
35 o 1:29becc82797a Added b
35 o 1:29becc82797a Added b
36 |
36 |
37 o 0:18d04c59bb5d Added a
37 o 0:18d04c59bb5d Added a
38
38
39 Trying to unamend when there was no amend done
39 Trying to unamend when there was no amend done
40
40
41 $ hg unamend
41 $ hg unamend
42 abort: changeset must have one predecessor, found 0 predecessors
42 abort: changeset must have one predecessor, found 0 predecessors
43 [10]
43 [10]
44
44
45 Unamend on clean wdir and tip
45 Unamend on clean wdir and tip
46
46
47 $ echo "bar" >> h
47 $ echo "bar" >> h
48 $ hg amend
48 $ hg amend
49
49
50 $ hg exp
50 $ hg exp
51 # HG changeset patch
51 # HG changeset patch
52 # User test
52 # User test
53 # Date 0 0
53 # Date 0 0
54 # Thu Jan 01 00:00:00 1970 +0000
54 # Thu Jan 01 00:00:00 1970 +0000
55 # Node ID c9fa1a715c1b7661c0fafb362a9f30bd75878d7d
55 # Node ID c9fa1a715c1b7661c0fafb362a9f30bd75878d7d
56 # Parent 87d6d66763085b629e6d7ed56778c79827273022
56 # Parent 87d6d66763085b629e6d7ed56778c79827273022
57 Added h
57 Added h
58
58
59 diff -r 87d6d6676308 -r c9fa1a715c1b h
59 diff -r 87d6d6676308 -r c9fa1a715c1b h
60 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
60 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
61 +++ b/h Thu Jan 01 00:00:00 1970 +0000
61 +++ b/h Thu Jan 01 00:00:00 1970 +0000
62 @@ -0,0 +1,2 @@
62 @@ -0,0 +1,2 @@
63 +foo
63 +foo
64 +bar
64 +bar
65
65
66 $ hg glog --hidden
66 $ hg glog --hidden
67 @ 8:c9fa1a715c1b Added h
67 @ 8:c9fa1a715c1b Added h
68 |
68 |
69 | x 7:ec2426147f0e Added h
69 | x 7:ec2426147f0e Added h
70 |/
70 |/
71 o 6:87d6d6676308 Added g
71 o 6:87d6d6676308 Added g
72 |
72 |
73 o 5:825660c69f0c Added f
73 o 5:825660c69f0c Added f
74 |
74 |
75 o 4:aa98ab95a928 Added e
75 o 4:aa98ab95a928 Added e
76 |
76 |
77 o 3:62615734edd5 Added d
77 o 3:62615734edd5 Added d
78 |
78 |
79 o 2:28ad74487de9 Added c
79 o 2:28ad74487de9 Added c
80 |
80 |
81 o 1:29becc82797a Added b
81 o 1:29becc82797a Added b
82 |
82 |
83 o 0:18d04c59bb5d Added a
83 o 0:18d04c59bb5d Added a
84
84
85 $ hg unamend
85 $ hg unamend
86 $ hg glog --hidden
86 $ hg glog --hidden
87 @ 9:46d02d47eec6 Added h
87 @ 9:46d02d47eec6 Added h
88 |
88 |
89 | x 8:c9fa1a715c1b Added h
89 | x 8:c9fa1a715c1b Added h
90 |/
90 |/
91 | x 7:ec2426147f0e Added h
91 | x 7:ec2426147f0e Added h
92 |/
92 |/
93 o 6:87d6d6676308 Added g
93 o 6:87d6d6676308 Added g
94 |
94 |
95 o 5:825660c69f0c Added f
95 o 5:825660c69f0c Added f
96 |
96 |
97 o 4:aa98ab95a928 Added e
97 o 4:aa98ab95a928 Added e
98 |
98 |
99 o 3:62615734edd5 Added d
99 o 3:62615734edd5 Added d
100 |
100 |
101 o 2:28ad74487de9 Added c
101 o 2:28ad74487de9 Added c
102 |
102 |
103 o 1:29becc82797a Added b
103 o 1:29becc82797a Added b
104 |
104 |
105 o 0:18d04c59bb5d Added a
105 o 0:18d04c59bb5d Added a
106
106
107 $ hg diff
107 $ hg diff
108 diff -r 46d02d47eec6 h
108 diff -r 46d02d47eec6 h
109 --- a/h Thu Jan 01 00:00:00 1970 +0000
109 --- a/h Thu Jan 01 00:00:00 1970 +0000
110 +++ b/h Thu Jan 01 00:00:00 1970 +0000
110 +++ b/h Thu Jan 01 00:00:00 1970 +0000
111 @@ -1,1 +1,2 @@
111 @@ -1,1 +1,2 @@
112 foo
112 foo
113 +bar
113 +bar
114
114
115 $ hg exp
115 $ hg exp
116 # HG changeset patch
116 # HG changeset patch
117 # User test
117 # User test
118 # Date 0 0
118 # Date 0 0
119 # Thu Jan 01 00:00:00 1970 +0000
119 # Thu Jan 01 00:00:00 1970 +0000
120 # Node ID 46d02d47eec6ca096b8dcab3f8f5579c40c3dd9a
120 # Node ID 46d02d47eec6ca096b8dcab3f8f5579c40c3dd9a
121 # Parent 87d6d66763085b629e6d7ed56778c79827273022
121 # Parent 87d6d66763085b629e6d7ed56778c79827273022
122 Added h
122 Added h
123
123
124 diff -r 87d6d6676308 -r 46d02d47eec6 h
124 diff -r 87d6d6676308 -r 46d02d47eec6 h
125 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
125 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
126 +++ b/h Thu Jan 01 00:00:00 1970 +0000
126 +++ b/h Thu Jan 01 00:00:00 1970 +0000
127 @@ -0,0 +1,1 @@
127 @@ -0,0 +1,1 @@
128 +foo
128 +foo
129
129
130 $ hg status
130 $ hg status
131 M h
131 M h
132
132
133 $ hg log -r . -T '{extras % "{extra}\n"}' --config alias.log=log
133 $ hg log -r . -T '{extras % "{extra}\n"}' --config alias.log=log
134 branch=default
134 branch=default
135 unamend_source=c9fa1a715c1b7661c0fafb362a9f30bd75878d7d
135 unamend_source=c9fa1a715c1b7661c0fafb362a9f30bd75878d7d
136
136
137 Using unamend to undo an unamed (intentional)
137 Using unamend to undo an unamed (intentional)
138
138
139 $ hg unamend
139 $ hg unamend
140 $ hg exp
140 $ hg exp
141 # HG changeset patch
141 # HG changeset patch
142 # User test
142 # User test
143 # Date 0 0
143 # Date 0 0
144 # Thu Jan 01 00:00:00 1970 +0000
144 # Thu Jan 01 00:00:00 1970 +0000
145 # Node ID 850ddfc1bc662997ec6094ada958f01f0cc8070a
145 # Node ID 850ddfc1bc662997ec6094ada958f01f0cc8070a
146 # Parent 87d6d66763085b629e6d7ed56778c79827273022
146 # Parent 87d6d66763085b629e6d7ed56778c79827273022
147 Added h
147 Added h
148
148
149 diff -r 87d6d6676308 -r 850ddfc1bc66 h
149 diff -r 87d6d6676308 -r 850ddfc1bc66 h
150 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
150 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
151 +++ b/h Thu Jan 01 00:00:00 1970 +0000
151 +++ b/h Thu Jan 01 00:00:00 1970 +0000
152 @@ -0,0 +1,2 @@
152 @@ -0,0 +1,2 @@
153 +foo
153 +foo
154 +bar
154 +bar
155 $ hg diff
155 $ hg diff
156
156
157 Unamend on a dirty working directory
157 Unamend on a dirty working directory
158
158
159 $ echo "bar" >> a
159 $ echo "bar" >> a
160 $ hg amend
160 $ hg amend
161 $ echo "foobar" >> a
161 $ echo "foobar" >> a
162 $ echo "bar" >> b
162 $ echo "bar" >> b
163 $ hg status
163 $ hg status
164 M a
164 M a
165 M b
165 M b
166
166
167 $ hg unamend
167 $ hg unamend
168
168
169 $ hg status
169 $ hg status
170 M a
170 M a
171 M b
171 M b
172
172
173 $ hg diff
173 $ hg diff
174 diff -r ec338db45d51 a
174 diff -r ec338db45d51 a
175 --- a/a Thu Jan 01 00:00:00 1970 +0000
175 --- a/a Thu Jan 01 00:00:00 1970 +0000
176 +++ b/a Thu Jan 01 00:00:00 1970 +0000
176 +++ b/a Thu Jan 01 00:00:00 1970 +0000
177 @@ -1,1 +1,3 @@
177 @@ -1,1 +1,3 @@
178 foo
178 foo
179 +bar
179 +bar
180 +foobar
180 +foobar
181 diff -r ec338db45d51 b
181 diff -r ec338db45d51 b
182 --- a/b Thu Jan 01 00:00:00 1970 +0000
182 --- a/b Thu Jan 01 00:00:00 1970 +0000
183 +++ b/b Thu Jan 01 00:00:00 1970 +0000
183 +++ b/b Thu Jan 01 00:00:00 1970 +0000
184 @@ -1,1 +1,2 @@
184 @@ -1,1 +1,2 @@
185 foo
185 foo
186 +bar
186 +bar
187
187
188 Unamending an added file
188 Unamending an added file
189
189
190 $ hg ci -m "Added things to a and b"
190 $ hg ci -m "Added things to a and b"
191 $ echo foo > bar
191 $ echo foo > bar
192 $ hg add bar
192 $ hg add bar
193 $ hg amend
193 $ hg amend
194
194
195 $ hg unamend
195 $ hg unamend
196 $ hg status
196 $ hg status
197 A bar
197 A bar
198
198
199 $ hg revert --all
199 $ hg revert --all
200 forgetting bar
200 forgetting bar
201
201
202 Unamending a removed file
202 Unamending a removed file
203
203
204 $ hg remove a
204 $ hg remove a
205 $ hg amend
205 $ hg amend
206
206
207 $ hg unamend
207 $ hg unamend
208 $ hg status
208 $ hg status
209 R a
209 R a
210 ? bar
210 ? bar
211
211
212 $ hg revert --all
212 $ hg revert --all
213 undeleting a
213 undeleting a
214
214
215 Unamending an added file with dirty wdir status
215 Unamending an added file with dirty wdir status
216
216
217 $ hg add bar
217 $ hg add bar
218 $ hg amend
218 $ hg amend
219 $ echo bar >> bar
219 $ echo bar >> bar
220 $ hg status
220 $ hg status
221 M bar
221 M bar
222
222
223 $ hg unamend
223 $ hg unamend
224 $ hg status
224 $ hg status
225 A bar
225 A bar
226 $ hg diff
226 $ hg diff
227 diff -r 7f79409af972 bar
227 diff -r 7f79409af972 bar
228 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
228 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
229 +++ b/bar Thu Jan 01 00:00:00 1970 +0000
229 +++ b/bar Thu Jan 01 00:00:00 1970 +0000
230 @@ -0,0 +1,2 @@
230 @@ -0,0 +1,2 @@
231 +foo
231 +foo
232 +bar
232 +bar
233
233
234 $ hg revert --all
234 $ hg revert --all
235 forgetting bar
235 forgetting bar
236 $ rm bar
236 $ rm bar
237
237
238 Unamending in middle of a stack
238 Unamending in middle of a stack
239
239
240 $ hg glog
240 $ hg glog
241 @ 19:7f79409af972 Added things to a and b
241 @ 19:7f79409af972 Added things to a and b
242 |
242 |
243 o 12:ec338db45d51 Added h
243 o 12:ec338db45d51 Added h
244 |
244 |
245 o 6:87d6d6676308 Added g
245 o 6:87d6d6676308 Added g
246 |
246 |
247 o 5:825660c69f0c Added f
247 o 5:825660c69f0c Added f
248 |
248 |
249 o 4:aa98ab95a928 Added e
249 o 4:aa98ab95a928 Added e
250 |
250 |
251 o 3:62615734edd5 Added d
251 o 3:62615734edd5 Added d
252 |
252 |
253 o 2:28ad74487de9 Added c
253 o 2:28ad74487de9 Added c
254 |
254 |
255 o 1:29becc82797a Added b
255 o 1:29becc82797a Added b
256 |
256 |
257 o 0:18d04c59bb5d Added a
257 o 0:18d04c59bb5d Added a
258
258
259 $ hg up 5
259 $ hg up 5
260 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
260 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
261 $ echo bar >> f
261 $ echo bar >> f
262 $ hg amend
262 $ hg amend
263 3 new orphan changesets
263 3 new orphan changesets
264 $ hg rebase -s 6 -d . -q
264 $ hg rebase -s 6 -d . -q
265
265
266 $ hg glog
266 $ hg glog
267 o 23:03ddd6fc5af1 Added things to a and b
267 o 23:03ddd6fc5af1 Added things to a and b
268 |
268 |
269 o 22:3e7b64ee157b Added h
269 o 22:3e7b64ee157b Added h
270 |
270 |
271 o 21:49635b68477e Added g
271 o 21:49635b68477e Added g
272 |
272 |
273 @ 20:93f0e8ffab32 Added f
273 @ 20:93f0e8ffab32 Added f
274 |
274 |
275 o 4:aa98ab95a928 Added e
275 o 4:aa98ab95a928 Added e
276 |
276 |
277 o 3:62615734edd5 Added d
277 o 3:62615734edd5 Added d
278 |
278 |
279 o 2:28ad74487de9 Added c
279 o 2:28ad74487de9 Added c
280 |
280 |
281 o 1:29becc82797a Added b
281 o 1:29becc82797a Added b
282 |
282 |
283 o 0:18d04c59bb5d Added a
283 o 0:18d04c59bb5d Added a
284
284
285
285
286 $ hg --config experimental.evolution=createmarkers unamend
286 $ hg --config experimental.evolution=createmarkers unamend
287 abort: cannot unamend changeset, as that will orphan 3 descendants
287 abort: cannot unamend changeset, as that will orphan 3 descendants
288 (see 'hg help evolution.instability')
288 (see 'hg help evolution.instability')
289 [10]
289 [10]
290
290
291 $ hg unamend
291 $ hg unamend
292 3 new orphan changesets
292 3 new orphan changesets
293
293
294 Trying to unamend a public changeset
294 Trying to unamend a public changeset
295
295
296 $ hg up -C 23
296 $ hg up -C 23
297 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
297 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
298 $ hg phase -r . -p
298 $ hg phase -r . -p
299 1 new phase-divergent changesets
299 1 new phase-divergent changesets
300 $ hg unamend
300 $ hg unamend
301 abort: cannot unamend public changesets: 03ddd6fc5af1
301 abort: cannot unamend public changesets: 03ddd6fc5af1
302 (see 'hg help phases' for details)
302 (see 'hg help phases' for details)
303 [10]
303 [10]
304
304
305 Testing whether unamend retains copies or not
305 Testing whether unamend retains copies or not
306
306
307 $ hg status
307 $ hg status
308
308
309 $ hg mv a foo
309 $ hg mv a foo
310
310
311 $ hg ci -m "Moved a to foo"
311 $ hg ci -m "Moved a to foo"
312 $ hg exp --git
312 $ hg exp --git
313 # HG changeset patch
313 # HG changeset patch
314 # User test
314 # User test
315 # Date 0 0
315 # Date 0 0
316 # Thu Jan 01 00:00:00 1970 +0000
316 # Thu Jan 01 00:00:00 1970 +0000
317 # Node ID cfef290346fbee5126313d7e1aab51d877679b09
317 # Node ID cfef290346fbee5126313d7e1aab51d877679b09
318 # Parent 03ddd6fc5af19e028c44a2fd6d790dd22712f231
318 # Parent 03ddd6fc5af19e028c44a2fd6d790dd22712f231
319 Moved a to foo
319 Moved a to foo
320
320
321 diff --git a/a b/foo
321 diff --git a/a b/foo
322 rename from a
322 rename from a
323 rename to foo
323 rename to foo
324
324
325 $ hg mv b foobar
325 $ hg mv b foobar
326 $ hg diff --git
326 $ hg diff --git
327 diff --git a/b b/foobar
327 diff --git a/b b/foobar
328 rename from b
328 rename from b
329 rename to foobar
329 rename to foobar
330 $ hg amend
330 $ hg amend
331
331
332 $ hg exp --git
332 $ hg exp --git
333 # HG changeset patch
333 # HG changeset patch
334 # User test
334 # User test
335 # Date 0 0
335 # Date 0 0
336 # Thu Jan 01 00:00:00 1970 +0000
336 # Thu Jan 01 00:00:00 1970 +0000
337 # Node ID eca050985275bb271ce3092b54e56ea5c85d29a3
337 # Node ID eca050985275bb271ce3092b54e56ea5c85d29a3
338 # Parent 03ddd6fc5af19e028c44a2fd6d790dd22712f231
338 # Parent 03ddd6fc5af19e028c44a2fd6d790dd22712f231
339 Moved a to foo
339 Moved a to foo
340
340
341 diff --git a/a b/foo
341 diff --git a/a b/foo
342 rename from a
342 rename from a
343 rename to foo
343 rename to foo
344 diff --git a/b b/foobar
344 diff --git a/b b/foobar
345 rename from b
345 rename from b
346 rename to foobar
346 rename to foobar
347
347
348 $ hg mv c wat
348 $ hg mv c wat
349 $ hg unamend
349 $ hg unamend
350
350
351 $ hg verify -v
351 $ hg verify -v
352 repository uses revlog format 1
352 repository uses revlog format 1
353 checking changesets
353 checking changesets
354 checking manifests
354 checking manifests
355 crosschecking files in changesets and manifests
355 crosschecking files in changesets and manifests
356 checking files
356 checking files
357 checked 28 changesets with 16 changes to 11 files
357 checked 28 changesets with 16 changes to 11 files
358
358
359 Retained copies in new prdecessor commit
359 Retained copies in new prdecessor commit
360
360
361 $ hg exp --git
361 $ hg exp --git
362 # HG changeset patch
362 # HG changeset patch
363 # User test
363 # User test
364 # Date 0 0
364 # Date 0 0
365 # Thu Jan 01 00:00:00 1970 +0000
365 # Thu Jan 01 00:00:00 1970 +0000
366 # Node ID 552e3af4f01f620f88ca27be1f898316235b736a
366 # Node ID 552e3af4f01f620f88ca27be1f898316235b736a
367 # Parent 03ddd6fc5af19e028c44a2fd6d790dd22712f231
367 # Parent 03ddd6fc5af19e028c44a2fd6d790dd22712f231
368 Moved a to foo
368 Moved a to foo
369
369
370 diff --git a/a b/foo
370 diff --git a/a b/foo
371 rename from a
371 rename from a
372 rename to foo
372 rename to foo
373
373
374 Retained copies in working directoy
374 Retained copies in working directoy
375
375
376 $ hg diff --git
376 $ hg diff --git
377 diff --git a/b b/foobar
377 diff --git a/b b/foobar
378 rename from b
378 rename from b
379 rename to foobar
379 rename to foobar
380 diff --git a/c b/wat
380 diff --git a/c b/wat
381 rename from c
381 rename from c
382 rename to wat
382 rename to wat
383 $ hg revert -qa
383 $ hg revert -qa
384 $ rm foobar wat
384 $ rm foobar wat
385
385
386 Rename a->b, then amend b->c. After unamend, should look like b->c.
386 Rename a->b, then amend b->c. After unamend, should look like b->c.
387
387
388 $ hg co -q 0
388 $ hg co -q 0
389 $ hg mv a b
389 $ hg mv a b
390 $ hg ci -qm 'move to a b'
390 $ hg ci -qm 'move to a b'
391 $ hg mv b c
391 $ hg mv b c
392 $ hg amend
392 $ hg amend
393 $ hg unamend
393 $ hg unamend
394 $ hg st --copies --change .
394 $ hg st --copies --change .
395 A b
395 A b
396 a
396 a
397 R a
397 R a
398 $ hg st --copies
398 $ hg st --copies
399 A c
399 A c
400 b
400 b
401 R b
401 R b
402 $ hg revert -qa
402 $ hg revert -qa
403 $ rm c
403 $ rm c
404
404
405 Rename a->b, then amend b->c, and working copy change c->d. After unamend, should look like b->d
405 Rename a->b, then amend b->c, and working copy change c->d. After unamend, should look like b->d
406
406
407 $ hg co -q 0
407 $ hg co -q 0
408 $ hg mv a b
408 $ hg mv a b
409 $ hg ci -qm 'move to a b'
409 $ hg ci -qm 'move to a b'
410 warning: commit already existed in the repository!
410 warning: commit already existed in the repository!
411 $ hg mv b c
411 $ hg mv b c
412 $ hg amend
412 $ hg amend
413 warning: commit already existed in the repository!
413 warning: commit already existed in the repository!
414 $ hg mv c d
414 $ hg mv c d
415 $ hg unamend
415 $ hg unamend
416 $ hg st --copies --change .
416 $ hg st --copies --change .
417 A b
417 A b
418 a
418 a
419 R a
419 R a
420 $ hg st --copies
420 $ hg st --copies
421 A d
421 A d
422 b
422 b
423 R b
423 R b
424
424
425 Try to unamend a merge
425 Try to unamend a merge
426
426
427 $ cd ..
427 $ cd ..
428 $ hg init merge
428 $ hg init merge
429 $ cd merge
429 $ cd merge
430 $ echo initial > initial
430 $ echo initial > initial
431 $ hg ci -Aqm initial
431 $ hg ci -Aqm initial
432 $ echo left > left
432 $ echo left > left
433 $ hg ci -Aqm left
433 $ hg ci -Aqm left
434 $ hg co -q 0
434 $ hg co -q 0
435 $ echo right > right
435 $ echo right > right
436 $ hg ci -Aqm right
436 $ hg ci -Aqm right
437 $ hg merge -q 1
437 $ hg merge -q 1
438 $ hg ci -m merge
438 $ hg ci -m merge
439 $ echo accidental > initial
439 $ echo accidental > initial
440 $ hg st --rev 1 --rev .
440 $ hg st --rev 1 --rev .
441 A right
441 A right
442 $ hg st --rev 2 --rev .
442 $ hg st --rev 2 --rev .
443 A left
443 A left
444 $ hg amend
444 $ hg amend
445 $ hg unamend
445 $ hg unamend
446 $ hg st --rev 1 --rev .
446 abort: cannot unamend merge changeset
447 A right
447 [10]
448 R left (known-bad-output !)
449 $ hg st --rev 2 --rev .
450 A left (missing-correct-output !)
General Comments 0
You need to be logged in to leave comments. Login now