Merging to an empty branch doesn't work
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Bazaar |
Confirmed
|
High
|
Unassigned | ||
Breezy |
Triaged
|
Low
|
Unassigned |
Bug Description
Merging to an empty tree doesn't work (merge corner case)
Attempting to merge to a branch without commits doesn't work correctly.
eg:
mkdir bob
cd bob
bzr init
cd ..
bzr branch bob branch
cd branch
touch some_file
bzr add some_file
bzr commit -m "some change on a branch"
cd ../bob
bzr merge ../branch # Fails here, due to merge requiring checkins
bzr status # even if merge worked, I would fail
bzr diff # and I wouldn't detect changes
bzr commit -m "I wont work either, due to not detecting changes"
bzr log # And even if the rest were fixed, I would give bad history
The reason it doesn't work is that the merged revision on the 'bob' branch will only have a single 'parent', a special case which is assumed by bzrlib.
Allowing the commit to succeed is as simple as updating the logic in bzrlib.
if len(self.parents) > 1:
to
if len(self.parents) > 1 or (len(self.
which will correctly check to see if we have any pending merges.
Unfortunately however, as parent_ids[0] and parent_ids[1:] are special cased throughout the code, other areas also break[2].
I believed the correct fix was to seperate the 'parent' and 'merged' revisions (in bzrlib.
I did this, but unfortunately it was still not enough; the topological sort routines in bzrlib.tsort take a raw parent list (and so are unable to differentiate between merges and parents at the first revision). This causes the log and annotate results to be distorted, causing the revisions we are merging in appear on the mainline. A complete fix would probably require the parent / merged id split distinction to be present all the way to the repository...
Attached are three bundles;
* The first is a blackbox test to confirm that we can perform the 'init/branch/
* The second bundle works around the entire issue, by refusing the merge when we have no revisions (and suggests 'bzr pull'). (also sent to the mailing list)
* The third attempts to fix the parent special case by breaking the tree parent_ids into parent_id and merged_ids (which works correctly for bzr diff and bzr status, but bzr log etc are still broken due to the topological problems). This is just a demonstration (all unit tests still pass after it, except for the attached merge test, but there are lots of deprecated warnings as get_parents was marked deprecated).
[1]
This is a corner case I hit when converting a sub-directory of a repository to bzr; I've been working on updating tailor so that the cvs frontend detects branch origin and merge points, and that the bzr backend will use that information to fully convert a repository. This corner case was hit when converting a module that was a sub-directory of a branch, where this sub-directory was added on a branch (so from the perspective of this directory, we branched from an empty tree, added the initial version, then merged back to integration).
This can happen any time the initial revision is added on a branch, then merged back (an operation that admittedly doesn't make much sense in a distributed system like bzr, but makes perfect sense on a centralised system).
[2]
Some areas that special case the parent check are bzrlib.
tags: | added: merge |
Changed in bzr: | |
importance: | Medium → High |
Changed in brz: | |
importance: | Undecided → Medium |
Changed in brz: | |
status: | New → Triaged |
importance: | Medium → Low |
Added blackbox unit test