分支

什么是分支

分支是为了将修改记录的整体流程分叉保存。分叉后的分支不受其他分支的影响,所以在同一个数据库里可以同时进行多个修改。

master分支

在数据库进行最初的提交后, Git会创建一个名为master的分支。因此之后的提交,在切换分支之前都会添加到master分支里。

分支的运用

merge分支

Merge分支是为了可以随时发布release而创建的分支,它还能作为Topic分支的源分支使用。保持分支稳定的状态是很重要的。如果要进行更改,通常先创建Topic分支,而针对该分支,可以使用Jenkins之类的CI工具进行自动化编译以及测试。

通常,大家会将master分支当作Merge分支使用。

Topic分支

Topic分支是为了开发新功能或修复Bug等任务而建立的分支。若要同时进行多个的任务,请创建多个的Topic分支。

Topic分支是从稳定的Merge分支创建的。完成作业后,要把Topic分支合并回Merge分支。

分支的切换

若要切换作业的分支,就要进行checkout操作。进行checkout时,git会从工作树还原向目标分支提交的修改内容。checkout之后的提交记录将被追加到目标分支

HEAD指向的是现在使用中的分支的最后一次更新。通常默认指向master分支的最后一次更新。通过移动HEAD,就可以变更使用的分支。
NOTE:提交时使用~(tilde)和^(caret)就可以指定某个提交的相对位置。最常用的就是相对于HEAD的位置。HEAD后面加上~(tilde)可以指定HEAD之前的提交记录。合并分支会有多个根节点,您可以用^(caret) 来指定使用哪个为根节点。

stash

stash是临时保存文件修改内容的区域。stash可以暂时保存工作树和索引里还没提交的修改内容,您可以事后再取出暂存的修改,应用到原先的分支或其他的分支上。

分支的合并

合并分支有2种方法:使用merge或rebase。使用这2种方法,合并后分支的历史记录会有很大的差别。

merge

合并 bugfix分支到master分支时,如果master分支的状态没有被更改过,把master分支的位置移动到bugfix的最新分支上,Git 就会合并。这样的合并被称为fast-forward(快进)合并。HEAD还在原位。
master分支的历史记录有可能在bugfix分支分叉出去后有新的更新。这种情况下,要把master分支的修改内容和bugfix分支的修改内容汇合起来。合并两个修改会生成一个提交。这时,master分支的HEAD会移动到该提交上。
NOTE:执行合并时,如果设定了non fast-forward选项,即使在能够fast-forward合并的情况下也会生成新的提交并合并。

non_fast_forward

一个圆圈代表一个提交

rebase

topic分支和merge分支的运用实例

分支操作示例

建立分支

$ git branch < branchname>

不指定参数直接执行branch命令的话,可以显示分支列表。 前面有*的就是现在的分支。

$ git branch
issue1
*master

切换分支

执行checkout命令以退出分支。

$ git checkout < branch>

NOTE:在checkout命令指定 -b选项执行,可以创建分支并进行切换。

$ git checkout -b < branch>

合并分支

执行merge命令以合并分支。

$ git merge < commit>

该命令将指定分支导入到HEAD指定的分支。如当HEAD指向issue1时,先切换到master分支,然后把issue1分支导入到master分支。

$ git checkout master
$ git merge issue1

删除分支

在branch命令指定-d选项执行,以删除分支。

$ git branch -d < branchname>

用rebase合并

切换到issue3分支后,对master执行rebase。

$ git checkout issue3
$ git rebase master

rebase的时候,修改冲突后的提交不是使用commit命令,而是执行rebase命令指定 –continue选项。若要取消rebase,指定 –abort选项。

$ git add myfile.txt
$ git rebase –continue

这样,在master分支的issue3分支就可以fast-forward合并了。切换到master分支后执行合并.看来rebase是将issue3分支消失而生成一个新的提交,就像fast-forward的情形一样。
切换到master分支后执行合并。

$ git checkout master
$ git merge issue3

rebase

上图为rebase图

merge

上图为merge图

Merge和rebase都是合并历史记录,但是各自的特征不同。

merge
保持修改内容的历史记录,但是历史记录会很复杂。
rebase
历史记录简单,是在原有提交的基础上将差异内容反映进去。
因此,可能导致原本的提交内容无法正常运行。
您可以根据开发团队的需要分别使用merge和rebase。
例如,想简化历史记录,
在topic分支中更新merge分支的最新代码,请使用rebase。
向merge分支导入topic分支的话,先使用rebase,再使用merge。

远端数据库

pull

首先确认更新的本地数据库分支没有任何的更改。这时只执行fast-forward合并。
如果本地数据库的分支有新的历史记录,就需要合并双方的修改。
执行pull就可以进行合并。这时,如果没有冲突的修改,就会自动创建合并提交。如果发生冲突的话,要先解决冲突,再手动提交。

fetch

执行pull,远程数据库的内容就会自动合并。但是,有时只是想确认本地数据库的内容而不想合并。这种情况下,请使用fetch。
执行fetch就可以取得远程数据库的最新历史记录。取得的提交会导入到没有名字的分支,这个分支可以从名为FETCH_HEAD的退出。
就相当于在本地数据库建立了一个和远程数据库一样的分支,还没合并。
合并后,历史记录会和pull相同。实际上pull的内容是fetch + merge组成的。

push

从本地数据库push到远程数据库时,要fast-forward合并push的分支。如果发生冲突,push会被拒绝的。
若要共享在本地数据库创建的分支,需要明确的push。因此,没有执行push就不会给远程数据库带来影响,因而可以自由的创建自己的分支。
基本上,远程数据库共享的提交是不能修改的。如果修改的话,跟远程数据库同步的其他数据库的历史记录会变得很奇怪的。

标签

标签是为了更方便地参考提交而给它标上易懂的名称。
Git可以使用2种标签:轻标签和注解标签。打上的标签是固定的,不能像分支那样可以移动位置。
轻标签:添加名称
注解标签:添加名称 添加注解 添加签名
一般情况下,发布标签是采用注解标签来添加注解或签名的。轻标签是为了在本地暂时使用或一次性使用。

使用标签

使用tag命令来添加标签,在< tagname>执行标签的名称。

$ git tag < tagname>

在HEAD指向的提交里添加名为apple的标签,请执行以下的命令。

$ git tag apple

如果没有使用参数而执行tag,可以显示标签列表。

$ git tag

如果在log命令添加 –decorate选项执行,可以显示包含标签资料的历史记录。

$ git log –decorate

添加注解标签

若要添加注解标签,可以在tag命令指定 -a选项执行,以指定-m选项来添加注解。

$ git tag -a < tagname>

$ git tag -am “连猴子都懂的Git” banana

如果在tag命令指定-n选项执行,可以显示标签的列表和注解。

$ git tag -n

删除标签

若要删除标签,在tag命令指定 -d选项执行。

$ git tag -d < tagname>

改写提交

修改最近的提交

指定amend选项执行提交的话,可以修改同一个分支最近的提交内容和注解。

主要使用的场合:
添加最近提交时漏掉的档案
修改最近提交的注解

取消过去的提交

在revert可以取消指定的提交内容。使用后面要提到的rebase -i或reset也可以删除提交。但是,不能随便删除已经发布的提交,这时需要通过revert创建要否定的提交。

主要使用的场合:
安全地取消过去发布的提交

遗弃提交

在reset可以遗弃不再使用的提交。执行遗弃时,需要根据影响的范围而指定不同的模式,可以指定是否复原索引或工作树的内容。
除了默认的mixed模式,还有soft和hard模式。欲了解受各模式影响的部分,请参照下面的表格。

模式名称 HEAD的位置 索引 工作树
soft 修改 不修改 不修改
mixed 修改 修改 不修改
hard 修改 修改 修改

主要使用的场合:

复原修改过的索引的状态(mixed)
彻底取消最近的提交(hard)
只取消提交(soft)

提取提交

在cherry-pick,您可以从其他分支复制指定的提交,然后导入到现在的分支。

主要使用的场合:

把弄错分支的提交移动到正确的地方
把其他分支的提交添加到现在的分支

改写提交历史记录

在rebase指定i选项,您可以改写、替换、删除或合并提交。

主要使用的场合:

在push之前,重新输入正确的提交注解
清楚地汇合内容含义相同的提交。
添加最近提交时漏掉的档案

汇合分支上的提交,然后一同合并到分支

merge的特殊选项:squash
用这个选项指定分支的合并,就可以把所有汇合的提交添加到分支上。

主要使用的场合:

汇合主题分支的提交,然后合并提交到目标分支。

改写提交训练

commit –amend

git commit –amend

revert

$ git revert HEAD

在git log中会出现–Revert “添加pull的说明”

reset

$ git reset –hard HEAD~~

在git中,我们其实可以通过^和~来定位某个具体的commit,而不用每次都去敲繁琐的hash值。
“^”代表父提交,当一个提交有多个父提交时,可以通过在”^”后面跟上一个数字,表示第几个父提交,”^”相当于”^1”.
~< n>相当于连续的< n>个”^”.
在reset之前的提交可以参照ORIG_HEAD。Reset错误的时候,在ORIG_HEAD上reset 就可以还原到reset前的状态。

$ git reset –hard ORIG_HEAD

cherry-pick

$ git checkout master
$ git cherry-pick 99daed2

如果发生冲突,修改冲突的部分之后再提交。

用rebase -i 汇合提交

若要汇合过去的提交,请用rebase -i。

$ git rebase -i HEAD~~

两个提交就合并成一个提交了。

用rebase -i 修改提交

merge –squash