Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create new git repository from a branch of another using libgit2?

Tags:

c++

git

libgit2

In C++ using libgit2, I'd like to create a new local repository where its master branch is based on specific-branch from another local repository, maintaining its history so I can later synch between the two.

Essentially, I'm attempting the following, except using libgit2:

https://stackoverflow.com/a/9529847/1019385

So if I had files arranged as follows:

./old.git [branches: master, specific-branch]

./old/* [files and clone of ./old.git at specific-branch]

Where the commands would be something like:

git init --bare ./new.git
cd ./old
git push ./new.git +specific-branch:master

And come up with something like (removed error checking to reduce code):

git_libgit2_init();
git_repository* repo = nullptr;
git_repository_init(&repo, "./new.git", true);
git_remote_create(&remote, repo, "origin", "./new.git");
git_remote_add_push(repo, "origin", "+specific-branch:master");
git_push_options optionsPush = GIT_PUSH_OPTIONS_INIT;
git_remote_push(remote, nullptr, &optionsPush);

What I'm not really sure is where to go from here and how to invoke git_remote_push() properly where it actually does something. This currently has no side effects, as ./old.git is not referenced. That is, ./new.git is created properly, but it doesn't contain contents of ./old.git/./old/*.

Help much appreciated.


Based on an answer suggesting a "fetch" approach, I've also attempted the following:

git_repository* repo = nullptr;
if (git_repository_init(&repo, "./new.git", true)) {
    FATAL();
}
git_remote* remote;
git_remote_create_anonymous(&remote, repo, "./old");
char* specs[] = { _strdup("specific-branch:master"), nullptr };
git_strarray refspecs;
refspecs.count = 1;
refspecs.strings = specs;
if (git_remote_download(remote, &refspecs, NULL)) {
    FATAL();
}

This still has no effect.

like image 847
Mike Weir Avatar asked May 22 '18 00:05

Mike Weir


1 Answers

In straight git the most flexible and direct method (as it doesn't require you to already have the entire repository you only want pieces of) is e.g.

git init --bare new.git; cd $_

git fetch --no-tags ~/src/git next:master    # to fetch and rename a branch
# or
git fetch ~/src/git v2.17.0; git branch master FETCH_HEAD   # full handroll

To do this in libgit2, you can create a repository as usual with git_repository_init and an in-memory "anonymous" remote from a url (i'd hope a path would do as well, check that) with git_remote_create_anonymous, then git_remote_downloadgit_remote_fetch the refspec you want from that.

like image 104
jthill Avatar answered Sep 25 '22 14:09

jthill