I have a problem merging what I think is two different heads in HG. When I update between the two revisions (512 and 502 in the screen shot) there are differences between the files. However when I try to merge 512 to 502 it says that there's nothing to merge. If I update to rev. 512 and try to merge 502 to 512 I get the following error message instead: "merging with a working directory ancestor has no effect". Judging by the error message it looks like 502 is a parent of 512 but based on the graph they look like two different heads. What am I doing wrong or misunderstanding?
but based on the graph they look like
two different heads. What am I doing
wrong or misunderstanding
The graph pretty clearly shows that 502 isn't a head at all, right there in red. Your view is filtering away changesets, changesets that must show that 502 is an ancestor of 512.
Can you disable the filter and re-post the image, or better yet provide the output of the command line hg glog command?
Worst case you can hg update 502 commit a do-nothing change, whose parent is 502, and then merge that with 512, but you're better off getting the full picture/understanding of what's going on.
Related
I seem to have made a mistake when performing a series of rebase, strip, and shelve operations. The result is that I am unable to unshelve. When I run hg unshelve in the current state, it just throws an ugly error:
# hg unshelve
unshelving change 'repo-02'
abort: 00changelog.i#5bd4b71e0176: unknown parent!
I think what has happened is that after shelving a change (or maybe a series of shelves) I stripped / rebased away a commit which was a dependency of the shelf.
The shelf has changes to a number of "random" files - meaning their changes are unrelated (mainly temporary debug output, things like that). So even with the single stripped file gone, the remaining parts of the shelve should be OK to use - but how can I get past this error?
One method of getting around this might be to undo the stripped changesets. But before I did that I found another method which worked, and I think this was ultimately simpler as I had a large # of strip backups to work through.
Looking in the .hg\shelved\ folder I actually had data files from several shelve 'events'. They looked something like this:
repo-01.hg
repo-01.patch
repo-01.shelve
repo-02.hg
repo-02.patch
repo-02.shelve
repo.hg
repo.patch
repo.shelve
Reading these file contents I noticed that the .patch files were indeed standard diff-style patches.
Also by looking at the contents of all 3 shelves I could determine that it was only the "repo.patch" (the oldest one) that I actually needed.
(Initially I tried removing the 01 and 02 files and unshelving, but this produced a different error, so I reversed course.)
I then ran:
hg patch --no-commit repo.patch
from within that folder. This basically worked fine, and now my working folder contained modified files again, and they checked out as having the expected contents.
Interestingly because of the original mistake (stripping a commit) one of the files in that patch failed to apply - because the file no longer exists. But fortunately hg patch was resilient enough to just skip over this. Since the file was deleted intentionally, this was not a problem.
Following the above, I used:
hg shelve --cleanup
to get rid of the messy state. Shelve / unshelve now work normally again.
I'm trying to create a bundle for a remote team. They have a copy of the depot from revision 892 and we are currently on revision 1119.
First I tried patches, but that created a ton of files that botched up when trying to apply them (usually on the merge submits)... and our repository is 17GB in size, so I'm trying to create a delta patch, thus figured hg bundle was perfect for this.
I generated a bundle via:
>hg bundle --rev 1119 --base 892 depot-892-to-1119.bundle
This created a bundle file that is 350MB, which is acceptable and feels right.
But when we apply it to the the destination depot that only goes to revision 892 it barfs on:
E:\dest-depot>hg unbundle -u depot-892-to-1119.bundle
adding changesets
transaction abort!
rollback completed
abort: 00changelog.i#e5cc33458251: unknown parent!
And so far this is similar to several other questions I have seen while searching, but I'll take it one step further.
I looked up e5cc33458251 in the source (bigger depot) and it shows up as revision 930 which is clearly after rev 892, but specifies this is the reason for the failure. Of course the destination depot doesn't have the revision. That is why I created the bundle in the first place.... so I'm not really sure why this one is causing me problems.
Now we do have a number of branches in the depot and rev 892 was tipped on a "Patch 2.7" branch and not default. I do not know if this should cause a problem. Eventually that patch branch was merged back into default in rev 999.
930 was actually a very small and trivial change to code and was also in "Patch 2.7" branch. There were actually 2 Patch 2.7 lines in the revision graph and they were merged together in 932. But again, nothing strange.
I am not seeing the problem here. Any ideas on what kind of a bundle I should be generating? Or if I should be going a different path?
It sounds like you're doing this essentially right, so let's check a few possible gotchas:
Are you aware that revision numbers aren't portable across clones? It's entirely possible that "their" 892 is different from yours. So you should find out what their latest revision is by nodeid and use that as the parameters to base.
I get that with their being remote using hg's internal protocol to actually transfer the data might not be feasible, but if you can get them to stand up a hg serve for a short while you can just do:
hg bundle ../depot-to-them.bundle http://THEIR_IP:8000
Then you'll have exactly the right bundle to get them everything they need without having to have them send you their nodeids.
Those aside the only other bit of info that might be worth mentioning is that by using --rev X --base Y you're saying "I want to send all the ancestors of X that they don't have if they only have Y and its ancestors", so if there's a branch that's not yet merged into X you're not going to be sending it, even if locally the revision numbers are between X and Y. That won't, however prevent the bundle from being applied, so it's more of a good-to-understand rather than a possible cause of your troubles.
Is there a canonical explanation why the same parent revision is listed twice for a given mercurial changeset resulting from a merge.
Unfortunately, we do not have a chance to tell, what exactly caused this situation in the observed case. It might be that the situation was caused by trying to perform an empty merge operation.
Any hints appreciated!
We found out a possible way to cause this kind of situation...
The situation can easily be reproduced with TortoiseHG by selecting your local version and "Merge with local" checking the option "Discard all changes from merge target (other) revision".
This does not result in calling hg merge (as one could assume), but hg debugsetparents. So we shot ourselves in the foot by forcing Mercurial to set both parents to the same revision.
Changes were made to our .vcproj to fix an issue on the build machine (changeset 1700). Later, a developer merged his changes (changes 1710 through 1715) into the trunk, but the mercurial auto-merge overwrote the changes from 1700. I assume this happened because he chose the wrong branch as the "parent" of the merge (see part 2 of the question).
1) What is the "correct" mercurial way to fix this issue, considering out of all the merged files, only one file was merged incorrectly, and
2) what should the developer have done differently in order to make sure this didn't occur? Are there ways we can enforce the "correct" way?
Edit: I probably wasn't clear enough on what happened. Developer A modified a line in our .vcproj file that removed an option for the compiler. His check-in became changeset 1700. Developer B, working from a previous parent (let's say changeset 1690), made some changes to completely different parts of the project, but he did touch the .vcproj file (just not anywhere near the changes made by Developer A). When Developer B merged his changes (becoming changes 1710 through 1715), the merge process overwrote the changes from 1700.
To fix this, I just re-modified the .vcproj file to include the change again, and checked it in. I just wanted to know why Mercurial thought that it shouldn't keep the changes in 1700, and whether or not there was an "official" way to fix this.
Edit the second: Developer B swears up and down that Mercurial merged the .vcproj file without prompting him for conflict resolution, but it is of course possible that he's just misremembering, in which case this whole exercise is academic.
I will address the 2nd part of you question first...
If there is a conflict, the automated merge tools should force the programmer to decide how the merge happens. But the general assumption is that a conflict will involve two edits to the same set of lines. If somehow a conflict arises because of edits to lines that are not close to each other the automated merge will blithely choose both of the edits and a bug will appear.
The general case of a merge tool always merging properly is very hard to solve, and really can't be with current technology. Here is an example of what I mean from C:
int i; // Someone replaces this with 'short i' in one changeset stating
// that a short is more efficient.
// ... lots of code;
// Someone else replaces all the 65000s with 100000s in another changeset,
// saying that more precision is needed.
for (i = 0; i < 65000; ++i) {
integral_approximation_piece(start + i/65000.0, end + (i + 1) / 65000.0);
}
No merge tool is going to catch this kind of conflict. The tool would have to actually compile the code to see that those two parts of the code have anything to do with eachother, and while that would likely be enough in this case, I can construct an example that would require the code to be run and the results examined to catch the conflict.
This means that what you really ought to do is rigorously test your code after a merge, just like you should after any other change. The vast majority of merges will result in obvious conflicts that a developer will have to resolve (even though that resolution is often fairly obvious), or will merge cleanly. But the very few merges that don't fit either category can't easily be handled in an automated fashion.
This can also be fixed by development practices that encourage locality. For example a coding standard that states "Variables should be declared near where they're used.".
I'm guessing that .vcproj files are particularly prone to this problem since they are not well understood by developers and so if conflicts do appear they will not be sure what to do with them. My guess is that this happened and your developer simply did a revert back to the revision (s)he checked in.
As for part 1...
What to do in this case depends a lot on your development process. You can either strip the merge changeset out and redo it, though that won't work very well if lots of people have already pulled it, and it will work especially poorly if there are lots of changesets that have already been checked in that are based on the merge changeset.
You can also check in a new change that fixes the problem with the merge.
Those are basically your two options.
The tone of your post seems to me to indicate that you may have some politics surrounding this issue in your organization, and people are blaming this error on the frequent merges of Mercurial. So I will point out that any change control system can have this problem. In the case of Subversion, for example, every time a developer does an update while they have outstanding changes in their working directory, they are doing a merge, and this kind of problem can arise with any merge.
In mercurial a merge doesn't have a single parent, it by definition has two and only two parents. When someone is merging they're making two choices:
What two changesets will constitute the two changes
Which of those changesets will be the left-parent and which will be the right-parent
Of those two questions the first is very important, and the second barely matters at all, though it took me a while to come to understand that.
You select the left-parent by using hg update X. That changes the output of hg parents (or in newer versions hg summary) and essentially determines what's in your working directory before the merge.
You select the right-parent by using hg merge Y. That says merge X (the working directory's parent) with changeset Y. As a special case, if there are only two heads in your repository and your parent is already one of them then Y will default to the the other.
I'd have to see your resulting graph to know just what the developer did, but it's possible he didn't update to one head or another before invoking merge, which would have him merging one head with some point back in history.
If your developer picked the right parents for the merge then the left vs. right doesn't much matter -- the only real difference is that when one uses hg diff or hg log -p or some other command that shows the patch for a merge changeset, it's displayed relative to the left-parent. That's, however, mostly a factor in display only. Functionally they're pretty much identical.
Assuming your developer picked the right changesets then what he should have done was test the result of the merge before committing it. Merging is software development, not an annoying VCS side effect, and not testing before committing is the error.
Fixing
To fix this, just re-do the merge correctly. Use hg update to set one parent, use hg merge to pick the other. Make sure your current working directory is correct and then commit. You can get rid of his bad merge using something like hg strip or better, just close down his branch with hg commit --close-branch after updating to it.
Avoiding
You say "mercurial auto-merge", but mercurial doesn't really auto-merge. It does a premerge which is an extremely cautious combination of obvious changes, but it's so careful it won't even merge for you if each merge parent adds code in the same region because it can't know which block of code you'd rather have first.
You can disable this premerge entirely or on a file-by-file basis using the merge tool configuration options:
https://www.mercurial-scm.org/wiki/MergeToolConfiguration?highlight=premerge
My branch2274 was branched from default. Rev. 415 was the first commit and it shares an ancestor with the rev. 412 on the default branch.
Branch2274 is a bug fix which needs merging into default soon BUT I did a very silly thing - I merged in changes from a feature branch (at rev. 418)
In simple terms, I need to undo whatever changes were brought in by rev. 418. There seems to be a lot of ways to attempt this but I'm struggling to get any of them to work:
Mercurial queues attempt:
I've tried importing revs 415, 416, 417, (skipping 418), 421, 428 into a patch queue so I can apply it to rev 425.
Problem: tortoisehg will only allow me to import revs 428, 421 but importing 417 is greyed out but importing 418 just gives me the error "abort: cannot import merge revision 418"
Transplant attempt:
patching file Portal/Instructor/Login.aspx.vb
Hunk #1 FAILED at 18
1 out of 1 hunks FAILED -- saving rejects to file Portal/Instructor/Login.aspx.vb.rej
applying 66b6b089ee01
abort: Fix up the merge and run hg transplant --continue
patch failed to apply
[command interrupted]
Login.aspx.vb has been changed on default and I understand why the merge has failed.
How do I 'fix up' the merge?
Alternatively, is there a simpler way for me to take rev. 418 and tell mercurial to undo the changes it brought in with a new commit on case2274?
In the interests of not leaving a question unanswered (!), I managed to resolve this and the ultimate answer is that there's no simple way to resolve it automatically. Transplant deals in patches, differences between two files but doesn't take into account the common ancestry of the two files so struggles to know what to do when a file has been changed by two people in the same place.
The solution is to load the file in your text editor and load the .rej file which lists the failed parts of the patch. I just had to put my additions in a sensible place in the code file.
Running:
hg transplant --continue
..allowed me to apply the other patches.
If anyone cares to spend some time expanding this answer with a little insight or a few relevant links, then the answer is theirs.