##// END OF EJS Templates
uncommit: add support to modify the commit message and date...
Matt Harbison -
r43557:ff1ff2aa default
parent child Browse files
Show More
@@ -1,250 +1,264 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 util,
36 util,
37 )
37 )
38
38
39 cmdtable = {}
39 cmdtable = {}
40 command = registrar.command(cmdtable)
40 command = registrar.command(cmdtable)
41
41
42 configtable = {}
42 configtable = {}
43 configitem = registrar.configitem(configtable)
43 configitem = registrar.configitem(configtable)
44
44
45 configitem('experimental', 'uncommitondirtywdir',
45 configitem('experimental', 'uncommitondirtywdir',
46 default=False,
46 default=False,
47 )
47 )
48 configitem('experimental', 'uncommit.keep',
48 configitem('experimental', 'uncommit.keep',
49 default=False,
49 default=False,
50 )
50 )
51
51
52 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
52 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
53 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
53 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
54 # be specifying the version(s) of Mercurial they are tested with, or
54 # be specifying the version(s) of Mercurial they are tested with, or
55 # leave the attribute unspecified.
55 # leave the attribute unspecified.
56 testedwith = 'ships-with-hg-core'
56 testedwith = 'ships-with-hg-core'
57
57
58 def _commitfiltered(repo, ctx, match, keepcommit):
58 def _commitfiltered(repo, ctx, match, keepcommit, message=None, user=None,
59 date=None):
59 """Recommit ctx with changed files not in match. Return the new
60 """Recommit ctx with changed files not in match. Return the new
60 node identifier, or None if nothing changed.
61 node identifier, or None if nothing changed.
61 """
62 """
62 base = ctx.p1()
63 base = ctx.p1()
63 # ctx
64 # ctx
64 initialfiles = set(ctx.files())
65 initialfiles = set(ctx.files())
65 exclude = set(f for f in initialfiles if match(f))
66 exclude = set(f for f in initialfiles if match(f))
66
67
67 # No files matched commit, so nothing excluded
68 # No files matched commit, so nothing excluded
68 if not exclude:
69 if not exclude:
69 return None
70 return None
70
71
71 # return the p1 so that we don't create an obsmarker later
72 # return the p1 so that we don't create an obsmarker later
72 if not keepcommit:
73 if not keepcommit:
73 return ctx.p1().node()
74 return ctx.p1().node()
74
75
75 files = (initialfiles - exclude)
76 files = (initialfiles - exclude)
76 # Filter copies
77 # Filter copies
77 copied = copiesmod.pathcopies(base, ctx)
78 copied = copiesmod.pathcopies(base, ctx)
78 copied = dict((dst, src) for dst, src in copied.iteritems()
79 copied = dict((dst, src) for dst, src in copied.iteritems()
79 if dst in files)
80 if dst in files)
80 def filectxfn(repo, memctx, path, contentctx=ctx, redirect=()):
81 def filectxfn(repo, memctx, path, contentctx=ctx, redirect=()):
81 if path not in contentctx:
82 if path not in contentctx:
82 return None
83 return None
83 fctx = contentctx[path]
84 fctx = contentctx[path]
84 mctx = context.memfilectx(repo, memctx, fctx.path(), fctx.data(),
85 mctx = context.memfilectx(repo, memctx, fctx.path(), fctx.data(),
85 fctx.islink(),
86 fctx.islink(),
86 fctx.isexec(),
87 fctx.isexec(),
87 copysource=copied.get(path))
88 copysource=copied.get(path))
88 return mctx
89 return mctx
89
90
90 if not files:
91 if not files:
91 repo.ui.status(_("note: keeping empty commit\n"))
92 repo.ui.status(_("note: keeping empty commit\n"))
92
93
94 if message is None:
95 message = ctx.description()
96 if not user:
97 user = ctx.user()
98 if not date:
99 date = ctx.date()
100
93 new = context.memctx(repo,
101 new = context.memctx(repo,
94 parents=[base.node(), node.nullid],
102 parents=[base.node(), node.nullid],
95 text=ctx.description(),
103 text=message,
96 files=files,
104 files=files,
97 filectxfn=filectxfn,
105 filectxfn=filectxfn,
98 user=ctx.user(),
106 user=user,
99 date=ctx.date(),
107 date=date,
100 extra=ctx.extra())
108 extra=ctx.extra())
101 return repo.commitctx(new)
109 return repo.commitctx(new)
102
110
103 @command('uncommit',
111 @command('uncommit',
104 [('', 'keep', None, _('allow an empty commit after uncommiting')),
112 [('', 'keep', None, _('allow an empty commit after uncommiting')),
105 ('', 'allow-dirty-working-copy', False,
113 ('', 'allow-dirty-working-copy', False,
106 _('allow uncommit with outstanding changes'))
114 _('allow uncommit with outstanding changes'))
107 ] + commands.walkopts,
115 ] + commands.walkopts + commands.commitopts + commands.commitopts2,
108 _('[OPTION]... [FILE]...'),
116 _('[OPTION]... [FILE]...'),
109 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
117 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
110 def uncommit(ui, repo, *pats, **opts):
118 def uncommit(ui, repo, *pats, **opts):
111 """uncommit part or all of a local changeset
119 """uncommit part or all of a local changeset
112
120
113 This command undoes the effect of a local commit, returning the affected
121 This command undoes the effect of a local commit, returning the affected
114 files to their uncommitted state. This means that files modified or
122 files to their uncommitted state. This means that files modified or
115 deleted in the changeset will be left unchanged, and so will remain
123 deleted in the changeset will be left unchanged, and so will remain
116 modified in the working directory.
124 modified in the working directory.
117
125
118 If no files are specified, the commit will be pruned, unless --keep is
126 If no files are specified, the commit will be pruned, unless --keep is
119 given.
127 given.
120 """
128 """
121 opts = pycompat.byteskwargs(opts)
129 opts = pycompat.byteskwargs(opts)
122
130
123 with repo.wlock(), repo.lock():
131 with repo.wlock(), repo.lock():
124
132
125 m, a, r, d = repo.status()[:4]
133 m, a, r, d = repo.status()[:4]
126 isdirtypath = any(set(m + a + r + d) & set(pats))
134 isdirtypath = any(set(m + a + r + d) & set(pats))
127 allowdirtywcopy = (opts['allow_dirty_working_copy'] or
135 allowdirtywcopy = (opts['allow_dirty_working_copy'] or
128 repo.ui.configbool('experimental', 'uncommitondirtywdir'))
136 repo.ui.configbool('experimental', 'uncommitondirtywdir'))
129 if not allowdirtywcopy and (not pats or isdirtypath):
137 if not allowdirtywcopy and (not pats or isdirtypath):
130 cmdutil.bailifchanged(repo, hint=_('requires '
138 cmdutil.bailifchanged(repo, hint=_('requires '
131 '--allow-dirty-working-copy to uncommit'))
139 '--allow-dirty-working-copy to uncommit'))
132 old = repo['.']
140 old = repo['.']
133 rewriteutil.precheck(repo, [old.rev()], 'uncommit')
141 rewriteutil.precheck(repo, [old.rev()], 'uncommit')
134 if len(old.parents()) > 1:
142 if len(old.parents()) > 1:
135 raise error.Abort(_("cannot uncommit merge changeset"))
143 raise error.Abort(_("cannot uncommit merge changeset"))
136
144
137 match = scmutil.match(old, pats, opts)
145 match = scmutil.match(old, pats, opts)
138
146
139 # Check all explicitly given files; abort if there's a problem.
147 # Check all explicitly given files; abort if there's a problem.
140 if match.files():
148 if match.files():
141 s = old.status(old.p1(), match, listclean=True)
149 s = old.status(old.p1(), match, listclean=True)
142 eligible = set(s.added) | set(s.modified) | set(s.removed)
150 eligible = set(s.added) | set(s.modified) | set(s.removed)
143
151
144 badfiles = set(match.files()) - eligible
152 badfiles = set(match.files()) - eligible
145
153
146 # Naming a parent directory of an eligible file is OK, even
154 # Naming a parent directory of an eligible file is OK, even
147 # if not everything tracked in that directory can be
155 # if not everything tracked in that directory can be
148 # uncommitted.
156 # uncommitted.
149 if badfiles:
157 if badfiles:
150 badfiles -= {f for f in util.dirs(eligible)}
158 badfiles -= {f for f in util.dirs(eligible)}
151
159
152 for f in sorted(badfiles):
160 for f in sorted(badfiles):
153 if f in s.clean:
161 if f in s.clean:
154 hint = _(b"file was not changed in working directory "
162 hint = _(b"file was not changed in working directory "
155 b"parent")
163 b"parent")
156 elif repo.wvfs.exists(f):
164 elif repo.wvfs.exists(f):
157 hint = _(b"file was untracked in working directory parent")
165 hint = _(b"file was untracked in working directory parent")
158 else:
166 else:
159 hint = _(b"file does not exist")
167 hint = _(b"file does not exist")
160
168
161 raise error.Abort(_(b'cannot uncommit "%s"')
169 raise error.Abort(_(b'cannot uncommit "%s"')
162 % scmutil.getuipathfn(repo)(f), hint=hint)
170 % scmutil.getuipathfn(repo)(f), hint=hint)
163
171
164 with repo.transaction('uncommit'):
172 with repo.transaction('uncommit'):
173 if not (opts[b'message'] or opts[b'logfile']):
174 opts[b'message'] = old.description()
175 message = cmdutil.logmessage(ui, pycompat.byteskwargs(opts))
176
165 keepcommit = pats
177 keepcommit = pats
166 if not keepcommit:
178 if not keepcommit:
167 if opts.get('keep') is not None:
179 if opts.get('keep') is not None:
168 keepcommit = opts.get('keep')
180 keepcommit = opts.get('keep')
169 else:
181 else:
170 keepcommit = ui.configbool('experimental', 'uncommit.keep')
182 keepcommit = ui.configbool('experimental', 'uncommit.keep')
171 newid = _commitfiltered(repo, old, match, keepcommit)
183 newid = _commitfiltered(repo, old, match, keepcommit,
184 message=message, user=opts.get(b'user'),
185 date=opts.get(b'date'))
172 if newid is None:
186 if newid is None:
173 ui.status(_("nothing to uncommit\n"))
187 ui.status(_("nothing to uncommit\n"))
174 return 1
188 return 1
175
189
176 mapping = {}
190 mapping = {}
177 if newid != old.p1().node():
191 if newid != old.p1().node():
178 # Move local changes on filtered changeset
192 # Move local changes on filtered changeset
179 mapping[old.node()] = (newid,)
193 mapping[old.node()] = (newid,)
180 else:
194 else:
181 # Fully removed the old commit
195 # Fully removed the old commit
182 mapping[old.node()] = ()
196 mapping[old.node()] = ()
183
197
184 with repo.dirstate.parentchange():
198 with repo.dirstate.parentchange():
185 scmutil.movedirstate(repo, repo[newid], match)
199 scmutil.movedirstate(repo, repo[newid], match)
186
200
187 scmutil.cleanupnodes(repo, mapping, 'uncommit', fixphase=True)
201 scmutil.cleanupnodes(repo, mapping, 'uncommit', fixphase=True)
188
202
189 def predecessormarkers(ctx):
203 def predecessormarkers(ctx):
190 """yields the obsolete markers marking the given changeset as a successor"""
204 """yields the obsolete markers marking the given changeset as a successor"""
191 for data in ctx.repo().obsstore.predecessors.get(ctx.node(), ()):
205 for data in ctx.repo().obsstore.predecessors.get(ctx.node(), ()):
192 yield obsutil.marker(ctx.repo(), data)
206 yield obsutil.marker(ctx.repo(), data)
193
207
194 @command('unamend', [], helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
208 @command('unamend', [], helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
195 helpbasic=True)
209 helpbasic=True)
196 def unamend(ui, repo, **opts):
210 def unamend(ui, repo, **opts):
197 """undo the most recent amend operation on a current changeset
211 """undo the most recent amend operation on a current changeset
198
212
199 This command will roll back to the previous version of a changeset,
213 This command will roll back to the previous version of a changeset,
200 leaving working directory in state in which it was before running
214 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
215 `hg amend` (e.g. files modified as part of an amend will be
202 marked as modified `hg status`)
216 marked as modified `hg status`)
203 """
217 """
204
218
205 unfi = repo.unfiltered()
219 unfi = repo.unfiltered()
206 with repo.wlock(), repo.lock(), repo.transaction('unamend'):
220 with repo.wlock(), repo.lock(), repo.transaction('unamend'):
207
221
208 # identify the commit from which to unamend
222 # identify the commit from which to unamend
209 curctx = repo['.']
223 curctx = repo['.']
210
224
211 rewriteutil.precheck(repo, [curctx.rev()], 'unamend')
225 rewriteutil.precheck(repo, [curctx.rev()], 'unamend')
212
226
213 # identify the commit to which to unamend
227 # identify the commit to which to unamend
214 markers = list(predecessormarkers(curctx))
228 markers = list(predecessormarkers(curctx))
215 if len(markers) != 1:
229 if len(markers) != 1:
216 e = _("changeset must have one predecessor, found %i predecessors")
230 e = _("changeset must have one predecessor, found %i predecessors")
217 raise error.Abort(e % len(markers))
231 raise error.Abort(e % len(markers))
218
232
219 prednode = markers[0].prednode()
233 prednode = markers[0].prednode()
220 predctx = unfi[prednode]
234 predctx = unfi[prednode]
221
235
222 # add an extra so that we get a new hash
236 # add an extra so that we get a new hash
223 # note: allowing unamend to undo an unamend is an intentional feature
237 # note: allowing unamend to undo an unamend is an intentional feature
224 extras = predctx.extra()
238 extras = predctx.extra()
225 extras['unamend_source'] = curctx.hex()
239 extras['unamend_source'] = curctx.hex()
226
240
227 def filectxfn(repo, ctx_, path):
241 def filectxfn(repo, ctx_, path):
228 try:
242 try:
229 return predctx.filectx(path)
243 return predctx.filectx(path)
230 except KeyError:
244 except KeyError:
231 return None
245 return None
232
246
233 # Make a new commit same as predctx
247 # Make a new commit same as predctx
234 newctx = context.memctx(repo,
248 newctx = context.memctx(repo,
235 parents=(predctx.p1(), predctx.p2()),
249 parents=(predctx.p1(), predctx.p2()),
236 text=predctx.description(),
250 text=predctx.description(),
237 files=predctx.files(),
251 files=predctx.files(),
238 filectxfn=filectxfn,
252 filectxfn=filectxfn,
239 user=predctx.user(),
253 user=predctx.user(),
240 date=predctx.date(),
254 date=predctx.date(),
241 extra=extras)
255 extra=extras)
242 newprednode = repo.commitctx(newctx)
256 newprednode = repo.commitctx(newctx)
243 newpredctx = repo[newprednode]
257 newpredctx = repo[newprednode]
244 dirstate = repo.dirstate
258 dirstate = repo.dirstate
245
259
246 with dirstate.parentchange():
260 with dirstate.parentchange():
247 scmutil.movedirstate(repo, newpredctx)
261 scmutil.movedirstate(repo, newpredctx)
248
262
249 mapping = {curctx.node(): (newprednode,)}
263 mapping = {curctx.node(): (newprednode,)}
250 scmutil.cleanupnodes(repo, mapping, 'unamend', fixphase=True)
264 scmutil.cleanupnodes(repo, mapping, 'unamend', fixphase=True)
@@ -1,571 +1,584 b''
1 Test uncommit - set up the config
1 Test uncommit - set up the config
2
2
3 $ cat >> $HGRCPATH <<EOF
3 $ cat >> $HGRCPATH <<EOF
4 > [experimental]
4 > [experimental]
5 > evolution.createmarkers=True
5 > evolution.createmarkers=True
6 > evolution.allowunstable=True
6 > evolution.allowunstable=True
7 > [extensions]
7 > [extensions]
8 > uncommit =
8 > uncommit =
9 > drawdag=$TESTDIR/drawdag.py
9 > drawdag=$TESTDIR/drawdag.py
10 > EOF
10 > EOF
11
11
12 Build up a repo
12 Build up a repo
13
13
14 $ hg init repo
14 $ hg init repo
15 $ cd repo
15 $ cd repo
16 $ hg bookmark foo
16 $ hg bookmark foo
17
17
18 Help for uncommit
18 Help for uncommit
19
19
20 $ hg help uncommit
20 $ hg help uncommit
21 hg uncommit [OPTION]... [FILE]...
21 hg uncommit [OPTION]... [FILE]...
22
22
23 uncommit part or all of a local changeset
23 uncommit part or all of a local changeset
24
24
25 This command undoes the effect of a local commit, returning the affected
25 This command undoes the effect of a local commit, returning the affected
26 files to their uncommitted state. This means that files modified or
26 files to their uncommitted state. This means that files modified or
27 deleted in the changeset will be left unchanged, and so will remain
27 deleted in the changeset will be left unchanged, and so will remain
28 modified in the working directory.
28 modified in the working directory.
29
29
30 If no files are specified, the commit will be pruned, unless --keep is
30 If no files are specified, the commit will be pruned, unless --keep is
31 given.
31 given.
32
32
33 (use 'hg help -e uncommit' to show help for the uncommit extension)
33 (use 'hg help -e uncommit' to show help for the uncommit extension)
34
34
35 options ([+] can be repeated):
35 options ([+] can be repeated):
36
36
37 --keep allow an empty commit after uncommiting
37 --keep allow an empty commit after uncommiting
38 --allow-dirty-working-copy allow uncommit with outstanding changes
38 --allow-dirty-working-copy allow uncommit with outstanding changes
39 -I --include PATTERN [+] include names matching the given patterns
39 -I --include PATTERN [+] include names matching the given patterns
40 -X --exclude PATTERN [+] exclude names matching the given patterns
40 -X --exclude PATTERN [+] exclude names matching the given patterns
41 -m --message TEXT use text as commit message
42 -l --logfile FILE read commit message from file
43 -d --date DATE record the specified date as commit date
44 -u --user USER record the specified user as committer
41
45
42 (some details hidden, use --verbose to show complete help)
46 (some details hidden, use --verbose to show complete help)
43
47
44 Uncommit with no commits should fail
48 Uncommit with no commits should fail
45
49
46 $ hg uncommit
50 $ hg uncommit
47 abort: cannot uncommit null changeset
51 abort: cannot uncommit null changeset
48 (no changeset checked out)
52 (no changeset checked out)
49 [255]
53 [255]
50
54
51 Create some commits
55 Create some commits
52
56
53 $ touch files
57 $ touch files
54 $ hg add files
58 $ hg add files
55 $ for i in a ab abc abcd abcde; do echo $i > files; echo $i > file-$i; hg add file-$i; hg commit -m "added file-$i"; done
59 $ for i in a ab abc abcd abcde; do echo $i > files; echo $i > file-$i; hg add file-$i; hg commit -m "added file-$i"; done
56 $ ls
60 $ ls
57 file-a
61 file-a
58 file-ab
62 file-ab
59 file-abc
63 file-abc
60 file-abcd
64 file-abcd
61 file-abcde
65 file-abcde
62 files
66 files
63
67
64 $ hg log -G -T '{rev}:{node} {desc}' --hidden
68 $ hg log -G -T '{rev}:{node} {desc}' --hidden
65 @ 4:6c4fd43ed714e7fcd8adbaa7b16c953c2e985b60 added file-abcde
69 @ 4:6c4fd43ed714e7fcd8adbaa7b16c953c2e985b60 added file-abcde
66 |
70 |
67 o 3:6db330d65db434145c0b59d291853e9a84719b24 added file-abcd
71 o 3:6db330d65db434145c0b59d291853e9a84719b24 added file-abcd
68 |
72 |
69 o 2:abf2df566fc193b3ac34d946e63c1583e4d4732b added file-abc
73 o 2:abf2df566fc193b3ac34d946e63c1583e4d4732b added file-abc
70 |
74 |
71 o 1:69a232e754b08d568c4899475faf2eb44b857802 added file-ab
75 o 1:69a232e754b08d568c4899475faf2eb44b857802 added file-ab
72 |
76 |
73 o 0:3004d2d9b50883c1538fc754a3aeb55f1b4084f6 added file-a
77 o 0:3004d2d9b50883c1538fc754a3aeb55f1b4084f6 added file-a
74
78
75 Simple uncommit off the top, also moves bookmark
79 Simple uncommit off the top, also moves bookmark
76
80
77 $ hg bookmark
81 $ hg bookmark
78 * foo 4:6c4fd43ed714
82 * foo 4:6c4fd43ed714
79 $ hg uncommit
83 $ hg uncommit
80 $ hg status
84 $ hg status
81 M files
85 M files
82 A file-abcde
86 A file-abcde
83 $ hg bookmark
87 $ hg bookmark
84 * foo 3:6db330d65db4
88 * foo 3:6db330d65db4
85
89
86 $ hg log -G -T '{rev}:{node} {desc}' --hidden
90 $ hg log -G -T '{rev}:{node} {desc}' --hidden
87 x 4:6c4fd43ed714e7fcd8adbaa7b16c953c2e985b60 added file-abcde
91 x 4:6c4fd43ed714e7fcd8adbaa7b16c953c2e985b60 added file-abcde
88 |
92 |
89 @ 3:6db330d65db434145c0b59d291853e9a84719b24 added file-abcd
93 @ 3:6db330d65db434145c0b59d291853e9a84719b24 added file-abcd
90 |
94 |
91 o 2:abf2df566fc193b3ac34d946e63c1583e4d4732b added file-abc
95 o 2:abf2df566fc193b3ac34d946e63c1583e4d4732b added file-abc
92 |
96 |
93 o 1:69a232e754b08d568c4899475faf2eb44b857802 added file-ab
97 o 1:69a232e754b08d568c4899475faf2eb44b857802 added file-ab
94 |
98 |
95 o 0:3004d2d9b50883c1538fc754a3aeb55f1b4084f6 added file-a
99 o 0:3004d2d9b50883c1538fc754a3aeb55f1b4084f6 added file-a
96
100
97
101
98 Recommit
102 Recommit
99
103
100 $ hg commit -m 'new change abcde'
104 $ hg commit -m 'new change abcde'
101 $ hg status
105 $ hg status
102 $ hg heads -T '{rev}:{node} {desc}'
106 $ hg heads -T '{rev}:{node} {desc}'
103 5:0c07a3ccda771b25f1cb1edbd02e683723344ef1 new change abcde (no-eol)
107 5:0c07a3ccda771b25f1cb1edbd02e683723344ef1 new change abcde (no-eol)
104
108
105 Uncommit of non-existent and unchanged files aborts
109 Uncommit of non-existent and unchanged files aborts
106 $ hg uncommit nothinghere
110 $ hg uncommit nothinghere
107 abort: cannot uncommit "nothinghere"
111 abort: cannot uncommit "nothinghere"
108 (file does not exist)
112 (file does not exist)
109 [255]
113 [255]
110 $ hg status
114 $ hg status
111 $ hg uncommit file-abc
115 $ hg uncommit file-abc
112 abort: cannot uncommit "file-abc"
116 abort: cannot uncommit "file-abc"
113 (file was not changed in working directory parent)
117 (file was not changed in working directory parent)
114 [255]
118 [255]
115 $ hg status
119 $ hg status
116
120
117 Try partial uncommit, also moves bookmark
121 Try partial uncommit, also moves bookmark
118
122
119 $ hg bookmark
123 $ hg bookmark
120 * foo 5:0c07a3ccda77
124 * foo 5:0c07a3ccda77
121 $ hg uncommit files
125 $ hg uncommit files
122 $ hg status
126 $ hg status
123 M files
127 M files
124 $ hg bookmark
128 $ hg bookmark
125 * foo 6:3727deee06f7
129 * foo 6:3727deee06f7
126 $ hg heads -T '{rev}:{node} {desc}'
130 $ hg heads -T '{rev}:{node} {desc}'
127 6:3727deee06f72f5ffa8db792ee299cf39e3e190b new change abcde (no-eol)
131 6:3727deee06f72f5ffa8db792ee299cf39e3e190b new change abcde (no-eol)
128 $ hg log -r . -p -T '{rev}:{node} {desc}'
132 $ hg log -r . -p -T '{rev}:{node} {desc}'
129 6:3727deee06f72f5ffa8db792ee299cf39e3e190b new change abcdediff -r 6db330d65db4 -r 3727deee06f7 file-abcde
133 6:3727deee06f72f5ffa8db792ee299cf39e3e190b new change abcdediff -r 6db330d65db4 -r 3727deee06f7 file-abcde
130 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
134 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
131 +++ b/file-abcde Thu Jan 01 00:00:00 1970 +0000
135 +++ b/file-abcde Thu Jan 01 00:00:00 1970 +0000
132 @@ -0,0 +1,1 @@
136 @@ -0,0 +1,1 @@
133 +abcde
137 +abcde
134
138
135 $ hg log -G -T '{rev}:{node} {desc}' --hidden
139 $ hg log -G -T '{rev}:{node} {desc}' --hidden
136 @ 6:3727deee06f72f5ffa8db792ee299cf39e3e190b new change abcde
140 @ 6:3727deee06f72f5ffa8db792ee299cf39e3e190b new change abcde
137 |
141 |
138 | x 5:0c07a3ccda771b25f1cb1edbd02e683723344ef1 new change abcde
142 | x 5:0c07a3ccda771b25f1cb1edbd02e683723344ef1 new change abcde
139 |/
143 |/
140 | x 4:6c4fd43ed714e7fcd8adbaa7b16c953c2e985b60 added file-abcde
144 | x 4:6c4fd43ed714e7fcd8adbaa7b16c953c2e985b60 added file-abcde
141 |/
145 |/
142 o 3:6db330d65db434145c0b59d291853e9a84719b24 added file-abcd
146 o 3:6db330d65db434145c0b59d291853e9a84719b24 added file-abcd
143 |
147 |
144 o 2:abf2df566fc193b3ac34d946e63c1583e4d4732b added file-abc
148 o 2:abf2df566fc193b3ac34d946e63c1583e4d4732b added file-abc
145 |
149 |
146 o 1:69a232e754b08d568c4899475faf2eb44b857802 added file-ab
150 o 1:69a232e754b08d568c4899475faf2eb44b857802 added file-ab
147 |
151 |
148 o 0:3004d2d9b50883c1538fc754a3aeb55f1b4084f6 added file-a
152 o 0:3004d2d9b50883c1538fc754a3aeb55f1b4084f6 added file-a
149
153
150 $ hg commit -m 'update files for abcde'
154 $ hg commit -m 'update files for abcde'
151
155
152 Uncommit with dirty state
156 Uncommit with dirty state
153
157
154 $ echo "foo" >> files
158 $ echo "foo" >> files
155 $ cat files
159 $ cat files
156 abcde
160 abcde
157 foo
161 foo
158 $ hg status
162 $ hg status
159 M files
163 M files
160 $ hg uncommit
164 $ hg uncommit
161 abort: uncommitted changes
165 abort: uncommitted changes
162 (requires --allow-dirty-working-copy to uncommit)
166 (requires --allow-dirty-working-copy to uncommit)
163 [255]
167 [255]
164 $ hg uncommit files
168 $ hg uncommit files
165 abort: uncommitted changes
169 abort: uncommitted changes
166 (requires --allow-dirty-working-copy to uncommit)
170 (requires --allow-dirty-working-copy to uncommit)
167 [255]
171 [255]
168 $ cat files
172 $ cat files
169 abcde
173 abcde
170 foo
174 foo
171 $ hg commit --amend -m "files abcde + foo"
175 $ hg commit --amend -m "files abcde + foo"
172
176
173 Testing the 'experimental.uncommitondirtywdir' config
177 Testing the 'experimental.uncommitondirtywdir' config
174
178
175 $ echo "bar" >> files
179 $ echo "bar" >> files
176 $ hg uncommit
180 $ hg uncommit
177 abort: uncommitted changes
181 abort: uncommitted changes
178 (requires --allow-dirty-working-copy to uncommit)
182 (requires --allow-dirty-working-copy to uncommit)
179 [255]
183 [255]
180 $ hg uncommit --config experimental.uncommitondirtywdir=True
184 $ hg uncommit --config experimental.uncommitondirtywdir=True
181 $ hg commit -m "files abcde + foo"
185 $ hg commit -m "files abcde + foo"
182
186
183 Uncommit in the middle of a stack, does not move bookmark
187 Uncommit in the middle of a stack, does not move bookmark
184
188
185 $ hg checkout '.^^^'
189 $ hg checkout '.^^^'
186 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
190 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
187 (leaving bookmark foo)
191 (leaving bookmark foo)
188 $ hg log -r . -p -T '{rev}:{node} {desc}'
192 $ hg log -r . -p -T '{rev}:{node} {desc}'
189 2:abf2df566fc193b3ac34d946e63c1583e4d4732b added file-abcdiff -r 69a232e754b0 -r abf2df566fc1 file-abc
193 2:abf2df566fc193b3ac34d946e63c1583e4d4732b added file-abcdiff -r 69a232e754b0 -r abf2df566fc1 file-abc
190 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
194 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
191 +++ b/file-abc Thu Jan 01 00:00:00 1970 +0000
195 +++ b/file-abc Thu Jan 01 00:00:00 1970 +0000
192 @@ -0,0 +1,1 @@
196 @@ -0,0 +1,1 @@
193 +abc
197 +abc
194 diff -r 69a232e754b0 -r abf2df566fc1 files
198 diff -r 69a232e754b0 -r abf2df566fc1 files
195 --- a/files Thu Jan 01 00:00:00 1970 +0000
199 --- a/files Thu Jan 01 00:00:00 1970 +0000
196 +++ b/files Thu Jan 01 00:00:00 1970 +0000
200 +++ b/files Thu Jan 01 00:00:00 1970 +0000
197 @@ -1,1 +1,1 @@
201 @@ -1,1 +1,1 @@
198 -ab
202 -ab
199 +abc
203 +abc
200
204
201 $ hg bookmark
205 $ hg bookmark
202 foo 9:48e5bd7cd583
206 foo 9:48e5bd7cd583
203 $ hg uncommit
207 $ hg uncommit
204 3 new orphan changesets
208 3 new orphan changesets
205 $ hg status
209 $ hg status
206 M files
210 M files
207 A file-abc
211 A file-abc
208 $ hg heads -T '{rev}:{node} {desc}'
212 $ hg heads -T '{rev}:{node} {desc}'
209 9:48e5bd7cd583eb24164ef8b89185819c84c96ed7 files abcde + foo (no-eol)
213 9:48e5bd7cd583eb24164ef8b89185819c84c96ed7 files abcde + foo (no-eol)
210 $ hg bookmark
214 $ hg bookmark
211 foo 9:48e5bd7cd583
215 foo 9:48e5bd7cd583
212 $ hg commit -m 'new abc'
216 $ hg commit -m 'new abc'
213 created new head
217 created new head
214
218
215 Partial uncommit in the middle, does not move bookmark
219 Partial uncommit in the middle, does not move bookmark
216
220
217 $ hg checkout '.^'
221 $ hg checkout '.^'
218 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
222 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
219 $ hg log -r . -p -T '{rev}:{node} {desc}'
223 $ hg log -r . -p -T '{rev}:{node} {desc}'
220 1:69a232e754b08d568c4899475faf2eb44b857802 added file-abdiff -r 3004d2d9b508 -r 69a232e754b0 file-ab
224 1:69a232e754b08d568c4899475faf2eb44b857802 added file-abdiff -r 3004d2d9b508 -r 69a232e754b0 file-ab
221 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
225 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
222 +++ b/file-ab Thu Jan 01 00:00:00 1970 +0000
226 +++ b/file-ab Thu Jan 01 00:00:00 1970 +0000
223 @@ -0,0 +1,1 @@
227 @@ -0,0 +1,1 @@
224 +ab
228 +ab
225 diff -r 3004d2d9b508 -r 69a232e754b0 files
229 diff -r 3004d2d9b508 -r 69a232e754b0 files
226 --- a/files Thu Jan 01 00:00:00 1970 +0000
230 --- a/files Thu Jan 01 00:00:00 1970 +0000
227 +++ b/files Thu Jan 01 00:00:00 1970 +0000
231 +++ b/files Thu Jan 01 00:00:00 1970 +0000
228 @@ -1,1 +1,1 @@
232 @@ -1,1 +1,1 @@
229 -a
233 -a
230 +ab
234 +ab
231
235
232 $ hg bookmark
236 $ hg bookmark
233 foo 9:48e5bd7cd583
237 foo 9:48e5bd7cd583
234 $ hg uncommit file-ab
238 $ hg uncommit file-ab
235 1 new orphan changesets
239 1 new orphan changesets
236 $ hg status
240 $ hg status
237 A file-ab
241 A file-ab
238
242
239 $ hg heads -T '{rev}:{node} {desc}\n'
243 $ hg heads -T '{rev}:{node} {desc}\n'
240 11:8eb87968f2edb7f27f27fe676316e179de65fff6 added file-ab
244 11:8eb87968f2edb7f27f27fe676316e179de65fff6 added file-ab
241 10:5dc89ca4486f8a88716c5797fa9f498d13d7c2e1 new abc
245 10:5dc89ca4486f8a88716c5797fa9f498d13d7c2e1 new abc
242 9:48e5bd7cd583eb24164ef8b89185819c84c96ed7 files abcde + foo
246 9:48e5bd7cd583eb24164ef8b89185819c84c96ed7 files abcde + foo
243
247
244 $ hg bookmark
248 $ hg bookmark
245 foo 9:48e5bd7cd583
249 foo 9:48e5bd7cd583
246 $ hg commit -m 'update ab'
250 $ hg commit -m 'update ab'
247 $ hg status
251 $ hg status
248 $ hg heads -T '{rev}:{node} {desc}\n'
252 $ hg heads -T '{rev}:{node} {desc}\n'
249 12:f21039c59242b085491bb58f591afc4ed1c04c09 update ab
253 12:f21039c59242b085491bb58f591afc4ed1c04c09 update ab
250 10:5dc89ca4486f8a88716c5797fa9f498d13d7c2e1 new abc
254 10:5dc89ca4486f8a88716c5797fa9f498d13d7c2e1 new abc
251 9:48e5bd7cd583eb24164ef8b89185819c84c96ed7 files abcde + foo
255 9:48e5bd7cd583eb24164ef8b89185819c84c96ed7 files abcde + foo
252
256
253 $ hg log -G -T '{rev}:{node} {desc}' --hidden
257 $ hg log -G -T '{rev}:{node} {desc}' --hidden
254 @ 12:f21039c59242b085491bb58f591afc4ed1c04c09 update ab
258 @ 12:f21039c59242b085491bb58f591afc4ed1c04c09 update ab
255 |
259 |
256 o 11:8eb87968f2edb7f27f27fe676316e179de65fff6 added file-ab
260 o 11:8eb87968f2edb7f27f27fe676316e179de65fff6 added file-ab
257 |
261 |
258 | * 10:5dc89ca4486f8a88716c5797fa9f498d13d7c2e1 new abc
262 | * 10:5dc89ca4486f8a88716c5797fa9f498d13d7c2e1 new abc
259 | |
263 | |
260 | | * 9:48e5bd7cd583eb24164ef8b89185819c84c96ed7 files abcde + foo
264 | | * 9:48e5bd7cd583eb24164ef8b89185819c84c96ed7 files abcde + foo
261 | | |
265 | | |
262 | | | x 8:84beeba0ac30e19521c036e4d2dd3a5fa02586ff files abcde + foo
266 | | | x 8:84beeba0ac30e19521c036e4d2dd3a5fa02586ff files abcde + foo
263 | | |/
267 | | |/
264 | | | x 7:0977fa602c2fd7d8427ed4e7ee15ea13b84c9173 update files for abcde
268 | | | x 7:0977fa602c2fd7d8427ed4e7ee15ea13b84c9173 update files for abcde
265 | | |/
269 | | |/
266 | | * 6:3727deee06f72f5ffa8db792ee299cf39e3e190b new change abcde
270 | | * 6:3727deee06f72f5ffa8db792ee299cf39e3e190b new change abcde
267 | | |
271 | | |
268 | | | x 5:0c07a3ccda771b25f1cb1edbd02e683723344ef1 new change abcde
272 | | | x 5:0c07a3ccda771b25f1cb1edbd02e683723344ef1 new change abcde
269 | | |/
273 | | |/
270 | | | x 4:6c4fd43ed714e7fcd8adbaa7b16c953c2e985b60 added file-abcde
274 | | | x 4:6c4fd43ed714e7fcd8adbaa7b16c953c2e985b60 added file-abcde
271 | | |/
275 | | |/
272 | | * 3:6db330d65db434145c0b59d291853e9a84719b24 added file-abcd
276 | | * 3:6db330d65db434145c0b59d291853e9a84719b24 added file-abcd
273 | | |
277 | | |
274 | | x 2:abf2df566fc193b3ac34d946e63c1583e4d4732b added file-abc
278 | | x 2:abf2df566fc193b3ac34d946e63c1583e4d4732b added file-abc
275 | |/
279 | |/
276 | x 1:69a232e754b08d568c4899475faf2eb44b857802 added file-ab
280 | x 1:69a232e754b08d568c4899475faf2eb44b857802 added file-ab
277 |/
281 |/
278 o 0:3004d2d9b50883c1538fc754a3aeb55f1b4084f6 added file-a
282 o 0:3004d2d9b50883c1538fc754a3aeb55f1b4084f6 added file-a
279
283
280 Uncommit with draft parent
284 Uncommit with draft parent
281
285
282 $ hg uncommit
286 $ hg uncommit
283 $ hg phase -r .
287 $ hg phase -r .
284 11: draft
288 11: draft
285 $ hg commit -m 'update ab again'
289 $ hg commit -m 'update ab again'
286
290
287 Phase is preserved
291 Phase is preserved
288
292
289 $ hg uncommit --keep --config phases.new-commit=secret
293 $ hg uncommit --keep --config phases.new-commit=secret
290 note: keeping empty commit
294 note: keeping empty commit
291 $ hg phase -r .
295 $ hg phase -r .
292 14: draft
296 14: draft
293 $ hg commit --amend -m 'update ab again'
297 $ hg commit --amend -m 'update ab again'
294
298
295 Uncommit with public parent
299 Uncommit with public parent
296
300
297 $ hg phase -p "::.^"
301 $ hg phase -p "::.^"
298 $ hg uncommit
302 $ hg uncommit
299 $ hg phase -r .
303 $ hg phase -r .
300 11: public
304 11: public
301
305
302 Partial uncommit with public parent
306 Partial uncommit with public parent
303
307
304 $ echo xyz > xyz
308 $ echo xyz > xyz
305 $ hg add xyz
309 $ hg add xyz
306 $ hg commit -m "update ab and add xyz"
310 $ hg commit -m "update ab and add xyz"
307 $ hg uncommit xyz
311 $ hg uncommit xyz
308 $ hg status
312 $ hg status
309 A xyz
313 A xyz
310 $ hg phase -r .
314 $ hg phase -r .
311 17: draft
315 17: draft
312 $ hg phase -r ".^"
316 $ hg phase -r ".^"
313 11: public
317 11: public
314
318
315 Uncommit with --keep or experimental.uncommit.keep leaves an empty changeset
319 Uncommit with --keep or experimental.uncommit.keep leaves an empty changeset
316
320
317 $ cd $TESTTMP
321 $ cd $TESTTMP
318 $ hg init repo1
322 $ hg init repo1
319 $ cd repo1
323 $ cd repo1
320 $ hg debugdrawdag <<'EOS'
324 $ hg debugdrawdag <<'EOS'
321 > Q
325 > Q
322 > |
326 > |
323 > P
327 > P
324 > EOS
328 > EOS
325 $ hg up Q -q
329 $ hg up Q -q
326 $ hg uncommit --keep
330 $ hg uncommit --keep
327 note: keeping empty commit
331 note: keeping empty commit
328 $ hg log -G -T '{desc} FILES: {files}'
332 $ hg log -G -T '{desc} FILES: {files}'
329 @ Q FILES:
333 @ Q FILES:
330 |
334 |
331 | x Q FILES: Q
335 | x Q FILES: Q
332 |/
336 |/
333 o P FILES: P
337 o P FILES: P
334
338
335 $ cat >> .hg/hgrc <<EOF
339 $ cat >> .hg/hgrc <<EOF
336 > [experimental]
340 > [experimental]
337 > uncommit.keep=True
341 > uncommit.keep=True
338 > EOF
342 > EOF
339 $ hg ci --amend
343 $ hg ci --amend
340 $ hg uncommit
344 $ hg uncommit
341 note: keeping empty commit
345 note: keeping empty commit
342 $ hg log -G -T '{desc} FILES: {files}'
346 $ hg log -G -T '{desc} FILES: {files}'
343 @ Q FILES:
347 @ Q FILES:
344 |
348 |
345 | x Q FILES: Q
349 | x Q FILES: Q
346 |/
350 |/
347 o P FILES: P
351 o P FILES: P
348
352
349 $ hg status
353 $ hg status
350 A Q
354 A Q
351 $ hg ci --amend
355 $ hg ci --amend
352 $ hg uncommit --no-keep
356 $ hg uncommit --no-keep
353 $ hg log -G -T '{desc} FILES: {files}'
357 $ hg log -G -T '{desc} FILES: {files}'
354 x Q FILES: Q
358 x Q FILES: Q
355 |
359 |
356 @ P FILES: P
360 @ P FILES: P
357
361
358 $ hg status
362 $ hg status
359 A Q
363 A Q
360 $ cd ..
364 $ cd ..
361 $ rm -rf repo1
365 $ rm -rf repo1
362
366
363 Testing uncommit while merge
367 Testing uncommit while merge
364
368
365 $ hg init repo2
369 $ hg init repo2
366 $ cd repo2
370 $ cd repo2
367
371
368 Create some history
372 Create some history
369
373
370 $ touch a
374 $ touch a
371 $ hg add a
375 $ hg add a
372 $ for i in 1 2 3; do echo $i > a; hg commit -m "a $i"; done
376 $ for i in 1 2 3; do echo $i > a; hg commit -m "a $i"; done
373 $ hg checkout 0
377 $ hg checkout 0
374 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
378 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
375 $ touch b
379 $ touch b
376 $ hg add b
380 $ hg add b
377 $ for i in 1 2 3; do echo $i > b; hg commit -m "b $i"; done
381 $ for i in 1 2 3; do echo $i > b; hg commit -m "b $i"; done
378 created new head
382 created new head
379 $ hg log -G -T '{rev}:{node} {desc}' --hidden
383 $ hg log -G -T '{rev}:{node} {desc}' --hidden
380 @ 5:2cd56cdde163ded2fbb16ba2f918c96046ab0bf2 b 3
384 @ 5:2cd56cdde163ded2fbb16ba2f918c96046ab0bf2 b 3
381 |
385 |
382 o 4:c3a0d5bb3b15834ffd2ef9ef603e93ec65cf2037 b 2
386 o 4:c3a0d5bb3b15834ffd2ef9ef603e93ec65cf2037 b 2
383 |
387 |
384 o 3:49bb009ca26078726b8870f1edb29fae8f7618f5 b 1
388 o 3:49bb009ca26078726b8870f1edb29fae8f7618f5 b 1
385 |
389 |
386 | o 2:990982b7384266e691f1bc08ca36177adcd1c8a9 a 3
390 | o 2:990982b7384266e691f1bc08ca36177adcd1c8a9 a 3
387 | |
391 | |
388 | o 1:24d38e3cf160c7b6f5ffe82179332229886a6d34 a 2
392 | o 1:24d38e3cf160c7b6f5ffe82179332229886a6d34 a 2
389 |/
393 |/
390 o 0:ea4e33293d4d274a2ba73150733c2612231f398c a 1
394 o 0:ea4e33293d4d274a2ba73150733c2612231f398c a 1
391
395
392
396
393 Add and expect uncommit to fail on both merge working dir and merge changeset
397 Add and expect uncommit to fail on both merge working dir and merge changeset
394
398
395 $ hg merge 2
399 $ hg merge 2
396 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
400 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
397 (branch merge, don't forget to commit)
401 (branch merge, don't forget to commit)
398
402
399 $ hg uncommit
403 $ hg uncommit
400 abort: outstanding uncommitted merge
404 abort: outstanding uncommitted merge
401 (requires --allow-dirty-working-copy to uncommit)
405 (requires --allow-dirty-working-copy to uncommit)
402 [255]
406 [255]
403
407
404 $ hg uncommit --config experimental.uncommitondirtywdir=True
408 $ hg uncommit --config experimental.uncommitondirtywdir=True
405 abort: cannot uncommit while merging
409 abort: cannot uncommit while merging
406 [255]
410 [255]
407
411
408 $ hg status
412 $ hg status
409 M a
413 M a
410 $ hg commit -m 'merge a and b'
414 $ hg commit -m 'merge a and b'
411
415
412 $ hg uncommit
416 $ hg uncommit
413 abort: cannot uncommit merge changeset
417 abort: cannot uncommit merge changeset
414 [255]
418 [255]
415
419
416 $ hg status
420 $ hg status
417 $ hg log -G -T '{rev}:{node} {desc}' --hidden
421 $ hg log -G -T '{rev}:{node} {desc}' --hidden
418 @ 6:c03b9c37bc67bf504d4912061cfb527b47a63c6e merge a and b
422 @ 6:c03b9c37bc67bf504d4912061cfb527b47a63c6e merge a and b
419 |\
423 |\
420 | o 5:2cd56cdde163ded2fbb16ba2f918c96046ab0bf2 b 3
424 | o 5:2cd56cdde163ded2fbb16ba2f918c96046ab0bf2 b 3
421 | |
425 | |
422 | o 4:c3a0d5bb3b15834ffd2ef9ef603e93ec65cf2037 b 2
426 | o 4:c3a0d5bb3b15834ffd2ef9ef603e93ec65cf2037 b 2
423 | |
427 | |
424 | o 3:49bb009ca26078726b8870f1edb29fae8f7618f5 b 1
428 | o 3:49bb009ca26078726b8870f1edb29fae8f7618f5 b 1
425 | |
429 | |
426 o | 2:990982b7384266e691f1bc08ca36177adcd1c8a9 a 3
430 o | 2:990982b7384266e691f1bc08ca36177adcd1c8a9 a 3
427 | |
431 | |
428 o | 1:24d38e3cf160c7b6f5ffe82179332229886a6d34 a 2
432 o | 1:24d38e3cf160c7b6f5ffe82179332229886a6d34 a 2
429 |/
433 |/
430 o 0:ea4e33293d4d274a2ba73150733c2612231f398c a 1
434 o 0:ea4e33293d4d274a2ba73150733c2612231f398c a 1
431
435
432
436
433 Rename a->b, then remove b in working copy. Result should remove a.
437 Rename a->b, then remove b in working copy. Result should remove a.
434
438
435 $ hg co -q 0
439 $ hg co -q 0
436 $ hg mv a b
440 $ hg mv a b
437 $ hg ci -qm 'move a to b'
441 $ hg ci -qm 'move a to b'
438 $ hg rm b
442 $ hg rm b
439 $ hg uncommit --config experimental.uncommitondirtywdir=True
443 $ hg uncommit --config experimental.uncommitondirtywdir=True
440 $ hg st --copies
444 $ hg st --copies
441 R a
445 R a
442 $ hg revert a
446 $ hg revert a
443
447
444 Rename a->b, then rename b->c in working copy. Result should rename a->c.
448 Rename a->b, then rename b->c in working copy. Result should rename a->c.
445
449
446 $ hg co -q 0
450 $ hg co -q 0
447 $ hg mv a b
451 $ hg mv a b
448 $ hg ci -qm 'move a to b'
452 $ hg ci -qm 'move a to b'
449 $ hg mv b c
453 $ hg mv b c
450 $ hg uncommit --config experimental.uncommitondirtywdir=True
454 $ hg uncommit --config experimental.uncommitondirtywdir=True
451 $ hg st --copies
455 $ hg st --copies
452 A c
456 A c
453 a
457 a
454 R a
458 R a
455 $ hg revert a
459 $ hg revert a
456 $ hg forget c
460 $ hg forget c
457 $ rm c
461 $ rm c
458
462
459 Copy a->b1 and a->b2, then rename b1->c in working copy. Result should copy a->b2 and a->c.
463 Copy a->b1 and a->b2, then rename b1->c in working copy. Result should copy a->b2 and a->c.
460
464
461 $ hg co -q 0
465 $ hg co -q 0
462 $ hg cp a b1
466 $ hg cp a b1
463 $ hg cp a b2
467 $ hg cp a b2
464 $ hg ci -qm 'move a to b1 and b2'
468 $ hg ci -qm 'move a to b1 and b2'
465 $ hg mv b1 c
469 $ hg mv b1 c
466 $ hg uncommit --config experimental.uncommitondirtywdir=True
470 $ hg uncommit --config experimental.uncommitondirtywdir=True
467 $ hg st --copies
471 $ hg st --copies
468 A b2
472 A b2
469 a
473 a
470 A c
474 A c
471 a
475 a
472 $ cd ..
476 $ cd ..
473
477
474 --allow-dirty-working-copy should also work on a dirty PATH
478 --allow-dirty-working-copy should also work on a dirty PATH
475
479
476 $ hg init issue5977
480 $ hg init issue5977
477 $ cd issue5977
481 $ cd issue5977
478 $ echo 'super critical info!' > a
482 $ echo 'super critical info!' > a
479 $ hg ci -Am 'add a'
483 $ hg ci -Am 'add a'
480 adding a
484 adding a
481 $ echo 'foo' > b
485 $ echo 'foo' > b
482 $ hg add b
486 $ hg add b
483 $ hg status
487 $ hg status
484 A b
488 A b
485 $ hg unc a
489 $ hg unc a
486 note: keeping empty commit
490 note: keeping empty commit
487 $ cat a
491 $ cat a
488 super critical info!
492 super critical info!
489 $ hg log
493 $ hg log
490 changeset: 1:656ba143d384
494 changeset: 1:656ba143d384
491 tag: tip
495 tag: tip
492 parent: -1:000000000000
496 parent: -1:000000000000
493 user: test
497 user: test
494 date: Thu Jan 01 00:00:00 1970 +0000
498 date: Thu Jan 01 00:00:00 1970 +0000
495 summary: add a
499 summary: add a
496
500
497 $ hg ci -Am 'add b'
501 $ hg ci -Am 'add b'
498 $ echo 'foo bar' > b
502 $ echo 'foo bar' > b
499 $ hg unc b
503 $ hg unc b
500 abort: uncommitted changes
504 abort: uncommitted changes
501 (requires --allow-dirty-working-copy to uncommit)
505 (requires --allow-dirty-working-copy to uncommit)
502 [255]
506 [255]
503 $ hg unc --allow-dirty-working-copy b
507 $ hg unc --allow-dirty-working-copy b
504 $ hg log
508 $ hg log
505 changeset: 3:30fa958635b2
509 changeset: 3:30fa958635b2
506 tag: tip
510 tag: tip
507 parent: 1:656ba143d384
511 parent: 1:656ba143d384
508 user: test
512 user: test
509 date: Thu Jan 01 00:00:00 1970 +0000
513 date: Thu Jan 01 00:00:00 1970 +0000
510 summary: add b
514 summary: add b
511
515
512 changeset: 1:656ba143d384
516 changeset: 1:656ba143d384
513 parent: -1:000000000000
517 parent: -1:000000000000
514 user: test
518 user: test
515 date: Thu Jan 01 00:00:00 1970 +0000
519 date: Thu Jan 01 00:00:00 1970 +0000
516 summary: add a
520 summary: add a
517
521
518 Removes can be uncommitted
522 Removes can be uncommitted
519
523
520 $ hg ci -m 'modified b'
524 $ hg ci -m 'modified b'
521 $ hg rm b
525 $ hg rm b
522 $ hg ci -m 'remove b'
526 $ hg ci -m 'remove b'
523 $ hg uncommit b
527 $ hg uncommit b
524 note: keeping empty commit
528 note: keeping empty commit
525 $ hg status
529 $ hg status
526 R b
530 R b
527
531
528 Uncommitting a directory won't run afoul of the checks that an explicit file
532 Uncommitting a directory won't run afoul of the checks that an explicit file
529 can be uncommitted.
533 can be uncommitted.
530
534
531 $ mkdir dir
535 $ mkdir dir
532 $ echo 1 > dir/file.txt
536 $ echo 1 > dir/file.txt
533 $ hg ci -Aqm 'add file in directory'
537 $ hg ci -Aqm 'add file in directory'
534 $ hg uncommit dir
538 $ hg uncommit dir -m 'uncommit with message' -u 'different user' \
539 > -d 'Jun 30 12:12:12 1980 +0000'
535 $ hg status
540 $ hg status
536 A dir/file.txt
541 A dir/file.txt
542 $ hg log -r .
543 changeset: 8:b4dd26dc42e0
544 tag: tip
545 parent: 6:2278a4c24330
546 user: different user
547 date: Mon Jun 30 12:12:12 1980 +0000
548 summary: uncommit with message
549
537
550
538 `uncommit <dir>` and `cd <dir> && uncommit .` behave the same...
551 `uncommit <dir>` and `cd <dir> && uncommit .` behave the same...
539
552
540 $ hg rollback -q --config ui.rollback=True
553 $ hg rollback -q --config ui.rollback=True
541 $ echo 2 > dir/file2.txt
554 $ echo 2 > dir/file2.txt
542 $ hg ci -Aqm 'add file2 in directory'
555 $ hg ci -Aqm 'add file2 in directory'
543 $ hg uncommit dir
556 $ hg uncommit dir
544 note: keeping empty commit
557 note: keeping empty commit
545 $ hg status
558 $ hg status
546 A dir/file2.txt
559 A dir/file2.txt
547
560
548 $ hg rollback -q --config ui.rollback=True
561 $ hg rollback -q --config ui.rollback=True
549 $ cd dir
562 $ cd dir
550 $ hg uncommit .
563 $ hg uncommit .
551 note: keeping empty commit
564 note: keeping empty commit
552 $ hg status
565 $ hg status
553 A dir/file2.txt
566 A dir/file2.txt
554 $ cd ..
567 $ cd ..
555
568
556 ... and errors out the same way when nothing can be uncommitted
569 ... and errors out the same way when nothing can be uncommitted
557
570
558 $ hg rollback -q --config ui.rollback=True
571 $ hg rollback -q --config ui.rollback=True
559 $ mkdir emptydir
572 $ mkdir emptydir
560 $ hg uncommit emptydir
573 $ hg uncommit emptydir
561 abort: cannot uncommit "emptydir"
574 abort: cannot uncommit "emptydir"
562 (file was untracked in working directory parent)
575 (file was untracked in working directory parent)
563 [255]
576 [255]
564
577
565 $ cd emptydir
578 $ cd emptydir
566 $ hg uncommit .
579 $ hg uncommit .
567 abort: cannot uncommit "emptydir"
580 abort: cannot uncommit "emptydir"
568 (file was untracked in working directory parent)
581 (file was untracked in working directory parent)
569 [255]
582 [255]
570 $ hg status
583 $ hg status
571 $ cd ..
584 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now