Open BowiFromStackOverflow opened 3 years ago
There's no automation around that. Part of what would be required is to remove some of git-imerge
's special references that it uses to keep track of progress: refs/imerge/$NAME/manual/$I-$J
and refs/imerge/$NAME/auto/$I-$J
. Specifically, if merge $I-$J
was incorrect, you'd have to remove any references with higher $I
or $J
values. You might also have to modify the blob pointed at by refs/imerge/$NAME/state
. I'm mostly looking at its blockers
value, which might refer to later merges. I haven't tried this before, so you might have to fiddle with things.
To be clear, if this works, it would put you back in the state when the erroneous merge was done. Any merges done after that would have to be re-done. It might be possible to salvage some of the later merges, but that would be a significantly more complicated project.
If you don't want to muddle around with git-imerge
's internal state, another approach would be to restart the imerge with the same arguments, and when you are asked to do a merge manually that was done right the first time, you could read the tree for the completed merge into your working copy (it would be the tree under refs/imerge/$NAME/manual/$I-$J
for the $I-$J
value you are working on).
Let us know if this works out!
First of all, thank you very much for your reply! I am currently not having the problem – in my case, I was just trying git-imerge with a very small set of commits and ended up just doing a normal merge with editing undetectably conflicting lines (it was only one...) manually at the end. But I am curious on how to solve such a problem. =)
If you don't want to muddle around with
git-imerge
's internal state, another approach would be to restart the imerge with the same arguments, and when you are asked to do a merge manually that was done right the first time, you could read the tree for the completed merge into your working copy (it would be the tree underrefs/imerge/$NAME/manual/$I-$J
for the$I-$J
value you are working on).Let us know if this works out!
I have to admit that I do not understand what you are suggesting – so when I have found the "bad" merge commit by bisecting, I just rerun the git-imerge start ...
command? Wouldn't this be in the completely wrong spot? And why should it ask me for a manual merge when there is no detectable conflict? I guess I am deeply misunderstanding your suggestion. ;-)
(This is a minimal undetectable conflict example I wrote for testing right now – a few people at a party; after the merge of the log lines we see that Adam is drinking wine despite Caesar having drunk all of it earlier: https://gist.github.com/BowiFromStackOverflow/5575fd41cf8944b72557083f359914ae)
I have to admit that I do not understand what you are suggesting – so when I have found the "bad" merge commit by bisecting, I just rerun the
git-imerge start ...
command? Wouldn't this be in the completely wrong spot? And why should it ask me for a manual merge when there is no detectable conflict? I guess I am deeply misunderstanding your suggestion. ;-)
For concreteness, let's suppose that you are merging branch
into main
. So you'd start by doing something like
git checkout main
git imerge merge branch
At some point during this imerge, or even after you've completed the imerge but before you run git imerge finish
, you notice that there is a failure, which you assume to have happened in one of the manual sub-merges.
At this point you can run bisect between main
and the commit that you noticed to be broken. This should show you which $I-$J
submerge introduced the failure, assuming that it's one of the merges that was done explicitly.
You could now start a new incremental merge with the same initial arguments:
git checkout main
git imerge merge --name=take2 branch
It should present the exact same manual merges to you, in the same order. So for example if it asks you to do merge $I-$J
, instead of doing the merge manually again, you could copy in the tree from the first imerge. The default name of that imerge is the name of the branch, branch
, so run
git checkout refs/imerge/branch/manual/$I-$J -- .
(I think that's the right command). Then run your tests to see if the merge results in your problem. If so, fix it before running git imerge continue
, and from this point on you'll probably have to redo the rest of the merges manually.
This will always work if you used --goal=full
or --manual
for the first merge, because then all submerges will have been filled in. But those options are very expensive, so in most cases you won't be guaranteed to find the very first broken sub-merge.
This could work better if git-imerge were taught to check not only whether a sub-merge completes without conflicts, but also runs a user-specified test against it before considering it a success. This would allow git-imerge
to (usually) find the exact erroneous sub-merge by itself and hand control over to the user when that happens. It was implemented in #64 but that never got merged (probably my fault).
I have to admit that I do not understand what you are suggesting – so when I have found the "bad" merge commit by bisecting, I just rerun the
git-imerge start ...
command? Wouldn't this be in the completely wrong spot? And why should it ask me for a manual merge when there is no detectable conflict? I guess I am deeply misunderstanding your suggestion. ;-)For concreteness, let's suppose that you are merging
branch
intomain
. So you'd start by doing something likegit checkout main git imerge merge branch
That's right so far (even if I used git-imerge start --name=includingBranchIntoMain --first-parent --goal=merge branch
instead)
At some point during this imerge, or even after you've completed the imerge but before you run
git imerge finish
, you notice that there is a failure, which you assume to have happened in one of the manual sub-merges.
Here we're diverging: It happened in one of the automatic sub-merges (like in my example in the gist, there is no detectable conflict at all).
At this point you can run bisect between
main
and the commit that you noticed to be broken. This should show you which$I-$J
submerge introduced the failure, assuming that it's one of the merges that was done explicitly.You could now start a new incremental merge with the same initial arguments:
git checkout main git imerge merge --name=take2 branch
It should present the exact same manual merges to you, in the same order. So for example if it asks you to do merge
$I-$J
, instead of doing the merge manually again, you could copy in the tree from the first imerge. The default name of that imerge is the name of the branch,branch
, so rungit checkout refs/imerge/branch/manual/$I-$J -- .
(I think that's the right command). Then run your tests to see if the merge results in your problem. If so, fix it before running
git imerge continue
, and from this point on you'll probably have to redo the rest of the merges manually.
Oh, now I think I understand it! Unfortunately, it is a conflict that does not cause git-imerge to stop, so I cannot do that while running the incremental merge.
This will always work if you used
--goal=full
or--manual
for the first merge, because then all submerges will have been filled in. But those options are very expensive, so in most cases you won't be guaranteed to find the very first broken sub-merge.
What is --manual
?
This could work better if git-imerge were taught to check not only whether a sub-merge completes without conflicts, but also runs a user-specified test against it before considering it a success. This would allow
git-imerge
to (usually) find the exact erroneous sub-merge by itself and hand control over to the user when that happens. It was implemented in #64 but that never got merged (probably my fault).
That indeed would be great! Even if there was no way of detecting the error automatically, one could do it like this:
bisect
Or do you have another opinion on that? Of course, on the long hand, it would be even greater to have a feature that "rolls back" to a specific incremental merge commit like it was in conflict and discards all commits affected by that – but I think, it would be very much effort.
It was implemented in #64 but that never got merged (probably my fault).
I hope it didn't get lost in a merge conflict. ;-)
This is more a question than an "issue". I've posted the very same question on StackOverflow already, hoping for it to just be me being unable to find the information in git-imerge documentation and got a "I do not think there is an easy way to achieve it!" comment.
The internet tells me about
git-imerge
:But how can I do that?
To start the operation of eg. merging branch
newFeature
tomaster
, I would useAnd then resolve all the conflicts that imerge finds by itself. After finishing, I see that somewhere a bug has been inserted. I search for it using
But when I have found the merge commit that did introduce the problem – how can I redo that merge and continue the incremental merge from there?