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