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