libgit2使用教程(三) git commit

首先去看 API 中关于 commit 的部分都有哪个函数比较像,但是意外的发现了 API 中并没有官方 101-samples 中的 git_commit_create 函数,搞得我好意外。不过据我所知,实现 commit 操作肯定是要使用这个 git_commit_create 函数了。那咱们先去头文件看看它需要什么参数:

/**
* Create new commit in the repository from a list of `git_object` pointers
*
* The message will **not** be cleaned up automatically. You can do that
* with the `git_message_prettify()` function.
*
* @param id Pointer in which to store the OID of the newly created commit
*
* @param repo Repository where to store the commit
*
* @param update_ref If not NULL, name of the reference that
* will be updated to point to this commit. If the reference
* is not direct, it will be resolved to a direct reference.
* Use "HEAD" to update the HEAD of the current branch and
* make it point to this commit. If the reference doesn't
* exist yet, it will be created. If it does exist, the first
* parent must be the tip of this branch.
*
* @param author Signature with author and author time of commit
*
* @param committer Signature with committer and * commit time of commit
*
* @param message_encoding The encoding for the message in the
* commit, represented with a standard encoding name.
* E.g. "UTF-8". If NULL, no encoding header is written and
* UTF-8 is assumed.
*
* @param message Full message for this commit
*
* @param tree An instance of a `git_tree` object that will
* be used as the tree for the commit. This tree object must
* also be owned by the given `repo`.
*
* @param parent_count Number of parents for this commit
*
* @param parents Array of `parent_count` pointers to `git_commit`
* objects that will be used as the parents for this commit. This
* array may be NULL if `parent_count` is 0 (root commit). All the
* given commits must be owned by the `repo`.
*
* @return 0 or an error code
* The created commit will be written to the Object Database and
* the given reference will be updated to point to it
*/
GIT_EXTERN(int) git_commit_create(
    git_oid *id,
    git_repository *repo,
    const char *update_ref,
    const git_signature *author,
    const git_signature *committer,
    const char *message_encoding,
    const char *message,
    const git_tree *tree,
    size_t parent_count,
    const git_commit *parents[]);

·id 返回一个 OID 的指针,这个 OID 表示的就是新创建的这个 commit
·repo 仓库指针
·update_ref 需要提交的目标引用,使用当前分支的引用就用 “HEAD” 就可以了
·author 作者 git_signature 指针。git_signature 记录作者的名字、email、和一个时间
·committer 提交人也是 git_signature 指针,跟上边可以是同一个
·message_encoding 这次提交说明信息的字符集
·message 这次提交的完整说明
·tree 我们需要传入一个 git_tree 实例的指针,这个 tree 对象必须属于这个仓库。这个 ·tree 将是我们下边要解决的第一个问题
·parent_count 这个 commit 的父级的数量,如果是 merge 后的 commit 会有两个甚至以上,咱们暂时先不考虑分支的事情,所以只玩儿1个的
·parents 是一个 git_commit 指针的数组,表示上一级的提交,如果是第一次 commit 数组应该是空的,同时 parent_count 应该是0。如果不是,咱们就得先把爸爸找出来,这将是下边要解决的第二个问题

1. tree:
这个 tree 实际上就是把 index 的 entry 写到一个 tree 中,最终把这个 tree 提交。从 API 文档可以找到 git_index_write_tree 这个函数。它的作用就是写一个 tree,所以就可以写出下面的代码:

git_oid new_tree_id;
git_tree *new_tree = nullptr;

// write index to tree
error = git_index_write_tree(&new_tree_id, index);
if (error < 0)
{
    const git_error *e = giterr_last();
    std::cout << "Error: " << error << " / " << e->klass << " : " << e->message << std::endl;
    goto SHUTDOWN;
}
else
{
    git_index_free(index);
}
git_tree_lookup(&new_tree, rep, &new_tree_id);

2. parent:
因为我们还先不考虑 merge 的情况,所以父级 commit 只有一个,这个父级实际上就是 head 引用,所以我们第一步先拿出 head。

git_reference* ref_head = nullptr; 
git_repository_head(&ref_head, rep);

这里我们要考虑一个情况:在一个全新的仓库的情况下,是没有之前的 commit 的,因此,取出来的 ref_head 会是空的。所以要做一个判断:

size_t parent_count = 0;
git_commit *parent_commit = nullptr;
const git_commit *parents[] = {nullptr};

// has parent
if (error == GIT_OK)
{
    // get parent commit
    git_commit_lookup(&parent_commit, rep, git_reference_target(ref_head));
    parents[0] = parent_commit;
    parent_count = 1;
    git_reference_free(ref_head);
}
else if (error != GIT_EUNBORNBRANCH)
{
    const git_error *e = giterr_last();
    std::cout << "Error: " << error << " / " << e->klass << " : " << e->message << std::endl;
    goto SHUTDOWN;
}

这样我们就拿到了我们需要的 tree 和 parent commit ,下面就是签名,然后提交了:

git_signature* me = nullptr; 
git_signature_now(&me, "XiaochenFTX", "xiaochenftx@gmail.com”);
git_oid new_commit;
error = git_commit_create(&new_commit,
                                    rep,
                                    "HEAD",
                                    me,
                                    me,
                                    "UTF-8",
                                    "commit message",
                                    new_tree,
                                    parent_count,
                                    parents);

这样 commit 操作就完成了。

示例代码是 sample3
同样放在 github 的 libgit2_samples 中

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

RSS
Follow by Email
YouTube
YouTube
Pinterest
fb-share-icon
LinkedIn
Share
VK
Weibo
WeChat
WhatsApp
Reddit
FbMessenger
Copy link
URL has been copied successfully!