我们在合并分支时,Git会用到”Fast forward“模式,在这种模式下删除分支后会丢掉分支信息。
如果我们要强制禁用”Fast forward“模式,Git就会在merge时生存一个新的commit,这样从分支历史上就可以看出分支信息。
那么,如何强制禁用”Fast forward“模式呢?在merge时 加上参数 --no-ff 即可。
创建并切换一个分支dev:
$ git checkout -b dev
Switched to a new branch 'dev'
修改readme.txt文件并提交:
$ git add readme.txt
$ git commit -m '修改readme'
[dev c835981] 修改readme
1 file changed, 1 insertion(+)
提交完成后切换至master:
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'GitGo/master' by 7 commits.
(use "git push" to publish your local commits)
现在开始合并dev分支到master,在使用merge时使用--no-ff禁用”Fast forward“:
$ git merge --no-ff -m '禁用fast forward方式合并文件' dev
Merge made by the 'recursive' strategy.
readme.txt | 1 +
1 file changed, 1 insertion(+)
因为本次禁用了”Fast forward“合并会创建一个新的commit,所以在后面加上了-m参数,把commit描述写进去。合并后可以使用git log查看分支历史:
$ git log --graph --pretty=oneline --abbrev-commit
* 068ed5b (HEAD -> master) 禁用fast forward方式合并文件
|\
| * c835981 (dev) 修改readme
|/
* da26543 修改文件内容
|\
| * cfc178e 修改Git为git
* | 898bd79 修改文字为繁体字,修改标点符号为英文
|/
* e235cf1 一个新的版本
* 081fd0d 修改后的文件
|\
| * 3b0631c 分支冲突解决学习1
* | 607fe21 修改的今天修改的内容【学习分支冲突解决方法】
|/
* cde8ce3 (GitGo/master) 添加测试文件
* 742b3d0 新增许可证描述文件;修改项目说明文件;
* 53b0c21 添加了一段文字 Add Time:2017-01-05
* 4b7b169 修改描述文档
* 068eefe wrote a readme file
可以从上面的操作历史中看到,不使用"Fast forward"模式,merge后就像这样:
分支策略:
通常在实际的开发中,我们应该按照几个基本原则进行分支管理:
首先,master分⽀应该是非常稳定的,也就是仅用来发布新版本,平时不能在上⾯干活;
那在哪干活呢?干活都在dev分支上,也就是说,dev分⽀是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分⽀发布1.0版本;
你和你的⼩伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。
所以,团队合作的分⽀支看起来就像这样:
小结
Git分支十分强大,在团队开发中应该充分应用。
合并分支时,加上--no-ff参数就可以用普模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。
BUG分支:
软件开发中,产生BUG几乎是我们每天无法避免的一件事。当然,既然有了BUG那就需要修复。比如现有一个BUG需要马上进行修复处理。这个时候,就可以体现出Git中强大的分支管理了。我们可以通过一个临时分支来修复BUG,修复后合并分支,然后将临时分支删除。
但接到一个修复的BUG任务,很自然地想到创建一个分支issue-105来修复他,但是我们当前正在dev上进行着开发工作,这部分代码还没有提交:
$ git status
On branch dev
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: LICENSE.txt
由于我的功能开发到一半,预计开发完成至少还需要1天,很显然这个未完成的代码是不能提交的。但是目前必须需要在最短的时间内修复这个BUG,怎么办?
强大的Git为我们提供了一个stash功能,可以把当前的工作现场”储藏“起来,等以后恢复现场继续工作:
$ git stash
Saved working directory and index state WIP on dev: c835981 修改readme
现在用git status查看工作区:
$ git status
On branch dev
nothing to commit, working tree clean
目前工作区是干净的(除还没有被Git管理的文件),因此可以放心的创建分支来修复Bug。首先得确认修复BUG是在那个分支上。假设我们需要在master上修复该BUG,就在master上创建临时的分支:
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'GitGo/master' by 11 commits.
(use "git push" to publish your local commits)
$ git checkout -b issue-105
Switched to a new branch 'issue-105'
修改文件然后提交:
$ git add test.txt
$ git commit -m '修改BUG'
[issue-105 05372b9] 修改BUG
1 file changed, 1 insertion(+), 1 deletion(-)
提交完成后,切换到master分支,合并issue-105分支,合并完成后删除issue-105分支:
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'GitGo/master' by 11 commits.
(use "git push" to publish your local commits)
$ git merge --no-ff -m '修复BUG105' issue-105
Merge made by the 'recursive' strategy.
test.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
$ git branch -d issue-105
Deleted branch issue-105 (was 05372b9).
好的。BUG105我们已经修复并提交了master了。现在我们需要返回dev继续干刚才没有完成的活。
$ git checkout dev
Switched to branch 'dev'
$ git status
On branch dev
nothing to commit, working tree clean
工作区我们刚刚在dev修改的文件,哪去了?不要着急。用git stash list 命令查看:
$ git stash list
stash@{0}: WIP on dev: c835981 修改readme
dev的工作现场还在,Git只是把stash内容存放在某个地方了,但是需要恢复一下,有两个方法:
1、 使用git stash apply 恢复,但是在恢复后,stash内容并没有删除,需要使用git stash drop 来删除;
$ git stash apply
On branch dev
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: LICENSE.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git stash drop
Dropped refs/stash@{0} (190f697d730a4a7816b3049acf7cf33d6d162162)
2、使用git stash pop,恢复的同时把stash内容也删除了:
$ git stash pop
On branch dev
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: LICENSE.txt
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (62947f8efd82d5b72410cdabd47eaaffa4d53dca)
再用git stash list查看,就看不到任何的stash内容:
可以多次stash,恢复的时候先用git stash list查看队列,然后恢复时指定stash序列;stash的队列是按照的时间的先后顺序倒叙排列的(即时间最新的在前,stash@{0});存在多个stash在不指明恢复序列,默认为队列第一个。
$ git stash list
stash@{0}: WIP on dev: c835981 修改readme
stash@{1}: WIP on dev: c835981 修改readme
stash@{2}: WIP on dev: c835981 修改readme
$ git stash apply stash@{1}
On branch dev
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: LICENSE.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git stash drop stash@{1}
Dropped refs/stash@{1} (159798b0499e0acf7cf33d6d162162a5fff64f0d)
修改BUG时,我们会通过创建新的BUG分支进行修复,然后合并,最后删除;当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复完成后,再git stash pop,重新回到工作现场。