-
Notifications
You must be signed in to change notification settings - Fork 2.5k
merge-base: Remove redundant merge bases #3492
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
return -1; | ||
} | ||
|
||
/* more than one merge base -- remove redundants */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes it sound like there are redundant entries every time we have more than one merge base, which is not what we're doing here. If there are multiple merge bases, we may have some redundant ones.
Looks fine; as far as testing goes, were you able to identify what was special about the repository in which this happened? Maybe we can recreate part of the graph which made us have redundant commits. |
Waiting for some feedback from @peff too. |
Nope, the history on that repo is quite dense. I could use the whole anonymized repo as the test case, but that'd be a tad too large I think. |
Yeah, even if we can't use the exact repo that you found, I would like to be able to have a test repo that shows what a redundant merge-base is... Though I think to create such a beast, we'll have to understand WTF is actually going on here, which I certainly don't yet. |
I looked at the graph of the repo that triggered this. What happens to cause the redundant base is that you have a merge one one side that "straddles" a merge on the other. Here's a picture:
Here we have a side branch Imagine we want to find the merge base of the side branch and master. We walk backwards from In a true criss-cross merge, I drew the diagram above by hand. It does represent the situation in the repo we found, but I didn't actually recreate the simplified version and test it. But it should be pretty straightforward to make a libgit2 test case out of it. |
I don't see anything obviously wrong with the code itself, but I am not that familiar with the libgit2 code. I'm fairly sure that failing to remove the redundant bases is the source of the problem we found, though. So at least the intent of this PR is correct. :) |
So, I couldn't make heads or tails of @peff's ASCII diagram, but running the original repository through the anonymizer and manually pruning some extra branches gave a pretty small reproduction case that seems to work really well. I've committed it to the I think this is ready to merge now. |
merge-base: Remove redundant merge bases
@vmg Hmm. I did recreate my diagram as a git repository, but running I git, I noticed that it didn't actually trigger I'd give it 50/50 odds on one explanation versus the other. I don't think it's worth spending a lot of time trying to recreate the minimal test case, though. That would give me a warm fuzzy feeling, but since you have a working anonymized case, that's probably enough. |
Following up on the Famous Case Of The Extra Merge Base. Comparing our runtime vs Git's, it turns out we never implemented a second optimization pass after finding the merge bases:
https://github.com/git/git/blob/80980a1d5c2678ab9031d7c60faf38b9631eb1ce/commit.c#L900-L954
So, here's my implementation, ported mostly verbatim from Git. I'm aware tests are missing, but it's not immediately obvious to me how to reproduce the "minimal test case" here (I haven't put much thought into it to be fair). Any assistance on that would be welcome.
cc @carlosmn @ethomson @peff