这篇一锅粥把主要的分支操作全都铺上来。
这里有一个基础概念需要复习一下,分支本质上上指的就是 reference ,在 .git/refs 中可以找到它们的信息。分支分为本地和远端,这里我们先不考虑远端分支,在之后介绍完联网操作之后再说。
所有内容:
git branch 列出所有分支
git branch <branch name> 新建分支
git branch -d <branch name> 删除分支
git branch -m <branch name> 分支改名
git checkout <branch name> 切换分支
1. git branch
主要使用 git_branch_iterator 对分支进行遍历。代码很简单,应该很好理解,就直接贴出来了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
git_branch_iterator* branch_iterator = nullptr; git_reference* tmp_branch = nullptr; git_branch_t branch_type; // list branch git_branch_iterator_new(&branch_iterator, rep, GIT_BRANCH_LOCAL); while (GIT_ITEROVER != git_branch_next(&tmp_branch, &branch_type, branch_iterator)) { const char* branch_name; git_branch_name(&branch_name, tmp_branch); bool is_head = git_branch_is_head(tmp_branch); if (is_head) { std::cout<< "*"; } std::cout<< "name: " << branch_name <<std::endl; } |
可以看一下 git_branch_t ,它实际上就是一个超简单的枚举类型,标示出本地和远端分支:
1 2 3 4 5 6 |
/** Basic type of any Git branch. */ typedef enum { GIT_BRANCH_LOCAL = 1, GIT_BRANCH_REMOTE = 2, GIT_BRANCH_ALL = GIT_BRANCH_LOCAL|GIT_BRANCH_REMOTE, } git_branch_t; |
git_branch_is_head,就是判断这个分支是否是当前工作分支。也就是判断这个 reference 是不是 head 。
2. git branch <branch name>
流程就是:找到源分支 → 取到最后一次 commit → 基于这个 commit 创建新的分支
那么如果这个分支并没有 commit 呢?那么这肯定是一个一次都没提交过的仓库,这种情况可以用命令行做一个测试:
1 2 |
$ git branch dev fatal: Not a valid object name: 'master'. |
实际上 git 并不支持这种行为。
所以新建分支的代码就是这样:
1 2 3 4 5 6 7 8 9 |
git_reference* head = nullptr; git_reference* new_branch = nullptr; const git_oid* commit_id = nullptr; git_commit* last_commit = nullptr; git_repository_head(&head, rep); commit_id = git_reference_target(head); git_commit_lookup(&last_commit, rep, commit_id); git_branch_create(&new_branch, rep, "new"/* branch name */, last_commit, 0); |
3. git branch -d <branch name>
很简单,先找到目标分支,然后调接口删之
1 2 3 4 5 6 |
git_reference* lookup_branch = nullptr; git_branch_lookup(&lookup_branch, rep, "new"/* branch name */, GIT_BRANCH_LOCAL); if (lookup_branch != nullptr && !git_branch_is_head(lookup_branch)) { git_branch_delete(lookup_branch); } |
删除分支要保证被删分支不是当前 head 分支,否则会报错
4. git branch -m <branch name>
跟删除分支差不多,先根据分支名找到要改名字的分支,然后调一个接口做改名操作
1 2 3 4 5 |
git_reference* lookup_branch = nullptr; git_reference* renamed_branch = nullptr; git_branch_lookup(&lookup_branch, rep, "new"/* old name */, GIT_BRANCH_LOCAL); git_branch_move(&renamed_branch, lookup_branch, "new3"/* new name */, 0); |
5. git checkout <branch name>
就是把当前工作分支(head)切换成指定的分支
1 2 3 |
git_reference* lookup_branch = nullptr; git_branch_lookup(&lookup_branch, rep, "new"/* branch name */, GIT_BRANCH_LOCAL); git_repository_set_head(rep, git_reference_name(lookup_branch)); |
git_repository_set_head 这个接口需要的名字不是简单的分支名,而是一个 reference 的全名(refs/heads/new),所以需要使用 git_reference_name 来取一下。
代码示例 sample6