git学习(五)分支管理

分⽀在实际中有什么⽤呢?假设你准备开发⼀个新功能,但是需要两周才能完成,第⼀周你写了50%的代码,如果⽴刻提交,由于代码还没写完,不完整的代码库会导致别⼈无法干活。如果等代码全部写完再⼀次提交,⼜存在丢失每天进度的巨⼤⻛险。现在有了分⽀,就不⽤怕了。你创建了⼀个属于你⾃⼰的分⽀,别⼈看不到,还继续在原来的分⽀上正常⼯作,⽽你在⾃⼰的分⽀上干活,想提交就提交,直到开发完毕后,再⼀次性合并到原来的分⽀上,这样,既安全,⼜不影响别⼈⼯作。

创建与合并分支

每次提交,git都会把它们串成时间线,这就是一个分支,当前只有一个主分支即master分支,head指向master,master指向提交。
git学习(五)分支管理_第1张图片
每提交一次,master向前移动一次。当创建新的分⽀,例如dev时,git新建了⼀个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表⽰当前分⽀在dev上。
git学习(五)分支管理_第2张图片
现在开始,所有操作就在dev分支上了,进行提交时,dev向前移动,master不变。
git学习(五)分支管理_第3张图片
将完成的dev合并到master上,最简单的方式,就是直接把master指向dev的当前提交。
git学习(五)分支管理_第4张图片
新建dev分支,并切换到dev分支

$ git checkout -b dev
Switched to a new branch 'dev'`在这里插入代码片`

xx@xx MINGW64 /d/git-repository/learn_git/test_java (dev)

git checkout命令加上-b参数表⽰创建并切换,相当于以下两条命令:

$ git branch dev //创建
$ git checkout dev //切换

git branch命令查看当前分⽀:

$ git branch
* dev
 master

git branch命令会列出所有分⽀,当前分⽀前⾯会标⼀个*号。
然后在dev分支下修改文件内容,然后切换到master下查看文件,发现修改的内容并没有同步过来,因为那个提交是在dev分⽀上,⽽master分⽀此刻的提交点并没有变。

现在把dev分⽀的内容合并到master分⽀:

$ git merge dev
Updating 511d153..271bc9a
Fast-forward
 test.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

git merge命令⽤于合并指定分⽀到当前分⽀。
合并完成后,就可以放⼼地删除dev分⽀:

$ git branch -d dev
Deleted branch dev (was 271bc9a).

(git branch -D dev为强制删除dev分支)
现在只有master了。

$ git branch
* master

小结:
查看分⽀:git branch
创建分⽀:git branch name
切换分⽀:git checkout name
创建并切换分⽀:git checkout -b name
合并某分⽀到当前分⽀:git merge name
删除分⽀:git branch -d name

冲突解决

创建一个dev分支,修改test.txt内容,并提交。

$ git checkout -b dev
Switched to a new branch 'dev'

xx@xx MINGW64 /d/git-repository/learn_git/test_java (dev)
$ vim test.txt

xx@xx MINGW64 /d/git-repository/learn_git/test_java (dev)
$ git add test.txt

xx@xx MINGW64 /d/git-repository/learn_git/test_java (dev)
$ git commit -m "修改了test.txt文件"
[dev 34374e4] 修改了test.txt文件
 1 file changed, 1 insertion(+)

切换到master分支,也修改tes.txt内容并提交。

$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.

xx@xx MINGW64 /d/git-repository/learn_git/test_java (master)
$ vim test.txt

xx@xx MINGW64 /d/git-repository/learn_git/test_java (master)
$ git add test.txt

xx@xx MINGW64 /d/git-repository/learn_git/test_java (master)
$ git commit -m "master分支下修改了test.txt文件"
[master 2c1cfc0] master分支下修改了test.txt文件
 1 file changed, 1 insertion(+)

接下来将dev合并到master。

$ git merge dev
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.

无法合并,这时候就有了冲突。提交后变成了这样:
git学习(五)分支管理_第5张图片
2个分支都修改了同一个文件,git无法知道哪个修改是有效的,所以只能我们手动解决冲突。
文件内容如下,

$ cat test.txt
哈哈哈哈
oooooooo
<<<<<<< HEAD
master分支修改了文件
=======
我修改了i
>>>>>>> dev

git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,其中<<>>>>dev 是指dev上修改的内容。git不知道我们修改的哪个内容需要保存,哪个需要丢弃。所以我们可以修改test.txt的内容为我们想要的,然后再提交。现在就会变成这样:
git学习(五)分支管理_第6张图片
然后删除dev分支,完成。

分支管理策略

通常,合并分⽀时,如果可能,Git会⽤“Fast forward”模式,但这种模式下,删除分⽀后,会丢掉分⽀信息。如果要强制禁⽤“Fast forward”模式,Git就会在merge时⽣成⼀个新的commit,这样,从分⽀历史上就可以看出分⽀信息。
创建dev分支,并修改文件提交。然后采用禁用“fast forward”方式合并

$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'recursive' strategy.
 test.txt | 1 +
 1 file changed, 1 insertion(+)

因为本次合并要创建⼀个新的commit,所以加上-m参数,把commit描述写进去。
查看分支历史

git log --graph --pretty=oneline --abbrev-commit
*   b4b65e0 (HEAD -> master) merge with no-ff
|\
| * 92d4857 (dev) 修改test.txt
|/
* c09321a (origin/master, origin/HEAD) 提交mm.txt

禁用“fast forward”后,合并像这样:
git学习(五)分支管理_第7张图片

分支策略

实际开发中,我们应该按照⼏个基本原则进⾏分⽀管理:
master分⽀应该是⾮常稳定的,仅⽤来发布新版本,平时不能在上⾯干活;干活都在dev分⽀上,也就是说,dev分⽀是不稳定的,到某个时候,⽐如1.0版本发布时,再把dev分⽀合并到master上,在master分⽀发布1.0版本;每个⼈都在dev分⽀上干活,每个⼈都有⾃⼰的分⽀,时不时地往dev分⽀上合并就可以了。所以,团队合作的分⽀看起来就像这样:
git学习(五)分支管理_第8张图片

Bug分支

当你工作到一半的时候,其他分支有个bug急需修复,工作一半的内容不能提交,所以你可以使用$ git stash,将当前工作现场隐藏起来,修复bug后再恢复工作现场。
首先确定bug所在的分支,假设是dev分支,然后在dev下创建一个临时分支,在临时分支下修复bug,然后切换到dev分支,将临时分支合并,最后删除临时分支。
这时候就可以切换回原来的分支下继续干活了。
使用$ git stash list查看被隐藏的工作现场。

$ git stash list
stash@{0}: WIP on master: b4b65e0 merge with no-ff

然后就可以恢复工作现场了,有2种方式:

  1. $ git stash apply恢复,但是恢复后,stash内容并不会消失。需要⽤$ git stash drop来删除。
  2. 是⽤$ git stash pop,恢复的同时把stash内容也删了。

你可以多次进行stash,恢复的时候,先⽤git stash list查看,然后恢复指定的stash,⽤命令:$ git stash apply stash@{0}

Feature分支

开发中,总有⽆穷⽆尽的新的功能要不断添加进来。添加⼀个新功能时,你肯定不希望因为⼀些实验性质的代码,把主分⽀搞乱了,所以,每添加⼀个新功能,最好在dev分支下新建⼀个feature分⽀,在上⾯开发,完成后,合并到dev分支,最后,删除该feature分⽀。

你可能感兴趣的:(git)