Git分支操作

Git分支操作

这篇文章主要说明如何使用分支使我们的开发工作更加顺滑。

git branch 用法

1
2
3
4
5
git branch //列出所有分支
git branch <branch> //创建名为<branch>的分支,但是不会切换过去
git branch -d <branch> //删除指定分支,这是一个安全操作,git会阻止你删除包含未合并更改的分支
git branch -D <branch> //强制删除分支
git branch -m <branch> //重新命名当前分支

在日常开发中,无论是修复一个我们不稳定bug或者是添加一个功能,我们都应该新建一个分支来封装我们的修改。这样可以保证我们不稳定的代码永远不会提交到主分支上。

  1. 创建分支
    分支只是指向提交的指针,当你创建新分支,实际上只是创建了一个新的指针,仓库本身不会受到影响,一开始你的仓库只有一条分支:

    git branch

    然后你执行下面的命令创建一个分支,用于加一个新的feature:

    git branch

    当然执行后,你只是创建了这个分支,还需要执行git checkout new-feature切换到new-feature分支,然后在使用git add,git commit

  1. 删除分支
    假如你已经开发完了new-feature ,并且已经commit代码了,你就可以自由的删除这个分支了。git branch -d new-feature
    如果分支没有合入master,会报下面的错误:

    1
    2
    error: The branch 'new feature' is not fully merged.
    If you are sure you want to delete it, run 'git branch -D crazy-experiment'.

    这时候你就可以合并分支,如果你真的确定要删除分支,可以使用-D执行强制删除:git branch -D new-feature

  2. 切换分支(git checkout)

    git checkout命令允许你切换到用git branch创建的分支。切换分支会更新当前工作目录中的文件,还可以使用git log查看当前分支的历史。

    1
    2
    3
    git checkout <existing-branch> //切换到一个已有分支上
    git checkout -b <new-branch> //创建时进行直接切换
    git checkout -b <new-branch> <existing-branch> //在已有的分支上创建分支,原来的分支是新分支的基

    git branchgit checkout是一对兄弟,你可以使用git checkout在不同的分支或者bug分支之间切换,而不产生影响。

  3. 合并(git merge)
    合并是git将被fork的历史放回到一起的方式。git merge命令允许你将git branch创建的多条分支合并成一个。

    1
    2
    git merge <branch> //将指定分支并入当前分支
    git merge --no-ff <branch> //经指定分支并入当前分支,但总是生成一个合并提交(即是快速向前合并)。这可以用来记录仓库中发生的所有合并。

一旦在分支上完成开发,我们需要把新分支的提交合并到主分支,git会根据目前分支之间的结构信息,选择不同的算法来完成合并。

  • 快速向前合并
  • 三路合并

快速向前合并

当new-feature的分支与原有的master分支呈现线性关系时,执行快速向前合并,git将当前的HEAD指针快速移到目前分支的顶端,master分支也就拥有了new-feature分支的历史了,

来看一个快速向前合并的实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 开始新功能
git checkout -b new-branch master
# 编辑文件
git add <file>
git commit -m '开始新功能'
# 编辑文件
git add <file>
git commit -m '完成功能'
# 合并new-feature分支
git checkout master
git merge new-feature
git branch -d new-feature

git branch

对于合作开发的人少的项目,这是一种主要的工作流,合作开发的人多的话,主master分支经常会有新提交,如果你的new-feature耗时比较久,再提交时,master分支就可能过去几个版本了,这时候就需要下面的三路合并了。

三路合并

如果master分支在new-feature分离后,又有了新的提交,即开始分叉了,git只能执行三路合并,三路合并使用一个专门的提交来合并两个分支的历史。

git branch

所谓的三路也就是:两个分支的顶端以及他们共同的祖先。在执行三路合并后:

git branch

使用三路合并产生的合并提交作为两个分支的连接标志。

解决冲突

如果两个分支对同一个文件的同一部分均有修改时,git将无法判断应该使用哪个,这时候合并提交会停止,需要你手动解决这些冲突。你可以使用git status来查看哪里存在冲突,也可以在目录下执行grep -rn HEAD来查看哪些文件里有这个标记,有这个的地方都是有冲突的。

当修改完所有的冲突后,git add所有的冲突文件,运行git commit生成一个合并提交,这和提交一个普通快照的流程相同。提交冲突只会存在三路合并中,快速向前合并中不可能出现针对同一文件同一部分的不一样的修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 开始新功能
git checkout -b new-feature master
# 编辑文件
git add <file>
git commit -m '开始新功能'
# 编辑文件
git add <file>
git commit -m '完成功能'
# 在master分支上开发
git checkout master
# 编辑文件
git add <file>
git commit -m '在master上添加了一些及其稳定的功能'
# 合并new-feature分支
git merge new-feature
git branch -d new-feature

这时候,merge会停止,因为无法将master直接移动到new-feature。所有需要你手动合并冲突后在提交。