rebase 就是将制定目标分支,或者制定 commit 所在的一条路径,直接插到当前分支或目标分支。(好像有点乱,具体的东西自己去查吧)
简单点说,这不是合并。
当然,虽然不是 merge 但是也会有冲突的可能,所以中途有解决冲突的需要,所以 rebase 操作是分阶段进行的,因此逻辑会复杂一些。
首先尝试打开现有未完成的 rebase
git_rebase* prebase = nullptr;
git_rebase_options rebase_opt = GIT_REBASE_OPTIONS_INIT;
error = git_rebase_open(&prebase, rep, &rebase_opt);
如果存在未完成的 rebase,可以选择继续将其完成,或者把它终止掉
git_rebase_abort(prebase);
在 git_rebase_open 返回 -3 (也就是 GIT_ENOTFOUND ) 表示当前仓库并没有其他未完成的 rebase 可以放心大胆的从头开始搞。
接下来创建一个 rebase
git_rebase* prebase = nullptr;
git_rebase_options rebase_opt = GIT_REBASE_OPTIONS_INIT; git_reference* onto_branch = nullptr;
git_annotated_commit* onto = nullptr;
git_branch_lookup(&onto_branch, rep, "new", GIT_BRANCH_LOCAL); git_annotated_commit_from_ref(&onto, rep, onto_branch);
git_rebase_init(&prebase, rep,
nullptr /* current branch */,
nullptr /* upstream */ ,
onto /* branch to rebase onto */,
&rebase_opt);
init 的第三个参数是需要被操作的分支,传空表示当前分支;第四个参数和第五个参数这俩二选一,前者表示以一个 commit 为节点把到这个节点为止的一条链合并到目标分支;后者是直接选一个分支的最新一个 commit ,将这个分支的整条链合并到目标分支。
当然,这个时候工作区不会有任何变化。到 .git 文件夹里面会看到多了一个叫做 rebase-merge 的文件夹。如果这个时候程序被终止,这个文件夹会保留,在下一次启动的时候,就可以通过 git_rebase_open 打开这个 rebase 。
接下来就是实际执行 rebase 这个操作
git_rebase_operation* operation = nullptr;
git_rebase_next(&operation, prebase)
这里可能存在遍历,但是为什么会有多个 operation 我也还没搞太明白,不过为了避免出事,还是循环调用保险一些:
while (git_rebase_next(&operation, prebase) != GIT_ITEROVER)
接下来,不要忘记查看是否有冲突,需要将冲突解决才可以做后边的 commit 的操作:
// reslove conflicts
git_repository_index(&index, rep);
if (git_index_has_conflicts(index))
{
// git checkout --theirs
git_checkout_options opt = GIT_CHECKOUT_OPTIONS_INIT;
opt.checkout_strategy |= GIT_CHECKOUT_USE_THEIRS;
git_checkout_index(rep, index, &opt);
}
// add
git_index_update_all(index, nullptr, nullptr, nullptr);
git_index_write(index);
在解决完冲突,并且 add 之后,就可以 commit 了。这里并不需要使用 commit 的 create 接口,rebase 部分提供了 rebase 专用的 commit 接口。
git_signature* me = nullptr;
git_oid new_commit;
git_signature_now(&me, "XiaochenFTX", "xiaochenftx@gmail.com");
git_rebase_commit(&new_commit, prebase, me, me, "UTF-8", "new rebase");
最后,做一下收尾 finish 掉这个 rebase 操作
git_rebase_finish(prebase, me);
示例代码:sample13