Showing posts with label libgit2. Show all posts
Showing posts with label libgit2. Show all posts

Sunday, June 3, 2018

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

Leave a Comment

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.

2 Answers

Answers 1

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_download the refspec you want from that.

Answers 2

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:

  1. git_repository_init the new.git, then
  2. 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); 
Read More

Sunday, April 10, 2016

Programmatically do “Git blame -w” in C#

Leave a Comment

I need to programmatically get the last author of a specific line in the Git history with C#. I tried using libgit2sharp :

var repo = new LibGit2Sharp.Repository(gitRepositoryPath); string relativePath = MakeRelativeSimple(filename); var blameHunks = repo.Blame(relativePath); // next : find the hunk which overlap the desired line number 

But this is the equivalent of the command

git blame <file>

And in fact I need

git blame -w <file> (to ignore whitespace when comparing)

Libgit2sharp do not set the -w switch and don't provide any parameter/option to set it. What are my options ? Do you know any other library compatible with the -w switch of the blame command ?

2 Answers

Answers 1

Maybe using NGIT library will help. That is direct (automatic) port of java JGIT library. Install via nuget package, then:

    static void Main() {         var git = Git.Init().SetDirectory("C:\\MyGitRepo").Call();                     string relativePath = "MyFolder/MyFile.cs";                     var blameHunks = git.Blame().SetFilePath(relativePath).SetTextComparator(RawTextComparator.WS_IGNORE_ALL).Call();         blameHunks.ComputeAll();         var firstLineCommit = blameHunks.GetSourceCommit(0);         // next : find the hunk which overlap the desired line number         Console.ReadKey();     } 

Note SetTextComparator(RawTextComparator.WS_IGNORE_ALL) part.

Answers 2

When I hit similar advanced scenarios where the git lib isn't cutting it, I just shell out using start process to the real git command line. It's not sexy, but it's mighty effective.

Read More