0

I have two branches in my mercurial repository that I want to merge. One is my default branch and the other is Bootstrap 3.3.7.

In my default branch I've customised the Less files. I replaced them with the vanilla ones from Bootstrap 3.3.7 and committed the changes to a new branch Bootstrap 3.3.7.

I'm currently on the default branch and want to merge Bootstrap 3.3.7 to that but when I do the merge instead of having merge conflicts that I can manually resolve (thereby preserving my edits), mercurial simply takes the file versions from my default branch, ignoring Bootstrap 3.3.7 files, even though I know there should be conflicts.

How do I do the merge so that I have the option of picking which changes I want.

In the attached screenshot I've filtered my repository to the relevant branches but my working directory is Rev 7097 on the default branch.

Mercurial repository and branches

jimmy
  • 504
  • 8
  • 16
  • Merge conflicts comes because of conflicting *changes*, only one branch introduced changes to that file, thus mercurial merges it without conflict by just taking those changes. That is correct behavior in terms of the merge. You need to compare that file to the one in the repository using an external tool and bring in those changes you want. – Lasse V. Karlsen Nov 16 '17 at 14:30
  • If the original file is based on bootstrap to begin with, and you don't mind an extra branch path along your history, you could update back to when you first introduced the original file, then commit the new on directly on top of that, and then try to merge this into the default branch, this should then compare the changes on the new branch (updating to new bootstrap version) with default (all your customizations) and give you the merge conflict you probably want. – Lasse V. Karlsen Nov 16 '17 at 14:31
  • If you try to merge two branches where one is just on top of the other, history-wise, like in your picture, then you will never get a merge conflict. In git lingo this would be a fast-forward merge. You can instruct git (not sure about mercurial) to actually make a merge commit, but it won't produce a merge *conflict* whatsoever. – Lasse V. Karlsen Nov 16 '17 at 14:32
  • @LasseVågsætherKarlsen On `default` I have `css/less/variables.less` which has `@brand-primary: #6AA1CD;` On `Bootstrap 3.3.7` I have in the same file, same line `@brand-primary: darken(#428bca, 6.5%);` When I merge `Bootstrap 3.3.7` to `default` should it not detect a conflict? The file is different on both branches, which one should it take? – jimmy Nov 16 '17 at 15:07
  • @jimmy: no. At the level of each individual file, merge doesn't mean "combine two files", merge means "combine two *changes* with respect to a *third* file". The third version of the file comes from the *merge base*, which is (roughly) the "newest" historical commit that is reached by following history backwards from each of the two heads. The head of `Bootstrap 3.3.7` is rev 7124; the head of `default` is rev `7097`; and the historical commit shared by those two revs is `7097` itself. What changed from 7097 to 7097? – torek Nov 16 '17 at 18:12
  • @LasseVågsætherKarlsen: In Mercurial commits are irrevocably bound to their branches, so for a case like this, you *must* get a merge commit on `default` as there's no option to use the existing rev on the other branch.. But there's no Hg equivalent to fast forward anyway: when merging two heads within a single branch, you still get a merge commit, even if the merge base is one of the two heads. (That's the only way to reduce the number of heads within the branch.) – torek Nov 16 '17 at 18:14
  • @LasseVågsætherKarlsen: actually it occurs to me (too late) that you can't *have* one of the two heads be the merge base, within the same branch: that implies that it's not a head. Hg just says `abort: nothing to merge`. – torek Nov 16 '17 at 19:20
  • I didn't say mercurial supported or used fast-forward or the equivalent, I just meant that git doesn't merge this either, because you're effectively merging changes, not snapshots, and as pointed out above, what changed between 7097 and 7097? Nothing. Thus, no changes, thus nothing to merge, and the changes on the other branch is accepted wholesale because they're not in conflict with any other *changes*. – Lasse V. Karlsen Nov 17 '17 at 08:58
  • @torek So if I understand correctly, the only thing that's needed is to make some change to `variables.less` on the `default` branch, and then do a merge? Also I ran across this https://stackoverflow.com/a/5708185/2271704 answer to an issue which looks like the one I'm having. Why would the solution work in that case but not mine? – jimmy Nov 17 '17 at 11:41
  • @jimmy: essentially, yes. But your second question means that either you still have not quite grasped the fundamental concept behind three-way merging, or you don't have in your head a good image of what `hg update` actually does (which would not be surprising as it's tricky in its own way). – torek Nov 17 '17 at 15:58
  • @LasseVågsætherKarlsen: Yes, I'm just noting that Git's fast-forward operation is fundamentally nonsensical in Mercurial, but not in Git, precisely *because* Git doesn't bind commits to one particular branch name (or, in an even deeper sense, because Git doesn't actually have the thing that Mercurial calls "a branch": Git merely has moveable labels). – torek Nov 17 '17 at 16:03
  • It would only be a conflict if the same file changes on both branches on the same line (or at least, I think the line is relevant). Two changes in separate parts of the file would result in a merged file but no *conflict*. – StayOnTarget Jan 11 '18 at 21:11

0 Answers0