分支

2023-01-12 更新

1 新建

master 是默认分支但并不特殊,跟其它分支没有区别。之所以个个仓库都有 master 分支,是因为 git init 时默认新建,而大多数人又懒得改。后来为了所谓的政治正确, git 将默认分支定为 main ,建议去配置文件里改回来。

Git 是怎么新建分支的呢?很简单,它只是新建了一个指向提交对象的指针。

$ git branch testing

注意, git branch 仅新建分支,不会自动切换到新分支,此时你仍然在 master 分支上。

two-branches

Git 又是怎么知道当前在哪个分支上呢?也很简单,有一个名为 HEAD 的二级指针指向当前所在的本地分支。

head-to-master

2 切换

$ git checkout another_branch

3 贮藏

只有干净的分支才能顺利地切换,对有修改又不提交的内容,我们必须使用命令 git stash 临时贮藏起来。 git stash -u 更加保险,新建的文件也一并贮藏。

$ git stash list
$ git stash apply
$ git stash drop
$ git stash pop = git stash apply + git stash drop

git clean 可以直接丢弃所有当前修改,此时的分支也是干净的。

4 合并

$ git merge branch_name

注意合并方向。

个人经验:语法意为将其它分支合入当前分支。合并的不只是已经提交的部分,还包括未提交的部分。有待进一步确认。

4.1 没有冲突的双方合并

$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
 index.html | 2 ++
 1 file changed, 2 insertions(+)

fast-forward 表示合并操作没有需要解决的冲突。

basic-branching-5

紧急问题解决后删除 hotfix 分支 git branch -d hotfix,因为你已经不再需要它了。

4.2 没有冲突的三方合并

这和你之前合并 hotfix 分支有点不一样,你的开发历史在一次提交后分叉(diverged), master 分支所指的提交对象并不是 iss53 分支所指的提交对象的直接祖先。出现这种情况时,Git 会使用两个分支的末端所指的提交对象(C4 和 C5)以及这两个分支的工作祖先(C2),做一个简单的三方合并。

basic-merging-1

basic-merging-2

4.3 有冲突的三方合并

如果你在 iss53 里的修改和在 hotfix 里的修改涉及到同一文件的同一处,合并它们时就会产生冲突。此时 Git 合并但不提交,停下来等待你去解决冲突。标准冲突解决标记如下:

<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> iss53:index.html

你必须在 ======= 分割的两部分中二选一。解决冲突后,<<<<<<< =======>>>>>>> 这些行必须完全删除,并通过 git add 命令将它们标记为冲突已解决。

git mergetool 会启动一个合适的可视化合并工具,前提是你已配置 merge.tool

5 管理

5.1 稳定分支

许多开发者都喜欢只在 master 分支上保留完全稳定的代码,用一些名为 develop 或者 next 的平行分支来做后续的开发和测试。稳定分支的指针总是在提交历史中落后一大截,而特性分支的指针往往比较靠前,就像流水线一样。

lr-branches-2

5.2 特性分支

任何规模的项目都应该有特性分支,它是一种短期分支,往往工作单一。

5.3 异根分支

强迫症的福音:借助 checkout 我们甚至可以直接创建新的空白分支!创建完先清空工作目录。

$ git checkout --orphan <branchname>
$ git rm --cached -r .

注意,此时 git branch 无法观察到该空白分支,因为它没有任何提交记录,是一个空指针,当第一次提交完成后,它才有名有实。随后你将遇到一堆诸如 fatal: refusing to merge unrelated histories 麻烦事,不得不附加 --allow-unrelated-histories 强制执行命令。