Possibility to merge independently added files/directories
Two folders (or files) with the same name added into different branches independently, cannot be merged in Plastic now.
It would be priceless in some cases (especially for folders).
http://www.plasticscm.net/index.php?/topic/1224-evil-twin-conflict-resolution/
http://www.plasticscm.net/index.php?/topic/391-directory-merge-fail/
-
SWSBB commented
(Without having read all the comments)
This could help: https://plasticscm.uservoice.com/forums/15467-general/suggestions/31531255-possibility-to-split-changesets -
Göran Wallgren commented
Continuing from my latest comment, this means that there is a possible workaround in some cases:
* After a cherry-pick involving added items, immediately do a normal merge back onto the original branch (the one you cherry-picked from).
Now, this is not always feasible and it will NOT help if the added files have already been modified on the original branch.
However, whatever it is that happens in that merge-back is very interesting - the resulting changeset does not seem to contain any changes but still it will make subsequent merge-backs work fine even when there are changes to the added items on both branches (no more "item loaded twice"). The hidden details that happen in this "magic" (and seemingly empty) merge-back are exactly what I'd like to happen in the original cherry-pick instead, so we don't get this problematic issue in the first place...
-
Göran Wallgren commented
Regarding "item loaded twice" caused by cherrypicking an Add operation, I have made the following suggestion that I discussed with Plastic staff in this (old) forum post:
http://www.plasticscm.net/index.php?/topic/2118-item-loaded-twice-conflict/Would it not be possible to handle _added_ files/folders in a better way in a Cherrypick? When cherrypicking a file Add operation, a sensible expectation is to be able to merge this back to the branch where the Add came from... Fixing that would solve an important part of this uservoice.
Here's a scenario:
* Switch to branch /main
* Add file a.txt. Checkin (1).
* Add file b.txt. Checkin (2).* Switch to branch /other
* Merge from (1). Checkin (3). "Copied (new) / Merge from 1".
* Cherrypick from (2). Checkin (4). "Copied (new) / Cherrypick from 2".
* Modify the contents of a.txt and b.txt. Checkin (5).* Switch back to branch /main
* Modify the contents of a.txt and b.txt. Checkin (6).
* Merge from (5).Now, you get "Item loaded twice conflict" on b.txt that was cherrypicked earlier. On a.txt that was merged earlier you get no such problem, only a normal conflict.
Could not the Cherrypick operation be modified to include the necessary info to be able to merge it back later?
If we had done a (no-change) Merge from (4) back to /main before the modify-checkin (6), the following merge from (5) would have worked just fine. That seems to indicate that not much extra info is needed to get it working as expected!
-
Göran Wallgren commented
The following thread is also related: http://www.plasticscm.net/index.php?/topic/3029-new-files-or-folders-committed-with-name-conflict-prefixed/
-
Göran Wallgren commented
Yet another situation where an identical item can become two totally different unique item-IDs is in Plastic GitSync. Git itself does not version-track folders, and if a merge done in Git involves an added folder then GitSync fails to correctly detect this as a folder-copy-add "Copied (new) / Merged from ..." and instead adds the folder as a new unique item-ID on the destination branch.
When later merged back in Plastic, this can lead to a full delete-add cycle of the added folder. It can also lead to "Changed/Deleted" conflicts and "(name_conflict)_*" renames in further merges.
-
Göran Wallgren commented
Actually, we could possibly add an even earlier fix step to the list from my previous comment:
0. Add the same "Keep both changes, renaming the destination to ..." option from "evil twin" to the "item loaded twice" as well. (Without this choice, you'll have to lose any changes made to one of the files since the cherrypick.)
-
Göran Wallgren commented
For a file in an "item loaded twice" conflict, I suppose the initial cherrypick (where the file was added on the second branch) could be chosen as the base/ancestor for that file in a 3-way merge. But that could be a follow-up improvement if it's simpler to implement 2-way merge first.
In the far future, it may even be possible to create a "virtual" ancestor for some of these cases, similar to a "merge recursive": http://codicesoftware.blogspot.com/2011/09/merge-recursive-strategy.html
Personally, I think that improvements to this issue could be slowly added over time (since it seems a rather complicated topic overall). I can imagine the following rough prio list:
1. Add 2-way merge resolution for files in "loaded twice" case.
2. Add 2-way merge resolution for files in "evil twin" case.
3. Add (simplistic?) merge resolution for directories in "loaded twice" case.
4. Add (simplistic?) merge resolution for directories in "evil twin" case.
5. Add 3-way merge resolution for files in "loaded twice" case.
6. (Add 2-way merge resolution for files in "divergent move" case, if at all applicable?)
7. (Add (simplistic) merge resolution for directories in "divergent move" case, if at all applicable?)
8. (Virtual ancestors, 3-way merge in remaining cases ???) -
Göran Wallgren commented
Follow-up: What (I think) I mean by 2-way folder merge is actually this:
* For a "loaded twice" folder, the folder is the same "unique item" on both branches. We should be able to choose keeping one of the parent changesets/revisions while also merging the contents. For each file (inside this folder) that is the same "unique object" in both branches the same option of choose-parent-and-2-way-merge-contents should be auto-applied, according to the same choice that we made for the folder. (This should be applied recursively, so a sub-folder that is "loaded twice" should have the same resolution auto-applied etc.) For a conflicting change in the folder (add/delete/move file etc), that conflict should be displayed in the pending conflicts and be resolved manually.
* For an "evil twin" folder, by choosing to merge contents we acknowledge that we actually intended these separate "unique items" to be the same folder on both branches. Then, we should be able to handle this case (recursively) very similarly to the "loaded twice" case.
That said, please also take the time to read all my previous rambling comments, to follow my train of thought... :P
-
Göran Wallgren commented
All that ever was asked for in this thread is a 2-way merge. We simply want the extra resolve-options for the cases where the file is meant to be the same (or at least related, which is probably most often the case since they have the same name). 2-way merge is so much better than no merge at all - we just don't want to be forced to discard one of the set-of-changes. This is not so much about the history line but rather about the contents of the file or directory that is being merged. No need to go all complicated and rebuild history!
BUT: While the first solution is fine, it should be implemented for directories too! I guess a "2-way merge"-style join of the contents from the two directories is needed in order to not risk losing added files etc.
Overall, I'm most of all concerned about the case of "Item loaded twice" (where the items really are the same) since it is very easy to get - simply add an item, cherrypick the add, merge back. I've already had this happen a couple of times before I was aware of this problem, during the month that has passed since we migrated from SVN.
I believe if you get "Item loaded twice" on an added directory, you risk losing files in the merge (if they were added between the cherrypick and the merge). Therefore we need the option to do some kind of merging for directories as well. If you want, I can provide more detailed steps for how to reproduce these scenarios.
-
Although the more seasoned users already know this, keep in mind the situation is as follows:
* You add a file /src/foo.c on a branch, then make whatever changes to it.
* You add a file /src/foo.c on a different branch. They are totally different *items*, not the same one, not the same file or anything. They'll have different histories.When you try to merge, they don't have a common ancestor, and the files can certainly be different.
One option is to use some sort of 2-way merge (yes, the kind of baseless merge we old hate from svn, where you have to solve every single conflict manually) and keep one of the two files with the 2-way-merged result while discarding the other.
This option would be relatively simple to implement.
The other option is to go and rebuild history, making the two files become actually the same item. This is a very hard problem, because while the simple case could be simple, it is full of corner cases as soon as you consider replication, partial replication, complex branch hierarchies and many more.
And I only covered files... directories would make the thing even more complex, because you could have full hierarchies inside, so, should you also recursively reconcile the children files inside using the same technique? Doable, yes, complex, yes.
I must admit I'm slightly biased against this, and that's the reason why it has been hanging around for too long, because we obviously use Plastic very intensively, and we almost never have this issue.
I don't think it will be something happening with code often, only, maybe with config files, and then... discarding one of them will be probably enough.
Would you guys be happy if we consider the first solution I exposed for files only? 2-way merge for the conflicting file, and keeping one of the two as the result.
Thanks,
-
Göran Wallgren commented
For the "Item loaded twice conflict" it really is the same unique item on both branches, so the natural default would be to keep the parent-linkage on the destination branch.
In most of these twin/twice cases it would make some sense to view an incoming merge an update to the contents of the duplicate item, not as a complete replacement, so again for history it probably is most natural to let the version on the destination branch "live on".
Maybe you could indicate with a text "(recommended)" or simply pre-selecting (or re-ordering) the conflict resolution option that is the "most natural" (preserve destination) and "least dangerous" (one where you don't loose any of the involved modifications). Alternatively you could indicate with a warning text the options where you potentially lose modifications.
Also, an alternative to adding more options could perhaps be a checkbox "Manually merge contents from both items" or similar.
-
Göran Wallgren commented
Hmm, actually I guess the "Divergent move conflict" could be handled very similar to the "evil twin" and "loaded twice", since it is próbably more important to preserve both modifications to the item contents than to preserve both move operations (the latter are easier to recreate if needed).
Thus, for the "divergent move" we could have the very same two additional options as proposed earlier for the "evil twin". It would merge the [item content] modifications done on source and destination and apply the result to the [item move] operation that you decide to keep.
-
Göran Wallgren commented
The same additional options "Merge contents and keep the add/move on src/dst" could also be used to better resolve the "Item loaded twice conflict". (The latter can be caused by first cherry-picking an added item and then later merging changes involving the same item.)
On a side note, I also think the "Divergent move conflict" resolve dialog should include options to keep both of the modifications by keeping one move and adding the other as a new item. Otherwise you will always be forced to discard one of the modifications to the item contents.
-
Göran Wallgren commented
For the evil twin case: I guess part of the problem is that an item can only have one parent revision, and that is why Plastic demands that you keep one of the twins and discard the other.
However, keeping only (the parent linkage of) one of the twin items should not prevent (two-way) merging of the contents from both versions.
Hence, I propose adding not one but two new options for resolving the evil twin conflict:
* Merge contents and keep the add/move done on source
* Merge contents and keep the add/move done on destination -
Göran Wallgren commented
BTW, suppose one has already happened to resolve this kind of conflict by discarding one of the changes. It would then be helpful if there was a way to diff/compare a file (from a workspace or a list of changed files) with another changeset, by ignoring ancestry and just picking the file with the same filepath from the other changeset...
-
Göran Wallgren commented
Yes! Besides the "Keep both changes, renaming the destination to ..." option, there should be another option "Merge the two items".
As there is no common ancestor, it will be a two-way merge. This is much better than renaming the destination and then manually combining the two (and deleting the renamed one) in a subsequent checkin!
Also, a better handling of the "item loaded twice" conflict occurring when merging a "cherry-picked added item" should be very high prio! (After all, we migrated to Plastic for its superior merging abilities... ;)
-
JakubH commented
I have found another case where this would be needed – for an "Item loaded twice conflict" after cherry-pick with an added item: http://www.plasticscm.net/index.php?/topic/2118-item-loaded-twice-conflict/
-
jmranger commented
Another independent request:
http://www.plasticscm.net/index.php?/topic/1762-feature-request-merge-functionality-in-addmove-dialog/
+1 for this. -
Gerard Murphy commented
I see the need for this quite a lot at client sites were I work - many developers are afraid to merge changes and will E-mail copies of files to transmit changes between branches being worked on by different people. They then commit the copied file in a new branch as an evil-twin. So when I get round to merging, I inherit lots of evil twin conflicts.
Mercurial allows evil twins to be merged: it effectively performs three-way merge using an empty file as a common base. As there are merge tools that can identify commonality between the two independent sets of changes (and therefore automatically merge them, as they are the result of the original copy via E-mail), this turns out to be quite an effective way of merging in practice.
-
JakubH commented
I should mention that it means: allow resolve an evil twin conflict with merge.