##// END OF EJS Templates
rebase: skip resolved but emptied revisions...
rebase: skip resolved but emptied revisions When rebasing, if a conflict occurs and is resolved in a way the rebased revision becomes empty, it is not skipped, unlike revisions being emptied without conflicts. The reason is: - File 'x' is merged and resolved, merge.update() marks it as 'm' in the dirstate. - rebase.concludenode() calls localrepo.commit(), which calls localrepo.status() which calls dirstate.status(). 'x' shows up as 'm' and is unconditionnally added to the modified files list, instead of being checked again. - localrepo.commit() detects 'x' as changed an create a new revision where only the manifest parents and linkrev differ. Marking 'x' as modified without checking it makes sense for regular merges. But in rebase case, the merge looks normal but the second parent is usually discarded. When this happens, 'm' files in dirstate are a bit irrelevant and should be considered 'n' possibly dirty instead. That is what the current patch does. Another approach, maybe more efficient, would be to pass another flag to merge.update() saying the 'branchmerge' is a bit of a lie and recordupdate() should call dirstate.normallookup() instead of merge(). It is also tempting to add this logic to dirstate.setparents(), moving from two to one parent is what invalidates the 'm' markers. But this is a far bigger change to make. v2: succumb to the temptation and move the logic in dirstate.setparents(). mpm suggested trying _filecommit() first but it is called by commitctx() which knows nothing about the dirstate and comes too late into the game. A second approach was to rewrite the 'm' state into 'n' on the fly in dirstate.status() which failed for graft in the following case: $ hg init repo $ cd repo $ echo a > a $ hg ci -qAm0 $ echo a >> a $ hg ci -m1 $ hg up 0 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg mv a b $ echo c > b $ hg ci -m2 created new head $ hg graft 1 --tool internal:local grafting revision 1 $ hg --config extensions.graphlog= glog --template '{rev} {desc|firstline}\n' @ 3 1 | o 2 2 | | o 1 1 |/ o 0 0 $ hg log -r 3 --debug --patch --git --copies changeset: 3:19cd7d1417952af13161b94c32e901769104560c tag: tip phase: draft parent: 2:b5c505595c9e9a12d5dd457919c143e05fc16fb8 parent: -1:0000000000000000000000000000000000000000 manifest: 3:3d27ce8d02241aa59b60804805edf103c5c0cda4 user: test date: Thu Jan 01 00:00:00 1970 +0000 extra: branch=default extra: source=a03df74c41413a75c0a42997fc36c2de97b26658 description: 1 Here, revision 3 is created because there is a copy record for 'b' in the dirstate and thus 'b' is considered modified. But this information is discarded at commit time since 'b' content is unchanged. I do not know if discarding this information is correct or not, but at this time we cannot represent it anyway. This patch therefore implements the last solution of moving the logic into dirstate.setparents(). It does not sound crazy as 'm' files makes no sense with only one parent. It also makes dirstate.merge() calls .lookupnormal() if there is one parent, to preserve the invariant. I am a bit concerned about introducing this kind of stateful behaviour to existing code which historically treated setparents() as a basic setter without side-effects. And doing that during the code freeze.

File last commit:

r16509:eab9119c stable
r16509:eab9119c stable
Show More
test-graft.t
277 lines | 6.0 KiB | text/troff | Tads3Lexer
Matt Mackall
graft: add a test
r15361 Create a repo with some stuff in it:
$ hg init a
$ cd a
$ echo a > a
$ echo a > d
$ echo a > e
$ hg ci -qAm0
$ echo b > a
$ hg ci -m1 -u bar
$ hg mv a b
$ hg ci -m2
$ hg cp b c
$ hg ci -m3 -u baz
$ echo b > d
$ echo f > e
$ hg ci -m4
$ hg up -q 3
$ echo b > e
$ hg branch -q stable
$ hg ci -m5
$ hg merge -q default --tool internal:local
$ hg branch -q default
$ hg ci -m6
Alain Leufroy
graft: add test to check the phase of new changesets...
r15918 $ hg phase --public 3
$ hg phase --force --secret 6
$ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
@ test@6.secret: 6
|\
| o test@5.draft: 5
| |
o | test@4.draft: 4
|/
o baz@3.public: 3
|
o test@2.public: 2
|
o bar@1.public: 1
|
o test@0.public: 0
Matt Mackall
graft: add a test
r15361
Need to specify a rev:
$ hg graft
abort: no revisions specified
[255]
Can't graft ancestor:
$ hg graft 1 2
skipping ancestor revision 1
skipping ancestor revision 2
[255]
Can't graft with dirty wd:
$ hg up -q 0
$ echo foo > a
$ hg graft 1
abort: outstanding uncommitted changes
[255]
$ hg revert a
Graft a rename:
$ hg graft 2 -u foo
grafting revision 2
merging a and b to b
$ hg export tip --git
# HG changeset patch
# User foo
# Date 0 0
# Node ID d2e44c99fd3f31c176ea4efb9eca9f6306c81756
# Parent 68795b066622ca79a25816a662041d8f78f3cd9e
2
diff --git a/a b/b
rename from a
rename to b
--- a/a
+++ b/b
@@ -1,1 +1,1 @@
-a
+b
Look for extra:source
$ hg log --debug -r tip
changeset: 7:d2e44c99fd3f31c176ea4efb9eca9f6306c81756
tag: tip
Pierre-Yves David
changeset_printer: display changeset phase on debug level...
r15907 phase: draft
Matt Mackall
graft: add a test
r15361 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
parent: -1:0000000000000000000000000000000000000000
manifest: 7:5d59766436fd8fbcd38e7bebef0f6eaf3eebe637
user: foo
date: Thu Jan 01 00:00:00 1970 +0000
files+: b
files-: a
extra: branch=default
extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
description:
2
Graft out of order, skipping a merge and a duplicate
Matt Mackall
graft: add --dry-run support (issue3362)
r16389 $ hg graft 1 5 4 3 'merge()' 2 -n
skipping ungraftable merge revision 6
skipping already grafted revision 2
grafting revision 1
grafting revision 5
grafting revision 4
grafting revision 3
Matt Mackall
graft: add a test
r15361 $ hg graft 1 5 4 3 'merge()' 2 --debug
skipping ungraftable merge revision 6
scanning for duplicate grafts
skipping already grafted revision 2
grafting revision 1
searching for copies back to rev 1
unmatched files in local:
b
all copies found (* = to merge, ! = divergent):
b -> a *
checking for directory renames
resolving manifests
Martin Geisler
merge: make debug output easier to read...
r15625 overwrite: False, partial: False
ancestor: 68795b066622, local: d2e44c99fd3f+, remote: 5d205f8b35b6
Matt Mackall
graft: add a test
r15361 b: local copied/moved to a -> m
preserving b for resolve of b
updating: b 1/1 files (100.00%)
grafting revision 5
searching for copies back to rev 1
resolving manifests
Martin Geisler
merge: make debug output easier to read...
r15625 overwrite: False, partial: False
Patrick Mezard
rebase: skip resolved but emptied revisions...
r16509 ancestor: 4c60f11aa304, local: d2e44c99fd3f+, remote: 97f8bfe72746
Matt Mackall
graft: add a test
r15361 e: remote is newer -> g
updating: e 1/1 files (100.00%)
getting e
e
grafting revision 4
searching for copies back to rev 1
resolving manifests
Martin Geisler
merge: make debug output easier to read...
r15625 overwrite: False, partial: False
Patrick Mezard
rebase: skip resolved but emptied revisions...
r16509 ancestor: 4c60f11aa304, local: 839a7e8fcf80+, remote: 9c233e8e184d
Matt Mackall
graft: add a test
r15361 e: versions differ -> m
d: remote is newer -> g
preserving e for resolve of e
updating: d 1/2 files (50.00%)
getting d
updating: e 2/2 files (100.00%)
picked tool 'internal:merge' for e (binary False symlink False)
merging e
Patrick Mezard
rebase: skip resolved but emptied revisions...
r16509 my e@839a7e8fcf80+ other e@9c233e8e184d ancestor e@68795b066622
Matt Mackall
graft: add a test
r15361 warning: conflicts during merge.
Matt Mackall
merge: give a special message for internal:merge failure (issue3105)
r15501 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
Matt Mackall
graft: add a test
r15361 abort: unresolved conflicts, can't continue
(use hg resolve and hg graft --continue)
[255]
Continue without resolve should fail:
$ hg graft -c
grafting revision 4
abort: unresolved merge conflicts (see hg help resolve)
[255]
Fix up:
$ echo b > e
$ hg resolve -m e
Continue with a revision should fail:
$ hg graft -c 6
abort: can't specify --continue and revisions
[255]
Continue for real, clobber usernames
$ hg graft -c -U
grafting revision 4
grafting revision 3
Compare with original:
$ hg diff -r 6
$ hg status --rev 0:. -C
M d
M e
A b
a
A c
a
R a
View graph:
Alain Leufroy
graft: add test to check the phase of new changesets...
r15918 $ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
Patrick Mezard
rebase: skip resolved but emptied revisions...
r16509 @ test@10.draft: 3
Matt Mackall
graft: add a test
r15361 |
Patrick Mezard
rebase: skip resolved but emptied revisions...
r16509 o test@9.draft: 4
Matt Mackall
graft: add a test
r15361 |
Patrick Mezard
rebase: skip resolved but emptied revisions...
r16509 o test@8.draft: 5
Matt Mackall
graft: add a test
r15361 |
Alain Leufroy
graft: add test to check the phase of new changesets...
r15918 o foo@7.draft: 2
Matt Mackall
graft: add a test
r15361 |
Alain Leufroy
graft: add test to check the phase of new changesets...
r15918 | o test@6.secret: 6
Matt Mackall
graft: add a test
r15361 | |\
Alain Leufroy
graft: add test to check the phase of new changesets...
r15918 | | o test@5.draft: 5
Matt Mackall
graft: add a test
r15361 | | |
Alain Leufroy
graft: add test to check the phase of new changesets...
r15918 | o | test@4.draft: 4
Matt Mackall
graft: add a test
r15361 | |/
Alain Leufroy
graft: add test to check the phase of new changesets...
r15918 | o baz@3.public: 3
Matt Mackall
graft: add a test
r15361 | |
Alain Leufroy
graft: add test to check the phase of new changesets...
r15918 | o test@2.public: 2
Matt Mackall
graft: add a test
r15361 | |
Alain Leufroy
graft: add test to check the phase of new changesets...
r15918 | o bar@1.public: 1
Matt Mackall
graft: add a test
r15361 |/
Alain Leufroy
graft: add test to check the phase of new changesets...
r15918 o test@0.public: 0
Matt Mackall
graft: add a test
r15361
Stefano Tortarolo
graft: preserve original source in subsequent grafts
r15506 Graft again onto another branch should preserve the original source
$ hg up -q 0
$ echo 'g'>g
$ hg add g
$ hg ci -m 7
created new head
$ hg graft 7
grafting revision 7
$ hg log -r 7 --template '{rev}:{node}\n'
7:d2e44c99fd3f31c176ea4efb9eca9f6306c81756
$ hg log -r 2 --template '{rev}:{node}\n'
2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
$ hg log --debug -r tip
Patrick Mezard
rebase: skip resolved but emptied revisions...
r16509 changeset: 12:95adbe5de6b10f376b699ece9ed5a57cd7b4b0f6
Stefano Tortarolo
graft: preserve original source in subsequent grafts
r15506 tag: tip
Pierre-Yves David
changeset_printer: display changeset phase on debug level...
r15907 phase: draft
Patrick Mezard
rebase: skip resolved but emptied revisions...
r16509 parent: 11:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
Stefano Tortarolo
graft: preserve original source in subsequent grafts
r15506 parent: -1:0000000000000000000000000000000000000000
Patrick Mezard
rebase: skip resolved but emptied revisions...
r16509 manifest: 12:9944044f82a462bbaccc9bdf7e0ac5b811db7d1b
Stefano Tortarolo
graft: preserve original source in subsequent grafts
r15506 user: foo
date: Thu Jan 01 00:00:00 1970 +0000
files+: b
files-: a
extra: branch=default
extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
description:
2
Stefano Tortarolo
graft: disallow grafting grafted csets in specific situations (issue3091)...
r15508 Disallow grafting an already grafted cset onto its original branch
$ hg up -q 6
$ hg graft 7
skipping already grafted revision 7 (was grafted from 2)
[255]
Disallow grafting already grafted csets with the same origin onto each other
Patrick Mezard
rebase: skip resolved but emptied revisions...
r16509 $ hg up -q 12
Stefano Tortarolo
graft: disallow grafting grafted csets in specific situations (issue3091)...
r15508 $ hg graft 2
skipping already grafted revision 2
[255]
$ hg graft 7
skipping already grafted revision 7 (same origin 2)
[255]
$ hg up -q 7
$ hg graft 2
skipping already grafted revision 2
[255]
$ hg graft tip
Patrick Mezard
rebase: skip resolved but emptied revisions...
r16509 skipping already grafted revision 12 (same origin 2)
Stefano Tortarolo
graft: disallow grafting grafted csets in specific situations (issue3091)...
r15508 [255]