Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Prefer younger merge bases over older ones. #1681

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

Merged
merged 2 commits into from
Jun 25, 2013

Conversation

arthurschreiber
Copy link
Member

git-core prefers younger merge bases over older ones in case that multiple valid merge bases exists.

I'm not sure whether git_commit_list_insert_by_date is the correct place to make this change, but this function is only ever called by git_merge__bases_many, so I hope that's ok.

I can also prepare a real test case for this, if the location of this change is determined to be ok. 😄

git-core prefers younger merge bases over older ones in case that multiple valid merge bases exists.
@arthurschreiber
Copy link
Member Author

This fixes #1679

@arthurschreiber
Copy link
Member Author

I just added a test case that is failing without my my change.

@scottjg
Copy link
Contributor

scottjg commented Jun 25, 2013

seems reasonable 👍

@carlosmn
Copy link
Member

This is closer to git-core so it's good, but using the commit date assumes a world where distributed clocks work, which is often the case with git as it's used by humans, but there are commits out there with very wrong clocks (some on GitHub are beyond 2038).

Eventually we'll want to fix this to actually look at the graph and decide which of the merge bases isn't an ancestor, but this is good as a fix.

arrbee added a commit that referenced this pull request Jun 25, 2013
Prefer younger merge bases over older ones.
@arrbee arrbee merged commit b0401c6 into libgit2:development Jun 25, 2013
@arthurschreiber arthurschreiber deleted the patch-1 branch June 26, 2013 11:01
@arthurschreiber
Copy link
Member Author

@carlosmn The way that merge bases are calculated is already correct, and follows the git-core implementation (at least that's what I understood from comparing the two implementations). So commits that aren't ancestors of both branches are already ignored.

The issue here is/was that we have 2 "best" merge bases, which is correct, and where you could use any of them to do diffs/merges. git-core just sorts the bases they return from youngest to oldest, and when you don't pass the --all flag, you get only the youngest. The libgit2 git_merge__bases_many implementation sorted the merge bases in the other direction, and would thus git_merge_base only returned the oldest merge base. If you then tried to emulate the git diff A...B syntax, you got different diffs.

@carlosmn
Copy link
Member

The "best" merge base is defined as the one that's not an ancestor to any other, which means that we can't have two best merge bases unless neither is an ancestor which I'm fairly confident can't happen.

Anyway, we agree that those two merges from --all is what both implementations calculate correctly and we need to look at which one we should return when asked for a single one.

This is where the definition for "best" from the manpage comes into play. We chose the one that's not an ancestor of the other one. In all sane cases it is going to be the one with the newest timestamp. However, I can create a merge base today with a date of one year from now. Next week you create a new merge base with a correct timestamp and run this. The older (in real terms) commit would be returned. Conversely I could create a new one which is older than the existing ones.

Lange Rede kurzer Sinn, what I'm trying to say is that these decisions should happen by looking at the graph as we can't always trust timestamps and this is what the merge-base manpage says it does.

@arthurschreiber
Copy link
Member Author

@carlosmn (don't want to argue with you but) git-core also sorts by date: https://github.com/git/git/blob/master/commit.c#L832

@carlosmn
Copy link
Member

That's for showing all, not determining which is the best for single-output mode. I'll get home shortly and I'll investigate further

@arthurschreiber
Copy link
Member Author

@carlosmn https://github.com/git/git/blob/master/builtin/merge-base.c#L6 just takes the first result when all is not given, and outputs all when all is given.

@arthurschreiber
Copy link
Member Author

Also, even the man page specifies that there can be multiple "best" merge bases, in case there is a criss-cross merge.

@arthurschreiber
Copy link
Member Author

Oh, and that example that I have in my test-case atually looks like a criss-cross merge I think.

@carlosmn
Copy link
Member

Yes, I was confusing which stage we were at. The list is indeed of merge bases so we have already taken the history into account. If we do actually have multiple merge bases, then we have a criss-cross merge and it's undefined what we show when the user doesn't ask for all of them. So in the end this isn't any more correct, just happens to have the same implementation detail as git-core.

phatblat pushed a commit to phatblat/libgit2 that referenced this pull request Sep 13, 2014
Prefer younger merge bases over older ones.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants