How to add a git sub-module to a super-project in code using libgit2

I have successfully created two git repositories (named repo and module) in code using the libgit2 C API and am now trying to add the “module” repository to the “repo” repository as a submodule. I am trying to use the libgit2 git_submodule_add_setup C API to do this. See https://libgit2.github.com/libgit2/#HEAD/group/submodule/git_submodule_add_setup.

The documentation says the following:

  • git push remote repo
  • Git: add vs push vs commit
  • Verbose display of a git add
  • git add multiple files at once
  • is there a command in GIT that has the options of “git add -p” and “git checkout -p” COMBINED?
  • Why does adding an existing repo as a submodule modify .git/config?
  • git_submodule_add_setup:
    This does “git submodule add” up to the fetch and checkout of the submodule contents. It preps a new submodule, creates an entry in .gitmodules and creates an empty initialized repository either at the given path in the working directory or in .git/modules with a gitlink from the working directory to the new repo.

    To fully emulate “git submodule add” call this function, then open the submodule repo and perform the clone step as needed. Lastly, call git_submodule_add_finalize() to wrap up adding the new submodule and .gitmodules to the index to be ready to commit.

    My question is how exactly do I perform the clone operation alluded to above given that the call to git_submodule_add_setup creates a initialised, but empty submodule (with a .git directory inside it)? I have already made several attempts to do the clone using the git_submodule_open and git_clone C APIs, but to no avail. The clone fails because the submodule is not an empty folder. I have read the git_clone C API documentation at and have also familiarised myself with the example code at https://libgit2.github.com/docs/guides/101-samples/#repositories_clone_simple etc., but I am still none the wiser. Some help from those in the the know would be much appreciated.

    I have included a code snippet below to give a flavour of what I have so far.

    namespace bfs = boost::filesystem;
    git_repository * repo = NULL;
    bfs::path const repo_path = bfs::current_path() / "repo";
    std::string const repo_url = repo_path.string();
    git_repository_init(&repo, repo_url.c_str(), 0);
    
    //Add various files to repo index, and commit them...
    
    git_repository * module = NULL;
    bfs::path const module_path = bfs::current_path() / "module";
    std::string const module_url = module_path.string();
    git_repository_init(&module, module_url.c_str(), 0);
    
    //Add various files to moduleindex, and commit them...
    
    git_submodule * submodule = NULL;
    git_submodule_add_setup(&submodule, repo, module_url.c_str(), "module", 0);
    
    //What do I need to do in here to clone the module into position??
    
    git_submodule_add_finalize(submodule);
    git_submodule_free(submodule);
    
    git_repository_free(module);
    git_repository_free(repo);
    

  • Why does `git submodule` require fetching from a remote repository everytime?
  • Knowing the file that a number represents
  • How to commit to particular branch ID without losing the top other commits?
  • Syncing magento database froms development to production
  • Why does git sign with GPG keys rather than using SSH keys?
  • jenkins trigger build if new tag is released
  • One Solution collect form web for “How to add a git sub-module to a super-project in code using libgit2”

    I’ve had my problems with adding submodules as well.
    Here is my Github issue.

    Fortunately, a contributer gave me this working example.

    #include <git2.h>
    #include <assert.h>
    #include <stdio.h>
    
    static int just_return_origin(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload)
    {
        return git_remote_lookup(out, repo, name);
    }
    
    static int just_return_repo(git_repository **out, const char *path, int bare, void *payload)
    {
        git_submodule *sm = payload;
        return git_submodule_open(out, sm);
    }
    
    int main(int argc, char *argv[])
    {
        git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
        git_submodule *sm;
        git_repository *parent, *child;
        int result = 0;
    
        git_libgit2_init();
    
        result = git_repository_open(&parent, "parent");
        assert(!result);
    
        assert(!git_submodule_add_setup(&sm, parent, "file:///tmp/sm/child", "sm_test", 1));
    
        opts.repository_cb = just_return_repo;
        opts.repository_cb_payload = sm;
        opts.remote_cb = just_return_origin;
        opts.remote_cb_payload = sm;
    
        assert(!git_clone(&child, "file:///tmp/sm/child", "sm_test", &opts));
        assert(!git_submodule_add_finalize(sm));
    
        git_submodule_free(sm);
        git_repository_free(child);
        git_repository_free(parent);
        git_libgit2_shutdown();
    
        return 0;
    }
    

    Maybe this example helps you as well (even though this question is rather old).

    Git Baby is a git and github fan, let's start git clone.