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.
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 eg
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_download
git_remote_fetch
the refspec you want from that.
An alternative (IMHO, the way of the API), since what you're after is a "standard" clone step using a custom upstream branch, would be to use git_clone
's provided customization points (instead of using all the smaller parts/steps).
So something like this should work (C pseudocode):
int main() {
git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
git_repository *repo;
opts.bare = 1;
opts.remote_create_cb = (git_remote_create_cb)git_remote_create_with_fetchspec;
opts.remote_create_payload = "specific-branch:master";
return git_clone(&repo, "./old", "./new", &opts);
}
It looks like you're creating a new repository, and then adding a remote on it and trying to use it to push to itself... If you want to truly emulate your commands, you'll need two repositories:
git_repository_init
the new.git
, then git_repository_open
the old
, and then set up the remote on it , and push it to the new repository. Something along the lines of:
git_repository *old = NULL, *new = NULL;
git_libgit2_init();
git_repository_init(&new, "./new.git", true);
git_repository_free(new);
git_repository_open(&old, "./old");
git_remote_create(&remote, old, "origin", "./new.git");
git_remote_add_push(old, "origin", "+specific-branch:master");
git_remote_push(remote, NULL, NULL);
git_repository_free(old);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.