Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pull latest from a specific remote branch without having need to provide user details?

Requirement:

Using libgit2sharp I want to pull (fetch + merge) latest from a specific git remote branch to my currently checked out local branch, without having to pass any other argument, like user credentials etc. Basically I am trying to replicate git pull origin my-remote-branch

Details:

I want to automate certain Git operations from C#. I can simply do what I want by invoking git.exe (if I know the path), like git.exe --git-dir=my-repo-directory pull origin my-remote-branch. Notice that here the only external parameters I have to supply are my-repo-directory and my-remote-branch. Git gets everything right, like the name, password, email, current working branch (even if it doesnt have remote attached) and git pull simply works. I dont have to pass any of those parameters manually. I assume Git gets them from current Git settings for the repo (from %HOME% folder?).

Is there a way to simulate that in LibGit2Sharp?

What I tried:

using (var repo = new Repository("my-repo-directory"))
{
    PullOptions pullOptions = new PullOptions()
    {
        MergeOptions = new MergeOptions()
        {
            FastForwardStrategy = FastForwardStrategy.Default
        }
    };

    MergeResult mergeResult = Commands.Pull(
        repo,
        new Signature("my name", "my email", DateTimeOffset.Now), // I dont want to provide these
        pullOptions
    );
}

Which fails since it says there is no tracking branch. I dont necessarily need a tracking remote branch. I just want to fetch latest from a specific random remote repo and perform automerge if possible.

Just to see if it works I tried:

using (var repo = new Repository("my-repo-directory"))
{
    var trackingBranch = repo.Branches["remotes/origin/my-remote-branch"];

    if (trackingBranch.IsRemote) // even though I dont want to set tracking branch like this
    {
        var branch = repo.Head;
        repo.Branches.Update(branch, b => b.TrackedBranch = trackingBranch.CanonicalName);
    }

    PullOptions pullOptions = new PullOptions()
    {
        MergeOptions = new MergeOptions()
        {
            FastForwardStrategy = FastForwardStrategy.Default
        }
    };

    MergeResult mergeResult = Commands.Pull(
        repo,
        new Signature("my name", "my email", DateTimeOffset.Now),
        pullOptions
    );
}

This fails with

request failed with status code: 401

Additional info:

I dont want to invoke git.exe directly because I cant hardcode the git exe path. Also, since I cant pass username, email etc at runtime, is there a way libgit2sharp get them by itself from the repository settings, like how git.exe does?

like image 528
nawfal Avatar asked Oct 19 '17 15:10

nawfal


People also ask

How do I pull a specific branch from a remote?

If you have a single remote repository, then you can omit all arguments. just need to run git fetch , which will retrieve all branches and updates, and after that, run git checkout <branch> which will create a local copy of the branch because all branches are already loaded in your system.

How do you pull changes from someone else's branch?

Pull new changes from remote: git checkout master , git pull upstream master . Sync dev branch: git checkout new_feature , git merge master . Push changes to your remote repository: git push origin new_feature . Open a pull request on GitHub merging your changes with the upstream (original) repository.


1 Answers

I assume Git gets them from current Git settings for the repo (from %HOME% folder?).

It depends entirely on what the remote "origin" is:

  • an ssh URL (in which case Git will rely on %HOME%\.ssh). ssh support for libgit2sharp is followed by issue 7 and (rejected) PR 1072: you might have to use leobuskin/libgit2sharp-ssh
  • an https URL (in which case Git should rely on a Git credential helper (see Git Storage), which is not supported directly by libgit2, as mentioned here.
    You will have to code that helper yourself in CSharp: "Retrieve Credentials from Windows Credentials Store using C#".
    Or, as commented by Edward Thomson:

    Pass a CredentialsHandler in your FetchOptions.
    Return either UsernamePasswordCredentials or DefaultCredentials from your handler, as appropriate.

See here for a UsernamePasswordCredentials example.
See also LibGit2Sharp.Tests/TestHelpers/Constants.cs and other occurrences.


Regarding the pull operation, it involves a Command Fetch, which involves a refspec. As in "Git pull/fetch with refspec differences", you can pass the source:destination branch names for your pull (even if there is no tracking information).

That is what is used in LibGit2Sharp.Tests/FetchFixture.cs.

string refSpec = string.Format("refs/heads/{2}:refs/remotes/{0}/{1}", remoteName, localBranchName, remoteBranchName);
Commands.Fetch(repo, remoteName, new string[] { refSpec }, new FetchOptions {
                TagFetchMode = TagFetchMode.None,
                OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler
}, null);
like image 151
VonC Avatar answered Oct 12 '22 23:10

VonC