using libgit2sharp to pull latest from a branch

2019-07-21 01:13发布

I am using libgit2sharp in a c# solution to switch to a branch and pull in the latest changes. Here is the code I am using:

    public void FetchAll()
    {
        using (var repo = new Repository(_LocalGitPath))
        {
            foreach (Remote remote in repo.Network.Remotes)
            {
                FetchOptions options = new FetchOptions();
                options.CredentialsProvider = new CredentialsHandler((url, usernameFromUrl, types) => new UsernamePasswordCredentials()
                {
                    Username = _UserName,
                    Password = _Password
                });
                repo.Network.Fetch(remote, options);
            }
        }
    }
    public string CheckoutBranch(string branchName)
    {
        using (var repo = new Repository(_LocalGitPath))
        {
            var trackingBranch = repo.Branches[branchName];

            if (trackingBranch.IsRemote)
            {
                branchName = branchName.Replace("origin/", string.Empty);

                var branch = repo.CreateBranch(branchName, trackingBranch.Tip);
                repo.Branches.Update(branch, b => b.TrackedBranch = trackingBranch.CanonicalName);
                Commands.Checkout(repo, branch, new CheckoutOptions { CheckoutModifiers = CheckoutModifiers.Force });
            }
            else
            {
                Commands.Checkout(repo, trackingBranch, new CheckoutOptions { CheckoutModifiers = CheckoutModifiers.Force });
            }

            return branchName;
        }
    }
    public void PullBranch(string branchName)
    {
        using (var repo = new Repository(_LocalGitPath))
        {
            PullOptions options = new PullOptions();

            options.MergeOptions = new MergeOptions();
            options.MergeOptions.FailOnConflict = true;

            options.FetchOptions = new FetchOptions();
            options.FetchOptions.CredentialsProvider = new CredentialsHandler((url, usernameFromUrl, types) => new UsernamePasswordCredentials()
            {
                Username = _UserName,
                Password = _Password
            });

            repo.Network.Pull(new Signature(_UserName, _Password, new DateTimeOffset(DateTime.Now)), options);
        }
    }

I have no problem fetching, and checking out a branch. When I try to pull latest, I get an error saying, 'There is no tracking information for the current branch.' I believe that this means that the local branch doesn't know what the correct remote repository is to pull changes from, but I haven't been able to figure out how to tell libgit2sharp what the remote repo path is. Anyone have any suggestions?

While doing research on this problem I found this: https://github.com/libgit2/libgit2sharp/issues/1235. Essentially, a libgit2sharp dev describes the exact problem I am seeing, but doesn't provide any code for the fix.

One additional note: I will never be merging or pushing any changes back from this repository. I am pulling it for an automated build, so we can ignore or overwrite any local changes. I just need to get the latest code.

SOLUTION: I have updated the code above with the solution that I got working. You need to be really careful to make sure that when you checkout a branch, you check the isRemote flag on the branch you are checking out is set to true. If you checkout a branch that isn't a remote it will set the remote to '.' in your git config file, and you need to manually fix it. If there isn't a valid remote you will not be able to pull the branch changes.

Do not use the code sample on the libgit2sharp wiki unless they add this check in.

1条回答
smile是对你的礼貌
2楼-- · 2019-07-21 01:47

You can setup the tracking brach information on the local branch by using the Refspec:

using (var repo = new Repository("/Users/sushi/code/redux/mono"))
{
    var trackingBranch = repo.Branches["remotes/origin/work-btls"];
    if (trackingBranch.IsRemote)
    {
        var branch = repo.CreateBranch("SomeLocalBranchName", trackingBranch.Tip);
        repo.Branches.Update(branch, b => b.TrackedBranch = trackingBranch.CanonicalName);
        repo.Checkout(branch, new CheckoutOptions { CheckoutModifiers = CheckoutModifiers.Force });
    }
}

You can use git to verify that SomeLocalBranchName is now tracking remotes/origin/work-btls:

>>>git for-each-ref --format='%(refname:short) <- %(upstream:short)' refs/heads

SomeLocalBranchName <- remotes/origin/work-btls
master <- origin/master 

>>>git status

On branch SomeLocalBranchName
Your branch is up-to-date with 'remotes/origin/work-btls'.
查看更多
登录 后发表回答