http://bugs.grommit.com/show_bug.cgi?id=347
Summary: recommit can strip local changes in such a way as to
corrupt the manifest
Product: SCM Migration
Version: unspecified
Platform: All
OS/Version: Solaris 11/Nevada
Status: NEW
Severity: blocker
Priority: P1
Component: cdm
AssignedTo: scm-migration-dev at opensolaris.org
ReportedBy: richlowe at richlowe.net
Bart had a completely linear workspace, with a change he intended to putback.
Someone else made a change in the gate he had to merge with, leaving
him like this.
Before Merge After
*
|\
* | *
* | * |
| | -> | |
|/ |/
* *
| |
Then he recommitted with the old Hg, which failed (because Hg was old)
and left his workspace at the new rev from the gate.
At this point his change was linear, merge-turd free, and totally the
right thing. Except Bart didn't know that...
He thought his change had vanished (it hadn't), and restored it.
Which left him like this:
* <- Bart's change from the first recommit
|
* <- change from gate
Bart's change again -> * |
| |
|/
*
|
Which left him with two heads again, so he merged again:
Before Merge After
*
|\
* | *
| | |
* -> | *
* | * |
| | | |
|/ |/
* *
| |
So, at this point we have Bart's change, twice, a random change, and a
merge (+ (Bart's change) (+ (Bart's change) (random change)))
Recommit does this:
Takes those outgoing changes, commits them above the parent tip (the
newest common node, in this case the change from the gate).
113 -> * * <- 112
| |\
\ | * <- 110
\ |
| * <- 109
* | <- 111
| |
|/
* <- 108
|
where 113 is the reci, 108 the base, 109 the parent tip, 110 is the
result of the first reci (the one Bart thought failed), and 111 the
restored changes he thought were gone forever.
reci then strips the now superfluous changes (the complete subgraphs
rooted at 110 and 111)
Removing 110 and 111 leave us (maintaining revnos, despite them
changing, we really mean nodes here):
110 Strip 111
* <- 113 * <- 113
| |
* <- 109 -> * <- 109
111 -> * | |
| | |
|/ |
108 -> * 108 -> *
| |
Which looks great, exactly what we wanted to happen, right?
Except the manifest entry for 113 above has a linkrev that now doesn't exist
(it refers to the a revno one higher than exists), which doesn't exist, and
the workspace is corrupt.
After the strip of 110 the manifests look thusly:
109 82752 76 51 109 c70da36d808c 047eabe09854 000000000000
110 82828 237 51 111 ce97ffb9392c c70da36d808c 000000000000
111 83065 153 51 111 c5c6709cd76c 047eabe09854 000000000000
Where the mapping to our simplified numbering is:
109 -> random change from the gate (109)
110 -> recommitted change (113)
111 -> Bart's change (111)
So we have two changes with the same linkrev. This is already
bogus, as best as I can tell. What really nails it, however, is
when we remove 111, so the link rev referred to in the recommitted
change no longer exists. Kablam.
The first strip did something pretty bad, the second strip made it fatal.
Now, experimentally, if these are done in reverse order (111 removed
before 110), everything is fine. However, when I was testing the logic
for removing multiple child-local branches, I had workspaces where the
reverse
was true. There's something subtly order dependent about stripping these
and,
currently, I don't know what it is.
Investigation continues...
--
Configure bugmail: http://bugs.grommit.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.