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