实验室有了服务器之后,终于过上了本地开发->推送远程->服务器更新代码
的幸福生活,也更加感受到了Git
的强大神力。靠Try Git
打下的基础就显得有些捉襟见肘了,查资料的时候Google大神给出了开源的Pro Git的中译版,豆瓣评分9.0,算得上相当不错了,见这里.
今天扫了一下第二章,基本上就是Try Git
课程的内容。出于近期的需求,详细读了第三章分支
,书写得很清楚,除了介绍命令,还介绍了一些底层实现,配合分支变化的插图,很容易理解。
自己也看了5, 6份关于Git的书籍,tutorial, 在线课程等等,推荐新手按照Try Git
->Pro Git
的学习路线,基本能够满足日常生活的需求。
Try Git的笔记之前已经po过了,点击下面的按钮阅读Pro Git
第三章分支的笔记。
分支
分支的新建与合并
本章的第一个高能!
分支的特性使得Git如此强大和迷人,作者是这么评论的
有人把
Git
的分支模型称为“必杀技特性”,而正是因为它,将Git
从版本控制系统家族里区分出来。…Git
鼓励在工作流程中频繁使用分支与合并,哪怕一天之内进行许多次都没有关系。理解分支的概念并熟练运用后,你才会意识到为什么Git
是一个如此强大而独特的工具,并从此真正改变你的开发方式。
这也是我最初被Git
吸引的原因:能够将还在开发的不完善代码和稳定版的代码分开,不用担心反复试验的误操作带来的影响。
工作流程
- 新建分支
- 在新分支上进行开发
- 将新分支与主分支进行合并(
merge
命令)
有时两个分支中的代码会出现冲突,任何包含未解决冲突的文件都会以未合并(unmerged
)的状态列出。发生冲突的文件将列出两个分支的不同之处,由开发者手动解决冲突,运行git add
将把它们标记为已解决状态,最后用git commit
提交,KO! - 如果不再需要新分支,
git branch -d [branch_name]
删除分支
利用分支进行开发
开发流程中的实践,分支管理的两种模式:长期分支和特性分支
当你在使用分支及合并的时候,一切都是在你自己的 Git 仓库中进行的 — 完全不涉及与服务器的交互。
注
:分支的新建与合并
和利用分支进行开发
这两节包括了几个实例,和多图讲解,看例子会比较容易明白。
远程分支
除了本地分支,还可以建立远程仓库的分支。用 (远程仓库名)/(分支名)
这样的形式表示远程分支。
git clone
执行后,Git 会自动为你将此远程仓库命名为origin
,并下载其中所有的数据,建立一个指向它的master
分支的指针,在本地命名为origin/master
,但无法在本地更改其数据。接着,Git 建立一个属于你自己的本地master
分支,始于origin
上master
分支相同的位置,你可以就此开始工作. 这种对应关系使得git pull
和git push
命令能够正常工作。
删除远程分支
如果不再需要某个远程分支了,比如搞定了某个特性并把它合并进了远程的master
分支(或任何其他存放稳定代码的分支),可以用这个非常无厘头的语法来删除它:git push [远程名] :[分支名]
(此处为原文照排,注意:
前的空格!)。辅助记忆
: 参考git push [远程名] [本地分支]:[远程分支]
语法,如果省略[本地分支]
,那就等于是在说“在这里提取空白然后把它变成[远程分支]
”。
衍合rebase
把一个分支中的修改整合到另一个分支的办法有两种:merge
和rebase
. 在基础教程里会介绍merge
的概念,在之前分支合并
小节也介绍过,而rebase
这个概念还是第一次看到。
原文在这里举了一个例子帮助大家理解,确实看完以后就能对merge
和rebase
的区别有一个了解。
简而言之,merge
将两个分支最新的快照及二者最新的共同祖先进行三方合并,合并的结果是产生一个新的提交对象,并更新master
分支的指针,指向新生成的提交对象。而rebase
把分支A里提交的改变移到分支B里重放一遍,从而改写A的提交历史,使它成为B分支的直接下游。对rebase
而言,所有修改都是在一根线上先后进行的,尽管实际上它们原本是同时并行发生的。
衍合的优点
- 能产生一个更为整洁的提交历史
- 得到一个能在远程分支上干净应用的补丁
衍合的风险
只要遵守下面这条金科玉律:
一旦分支中的提交对象发布到公共仓库,就千万不要对该分支进行衍合操作。
作者的解释:在进行衍合的时候,实际上抛弃了一些现存的提交对象而创造了一些类似但不同的新的提交对象。如果你把原来分支中的提交对象发布出去,并且其他人更新下载后在其基础上开展工作,而稍后你又用git rebase
抛弃这些提交对象,把新的重演后的提交对象发布出去的话,你的合作者就不得不重新合并他们的工作,这样当你再次从他们那里获取内容时,提交历史就会变得一团糟。
如果把衍合当成一种在推送之前清理提交历史的手段,而且仅仅衍合那些尚未公开的提交对象,就没问题。如果衍合那些已经公开的提交对象,并且已经有人基于这些提交对象开展了后续开发工作的话,就会出现叫人沮丧的麻烦。