Search code examples
gitgit-clonejgitngit

Clone repository into existing directory using NGit / JGit


I'm trying to clone a GitHub repository into a existing, non-empty directory. I tried mimicking the way it's done using the git command line:

git init
git remote add origin https://github.com/[...].git
git fetch
git reset --hard origin/branch

var git = Git.Init().SetDirectory(Location).Call();
Repository = git.GetRepository();

var config = Repository.GetConfig();
config.SetString("remote", "origin", "url", "https://github.com/[...].git");
config.Save();

git.Fetch().Call();

git.Reset().SetRef("origin/branch")
    .SetMode(ResetCommand.ResetType.HARD).Call();

In this particular case I got a "Nothing to fetch" error. I've tried a number of different things, including cloning into a temporary dictionary, using BranchCreate, ... but I've always ran into an issue somewhere.

So how would you go about properly cloning a repository and set it up to fetch updates in the future?


Solution

  • While cloning is easier than git init . + git remote add origin ... + git fetch + git reset --hard origin/master., that sequence is needed for a non-empty folder indeed.

    In that case, you need to tell Git what to fetch, as commented by the OP:

    git.Fetch().SetRefSpecs(new RefSpec("+refs/heads/*:refs/remotes/origin/*")).Call();
    

    That will allow the git.Fetch().Call(); to actually fetch something.

    (That is what the NGit.Test/NGit.Api/FetchCommandTest.cs L61-L82 is doing)

    After extensive discussion in the chat, here is the code the OP is using:

    var cloneUrl = ...;
    var branchName = ...;
     
    var git = Git.Init().SetDirectory(Location).Call();
    Repository = git.GetRepository();
     
    // Original code in question works, is shorter,
    // but this is most likely the "proper" way to do it.
    var config = Repository.GetConfig();
    RemoteConfig remoteConfig = new RemoteConfig(config, "origin");
    remoteConfig.AddURI(new URIish(cloneUrl));
    // May use * instead of branch name to fetch all branches.
    // Same as config.SetString("remote", "origin", "fetch", ...);
    remoteConfig.AddFetchRefSpec(new RefSpec(
        "+refs/heads/" + Settings.Branch +
        ":refs/remotes/origin/" + Settings.Branch));
    remoteConfig.Update(config);
    config.Save();
     
    git.Fetch().Call();
    git.BranchCreate().SetName(branchName).SetStartPoint("origin/" + branchName)
        .SetUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK).Call();
    git.Checkout().SetName(branchName).Call();
     
    // To update the branch:
     
    git.Fetch().Call();
    git.Reset().SetRef("origin/" + branchName).Call();