D5940: uncommit: add -f/--force when possibly hiding data (issue5977)
navaneeth.suresh (Navaneeth Suresh)
phabricator at mercurial-scm.org
Mon Feb 11 19:02:07 UTC 2019
navaneeth.suresh created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.
REVISION SUMMARY
The behaviour of uncommit may confuse a new user. Although it never
destroys the data, it can hide instead. I added a `-f/--force` flag
when the working copy is dirty. The data can be visible on `--hidden`
flag.
Some cases in `test-uncommit.t` changes output. I'll be working on
this further based on review.
REPOSITORY
rHG Mercurial
REVISION DETAIL
https://phab.mercurial-scm.org/D5940
AFFECTED FILES
hgext/uncommit.py
mercurial/rewriteutil.py
tests/test-uncommit.t
CHANGE DETAILS
diff --git a/tests/test-uncommit.t b/tests/test-uncommit.t
--- a/tests/test-uncommit.t
+++ b/tests/test-uncommit.t
@@ -35,6 +35,7 @@
options ([+] can be repeated):
--keep allow an empty commit after uncommiting
+ -f --force allow uncommit with outstanding changes
-I --include PATTERN [+] include names matching the given patterns
-X --exclude PATTERN [+] exclude names matching the given patterns
@@ -158,6 +159,9 @@
abort: uncommitted changes
[255]
$ hg uncommit files
+ abort: uncommitted changes
+ (use -f to force)
+ [255]
$ cat files
abcde
foo
@@ -170,14 +174,48 @@
abort: uncommitted changes
[255]
$ hg uncommit --config experimental.uncommitondirtywdir=True
+ abort: uncommitted changes
+ (use -f to force)
+ [255]
$ hg commit -m "files abcde + foo"
Uncommit in the middle of a stack, does not move bookmark
$ hg checkout '.^^^'
- 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
+ 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
(leaving bookmark foo)
$ hg log -r . -p -T '{rev}:{node} {desc}'
+ 3:6db330d65db434145c0b59d291853e9a84719b24 added file-abcddiff -r abf2df566fc1 -r 6db330d65db4 file-abcd
+ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+ +++ b/file-abcd Thu Jan 01 00:00:00 1970 +0000
+ @@ -0,0 +1,1 @@
+ +abcd
+ diff -r abf2df566fc1 -r 6db330d65db4 files
+ --- a/files Thu Jan 01 00:00:00 1970 +0000
+ +++ b/files Thu Jan 01 00:00:00 1970 +0000
+ @@ -1,1 +1,1 @@
+ -abc
+ +abcd
+
+ $ hg bookmark
+ foo 9:ad3773de7293
+ $ hg uncommit
+ 3 new orphan changesets
+ $ hg status
+ M files
+ A file-abcd
+ $ hg heads -T '{rev}:{node} {desc}'
+ 9:ad3773de72930be60f1ebb39fe89115b81630a8a files abcde + foo (no-eol)
+ $ hg bookmark
+ foo 9:ad3773de7293
+ $ hg commit -m 'new abc'
+ created new head
+
+Partial uncommit in the middle, does not move bookmark
+
+ $ hg checkout '.^'
+ 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ hg log -r . -p -T '{rev}:{node} {desc}'
2:abf2df566fc193b3ac34d946e63c1583e4d4732b added file-abcdiff -r 69a232e754b0 -r abf2df566fc1 file-abc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/file-abc Thu Jan 01 00:00:00 1970 +0000
@@ -191,119 +229,85 @@
+abc
$ hg bookmark
- foo 10:48e5bd7cd583
- $ hg uncommit
- 3 new orphan changesets
+ foo 9:ad3773de7293
+ $ hg uncommit file-ab
+ nothing to uncommit
+ [1]
$ hg status
- M files
- A file-abc
- $ hg heads -T '{rev}:{node} {desc}'
- 10:48e5bd7cd583eb24164ef8b89185819c84c96ed7 files abcde + foo (no-eol)
- $ hg bookmark
- foo 10:48e5bd7cd583
- $ hg commit -m 'new abc'
- created new head
-
-Partial uncommit in the middle, does not move bookmark
-
- $ hg checkout '.^'
- 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
- $ hg log -r . -p -T '{rev}:{node} {desc}'
- 1:69a232e754b08d568c4899475faf2eb44b857802 added file-abdiff -r 3004d2d9b508 -r 69a232e754b0 file-ab
- --- /dev/null Thu Jan 01 00:00:00 1970 +0000
- +++ b/file-ab Thu Jan 01 00:00:00 1970 +0000
- @@ -0,0 +1,1 @@
- +ab
- diff -r 3004d2d9b508 -r 69a232e754b0 files
- --- a/files Thu Jan 01 00:00:00 1970 +0000
- +++ b/files Thu Jan 01 00:00:00 1970 +0000
- @@ -1,1 +1,1 @@
- -a
- +ab
-
- $ hg bookmark
- foo 10:48e5bd7cd583
- $ hg uncommit file-ab
- 1 new orphan changesets
- $ hg status
- A file-ab
$ hg heads -T '{rev}:{node} {desc}\n'
- 12:8eb87968f2edb7f27f27fe676316e179de65fff6 added file-ab
- 11:5dc89ca4486f8a88716c5797fa9f498d13d7c2e1 new abc
- 10:48e5bd7cd583eb24164ef8b89185819c84c96ed7 files abcde + foo
+ 10:25798b2f714d0937797be0f9fde55aaf5472c052 new abc
+ 9:ad3773de72930be60f1ebb39fe89115b81630a8a files abcde + foo
$ hg bookmark
- foo 10:48e5bd7cd583
+ foo 9:ad3773de7293
$ hg commit -m 'update ab'
+ nothing changed
+ [1]
$ hg status
$ hg heads -T '{rev}:{node} {desc}\n'
- 13:f21039c59242b085491bb58f591afc4ed1c04c09 update ab
- 11:5dc89ca4486f8a88716c5797fa9f498d13d7c2e1 new abc
- 10:48e5bd7cd583eb24164ef8b89185819c84c96ed7 files abcde + foo
+ 10:25798b2f714d0937797be0f9fde55aaf5472c052 new abc
+ 9:ad3773de72930be60f1ebb39fe89115b81630a8a files abcde + foo
$ hg log -G -T '{rev}:{node} {desc}' --hidden
- @ 13:f21039c59242b085491bb58f591afc4ed1c04c09 update ab
+ o 10:25798b2f714d0937797be0f9fde55aaf5472c052 new abc
|
- o 12:8eb87968f2edb7f27f27fe676316e179de65fff6 added file-ab
- |
- | * 11:5dc89ca4486f8a88716c5797fa9f498d13d7c2e1 new abc
+ | * 9:ad3773de72930be60f1ebb39fe89115b81630a8a files abcde + foo
+ | |
+ | * 8:84beeba0ac30e19521c036e4d2dd3a5fa02586ff files abcde + foo
+ | |
+ | | x 7:0977fa602c2fd7d8427ed4e7ee15ea13b84c9173 update files for abcde
+ | |/
+ | * 6:3727deee06f72f5ffa8db792ee299cf39e3e190b new change abcde
| |
- | | * 10:48e5bd7cd583eb24164ef8b89185819c84c96ed7 files abcde + foo
- | | |
- | | | x 9:8a6b58c173ca6a2e3745d8bd86698718d664bc6c files abcde + foo
- | | |/
- | | | x 8:39ad452c7f684a55d161c574340c5766c4569278 update files for abcde
- | | |/
- | | | x 7:0977fa602c2fd7d8427ed4e7ee15ea13b84c9173 update files for abcde
- | | |/
- | | * 6:3727deee06f72f5ffa8db792ee299cf39e3e190b new change abcde
- | | |
- | | | x 5:0c07a3ccda771b25f1cb1edbd02e683723344ef1 new change abcde
- | | |/
- | | | x 4:6c4fd43ed714e7fcd8adbaa7b16c953c2e985b60 added file-abcde
- | | |/
- | | * 3:6db330d65db434145c0b59d291853e9a84719b24 added file-abcd
- | | |
- | | x 2:abf2df566fc193b3ac34d946e63c1583e4d4732b added file-abc
+ | | x 5:0c07a3ccda771b25f1cb1edbd02e683723344ef1 new change abcde
+ | |/
+ | | x 4:6c4fd43ed714e7fcd8adbaa7b16c953c2e985b60 added file-abcde
| |/
- | x 1:69a232e754b08d568c4899475faf2eb44b857802 added file-ab
+ | x 3:6db330d65db434145c0b59d291853e9a84719b24 added file-abcd
|/
+ @ 2:abf2df566fc193b3ac34d946e63c1583e4d4732b added file-abc
+ |
+ o 1:69a232e754b08d568c4899475faf2eb44b857802 added file-ab
+ |
o 0:3004d2d9b50883c1538fc754a3aeb55f1b4084f6 added file-a
Uncommit with draft parent
$ hg uncommit
+ 1 new orphan changesets
$ hg phase -r .
- 12: draft
+ 1: draft
$ hg commit -m 'update ab again'
+ created new head
Phase is preserved
$ hg uncommit --keep --config phases.new-commit=secret
$ hg phase -r .
- 15: draft
+ 12: draft
$ hg commit --amend -m 'update ab again'
Uncommit with public parent
$ hg phase -p "::.^"
$ hg uncommit
$ hg phase -r .
- 12: public
+ 1: public
Partial uncommit with public parent
$ echo xyz > xyz
$ hg add xyz
$ hg commit -m "update ab and add xyz"
+ created new head
$ hg uncommit xyz
$ hg status
A xyz
$ hg phase -r .
- 18: draft
+ 15: draft
$ hg phase -r ".^"
- 12: public
+ 1: public
Uncommit leaving an empty changeset
@@ -379,7 +383,7 @@
$ hg commit -m 'merge a and b'
$ hg uncommit
- abort: cannot uncommit merge changeset
+ abort: cannot uncommit merge changesets
[255]
$ hg status
@@ -398,3 +402,35 @@
|/
o 0:ea4e33293d4d274a2ba73150733c2612231f398c a 1
+ $ cd ..
+
+Uncommit should require -f/--force when possibly hiding data
+
+ $ hg init issue5977
+ $ cd issue5977
+ $ echo 'super critical info!' > a
+ $ hg ci -Am 'add a'
+ adding a
+ $ echo 'foo' > a
+ $ hg unc a
+ abort: uncommitted changes
+ (use -f to force)
+ [255]
+ $ cat a
+ foo
+ $ hg log
+ changeset: 0:e37b99831f6e
+ tag: tip
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: add a
+
+ $ hg unc -f a
+ $ hg log
+ changeset: 1:656ba143d384
+ tag: tip
+ parent: -1:000000000000
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: add a
+
diff --git a/mercurial/rewriteutil.py b/mercurial/rewriteutil.py
--- a/mercurial/rewriteutil.py
+++ b/mercurial/rewriteutil.py
@@ -16,9 +16,10 @@
revset,
)
-def precheck(repo, revs, action='rewrite'):
+def precheck(repo, revs, action='rewrite', merge=False):
"""check if revs can be rewritten
action is used to control the error message.
+ action is used to true the reject merges.
Make sure this function is called after taking the lock.
"""
@@ -39,6 +40,9 @@
newunstable = disallowednewunstable(repo, revs)
if newunstable:
raise error.Abort(_("cannot %s changeset with children") % action)
+ if merge and any(repo[r].p2() for r in revs):
+ msg = _("cannot %s merge changesets") % (action,)
+ raise error.Abort(msg)
def disallowednewunstable(repo, revs):
"""Checks whether editing the revs will create new unstable changesets and
diff --git a/hgext/uncommit.py b/hgext/uncommit.py
--- a/hgext/uncommit.py
+++ b/hgext/uncommit.py
@@ -137,6 +137,7 @@
@command('uncommit',
[('', 'keep', False, _('allow an empty commit after uncommiting')),
+ ('f', 'force', False, _('allow uncommit with outstanding changes')),
] + commands.walkopts,
_('[OPTION]... [FILE]...'),
helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
@@ -159,12 +160,16 @@
'uncommitondirtywdir'):
cmdutil.bailifchanged(repo)
old = repo['.']
- rewriteutil.precheck(repo, [old.rev()], 'uncommit')
- if len(old.parents()) > 1:
- raise error.Abort(_("cannot uncommit merge changeset"))
+ rewriteutil.precheck(repo, [old.rev()], 'uncommit', merge=True)
+
+ match = scmutil.match(old, pats, opts)
+ # explicitly check for a merge, so it cannot be overridden
+ if old.p2():
+ raise error.Abort(_("outstanding uncommitted merge"))
+ if not opts.get('force'):
+ cmdutil.bailifchanged(repo, hint=_('use -f to force'))
with repo.transaction('uncommit'):
- match = scmutil.match(old, pats, opts)
keepcommit = opts.get('keep') or pats
newid = _commitfiltered(repo, old, match, keepcommit)
if newid is None:
To: navaneeth.suresh, #hg-reviewers
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list