libgit2 / libgit2sharp

Git + .NET = ❤
http://libgit2.github.com
MIT License
3.15k stars 887 forks source link

Two conflicts instead of one for renamed file #1931

Open ydanila opened 2 years ago

ydanila commented 2 years ago

Reproduction steps

  1. Checkout commit https://github.com/ydanila/test_git from https://github.com/ydanila/test_git
  2. Renamed README.md to README2.md and commit (will be marked as renamed)
  3. Pull changes from 'main' using this code

    public void Pull(string branch)
    {
    using (var repo = new Repository(this.repoPath))
    {
        Configuration config = repo.Config;
        var mergeOptions = new MergeOptions
        {
            FailOnConflict = true,
            OnCheckoutProgress = OnCheckoutProgress
        };
    
        PullOptions options = new PullOptions
        {
            FetchOptions = new FetchOptions { CredentialsProvider = this.GetCredentialsProvider() },
            MergeOptions = mergeOptions
        };
    
        var trackingBranch = repo.Branches[branch];
    
        Signature buildSignature = config.BuildSignature(DateTimeOffset.Now);
        var mergeResult = Commands.Pull(repo, buildSignature, options);
    
        if (mergeResult.Status == MergeStatus.Conflicts)
        {
            repo.Merge(trackingBranch.TrackedBranch, buildSignature);
            ConflictCollection conflicts = repo.Index.Conflicts;
            var changes = new List<ContentChanges>();
            foreach (Conflict conflict in conflicts)
            {
                //  ...
                        }
        }
    }
    }

Expected behavior

As mergeOptions.FindRenames == true it returns one conflict which has Ancestor==Readme.md, Ours==Readme2.md and Theirs==null (file deleted)

Actual behavior

It returns two conflicts. First: 2021-12-06 20_58_25-Window Second: 2021-12-06 21_06_05-Aehnlich (Отладка) - Microsoft Visual Studio

Version of LibGit2Sharp (release number or SHA1)

Latest: 4daf6189b0e20f878348b262d1846eb25bc6d7f6

Operating system(s) tested; .NET runtime tested

Windows .Net Fw 4.7.2

ethomson commented 2 years ago

This is a https://github.com/libgit2/libgit2 feature. This is by-design - we store both sides of a rename conflict so that you can identify what happened in a merge after the fact. (git just spits out information to stdout, which is not particularly helpful if you're trying to drive it programmatically.)

I was reminded of this the other day. I had hoped that merge-ort would address this in git, but I don't think that it did. If it didn't, then we should make our behavior opt-in or opt-out and allow you to match git's retched behavior.

ydanila commented 2 years ago

The problem here that merge can have more than one such conflict and they don't have common ancestor so I can't filter out and group such values together.

This should work via manually rename tracking for second conflict to find common ancestor?