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