将提交推送到 GitHub

Pushing a commit to GitHub

一段时间以来,我一直在尝试将使用 libgit2 创建的提交推送到 github,我已经设法克服了很多我面临的问题,但是 "final" on 是实际推送提交,因为目前它没有错误,但实际上似乎也不起作用。所以我的代码是这样的(为简洁起见,我省略了所有错误检查):

...
git_commit_create(...); // create the commit
...
git_remote_lookup(&remote, _repo, "origin");
git_remote_init_callbacks(&cbs, GIT_REMOTE_CALLBACKS_VERSION);
cbs.credentials = my_git_cred_cb;
git_remote_connect(remote, GIT_DIRECTION_PUSH, &cbs, NULL, NULL);
git_remote_add_push(_repo, "origin", "refs/heads/master:refs/heads/master");
git_push_options_init(&options, GIT_PUSH_OPTIONS_VERSION);
options.callbacks = cbs;
git_remote_upload(remote, null, &options);
git_remote_disconnect(remote);
git_remote_free(remote);

所有这些函数都通过了,没有返回错误,但是,提交还没有被推送。我的猜测是我的 refspec (refs/heads/master:refs/heads/master) 已关闭 - 我尝试了很多其他的,但我只是在兜圈子。我在这里做错了什么吗,有没有其他人使用 libgit2 将提交完全推送到 github 存储库?任何帮助/指点将不胜感激!

所以,感谢 Jason Haslam 的评论,我已经设法弄明白了,因为 libgit2 完整示例看起来有点单薄,我发布了我自己的解决方案作为答案,它可能会对其他人有所帮助。为了简洁起见,我省略了错误和明显的变量创建。

// open reop
git_repository_open_(&repo, "path/to/repo");
// add commit
git_signature_now(&sig, "Name", "Email");
git_repository_index(&index, repo);
git_index_add_bypath(index, "some_test_file.txt");
git_index_write_tree(&tree_oid, index);
git_tree_lookup(&tree, repo, &tree_oid);
git_reference_name_to_id(&parent_oid, repo, "HEAD");
git_commit_lookup(&parent, repo, &parent_oid);
git_commit_create(&oid_commit, repo, "HEAD", sig, sig, null, "commit message", tree, 1, &parent);
// ... free all created objects

// push to github
git_remote_lookup(&remote, repo, "origin");
git_remote_init_callbacks(&cbs, GIT_REMOTE_CALLBACKS_VERSION);
cbs.credentials = &my_git_cred_cb;
git_push_options_init(&options, GIT_PUSH_OPTIONS_VERSION);
options.callbacks = cbs;

char *refspec_strings[] = {
    "HEAD:refs/heads/master",
};
git_strarray refspec_array = {
    refspec_strings,
    1,
};

git_remote_push(remote, &refspec_array, &options);
git_remote_upload(remote, null, &options);

git_repository_state_cleanup(repo); // not sure this is needed

char *pathspec_strings[] = {
    "HEAD",
};
git_strarray pathspec_array = {
    pathspec_strings,
    1,
};

git_reset_default(repo, null, &pathspec_array); // needed to reset to stop "git status" showing anything - not sure why it does
git_remote_disconnect(remote);
// ... free all created objects

积分回调非常简单:

int my_git_cred_cb(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *payload) {
    if ((allowed_types & GIT_CREDTYPE_USERPASS_PLAINTEXT) != 0) {
        return git_cred_userpass_plaintext_new(cred, "gh_user", "gh_pass");
    } else {
        /* Some other kind of authentication was requested */
        return -1;
    }

    return 1; /* unable to provide authentication data */
}