git工作流介绍--结合sourcetree
git分布式版本控制系统
分布式是如何实现的:

- 服务器上有一个git仓库。完整地克隆服务器上的git仓库生成本地仓库。进行本地开发,开发完成后,提交到本地仓库。在合适的时候将变更推送到服务器仓库。
好处:
- 完全复制代码库,多备份,服务器仓库损坏也没有影响。
- 环境完全隔离,本地如何修改都不会影响其他人。
- 可以离线开发,不需要时时连接服务器。
svn与git的对比
vss--svn--git优缺点
git相关工具
git工作流指南
开发者开始先克隆中央仓库。在自己的项目拷贝中编辑文件和提交修改;但修改是存在本地的,和中央仓库是完全隔离的。开发者可以把和上游的同步延后到一个方便时间点。
要发布修改到正式项目中,开发者要把本地master分支的修改『推』到中央仓库中,推送(push)操作会把所有还不在中央仓库的本地提交都推上去。

冲突解决
中央仓库代表了正式项目,所以提交历史是稳定不变的。如果开发者本地的提交历史和中央仓库有分歧,Git会拒绝push提交。


在开发者提交自己功能修改到中央库前,需要先拉取(fetch)在中央库的新增提交,变基(rebase)自己提交到中央库提交历史之上。

这样做的意思是在说,『我要把自己的修改加到别人已经完成的修改上。』最终的结果是一个完美的线性历史。
如果本地修改和上游提交有冲突,Git会暂停rebase过程,给你手动解决冲突的机会。还有一点,如果解决冲突时遇到麻烦,Git可以很简单中止整个rebase操作,重来一次(或者让别人来帮助解决)。
rebase操作过程是把本地提交一次一个地迁移到更新了的中央仓库master分支之上。
这意味着可能要解决在迁移某个提交时出现的合并冲突,而不是解决包含了所有提交的大型合并时所出现的冲突。
这样的方式让你尽可能保持每个提交的聚焦和项目历史的整洁。反过来,简化了哪里引入Bug的分析,如果有必要,回滚修改也可以做到对项目影响最小。
示例
让我们一起逐步分解来看看一个常见的小团队如何用这个工作流来协作的。有两个开发者小明和小红,看他们是如何开发自己的功能并提交到中央仓库上的。
有人先初始化好中央仓库

第一步,有人在服务器上创建好中央仓库。
所有人克隆中央仓库

下一步,各个开发者创建整个项目的本地拷贝。
基于你后续会持续和克隆的仓库做交互的假设,克隆仓库时Git会自动添加远程别名origin指回中央仓库。
小明开发功能

在小明的本地仓库中,他使用标准的Git过程开发功能:编辑、暂存(Stage)和提交。
如果你不熟悉暂存区(Staging Area),这里说明一下:暂存区的用来准备一个提交,但可以不用把工作目录中所有的修改内容都包含进来。
这样你可以创建一个高度聚焦的提交,即使你本地修改很多内容。

请记住,因为这些命令生成的是本地提交,小明可以按自己需求反复操作多次,而不用担心中央仓库上有了什么操作。
对需要多个更简单更原子分块的大功能,这个做法是很有用的。
小红开发功能

与此同时,小红在自己的本地仓库中用相同的编辑、暂存和提交过程开发功能。和小明一样,她也不关心中央仓库有没有新提交;
当然更不关心小明在他的本地仓库中的操作,因为所有本地仓库都是私有的。
小明发布功能

一旦小明完成了他的功能开发,会发布他的本地提交到中央仓库中,这样其它团队成员可以看到他的修改。

由于中央仓库自从小明克隆以来还没有被更新过,所以推送(push)操作不会有冲突,成功完成。
小红试着发布功能

一起来看看在小明发布修改后,小红push修改会怎么样?
但她的本地历史已经和中央仓库有分岐了,Git拒绝操作并给出下面很长的出错消息:

这避免了小红覆写正式的提交。她要先获取小明的更新到她的本地仓库合并上她的本地修改后,再重试。
小红在小明的提交之上rebase

小红获取上游的修改到自己的仓库中。
选择要变基(衍合 rebase)的位置,这里选择的是origin/master,即变基到中央仓库最新的master上。

小红解决合并冲突

如果小红和小明的功能是不相关的,不大可能在rebase过程中有冲突。
如果有,Git在合并有冲突的提交处暂停rebase过程,输出下面的信息并带上相关的指令:


本例中,小明上游先提交修改了"sdfghjkl!"-->"sdfghjkl1!",小红后提交了修改"sdfghjkl!"-->"sdfghjkl2!"
小红需要打开冲突的文件:

其中
<<<<< HEAD
上游提交修改
======
本次提交修改
>>>>>>>> *******
需要选择使用什么内容,比如说使用"sdfghjkl2!" ,则删除其他上游提交修改以及标识行

暂存修改,完成提交。
再次右键衍合(变基 rebase)


选择继续衍合,完成衍合(变基 rebase)过程。
变基完成后的结果如下图

如果你忘了变基(rebase)操作,推送(pull)仍然可以完成,切换到“文件状态”格外进行一次合并提交,然后再推送。但每次推送(pull)操作要同步中央仓库中别人修改时,提交历史会以一个多余的『合并提交』结尾。

最好是使用rebase而不是生成一个合并提交。
小红成功发布功能

小红完成和中央仓库的同步后,就能成功发布她的修改了。
功能分支工作流
说完了单个分支,下面将对功能分支工作流进行深入讨论
Gitflow工作流通过为功能开发、发布准备和维护分配独立的分支,让发布迭代过程更流畅。严格的分支模型也为大型项目提供了一些非常必要的结构。

Gitflow工作流定义了一个围绕项目发布的严格分支模型。虽然比功能分支工作流复杂几分,但提供了用于一个强壮的用于管理大型项目的框架。
Gitflow工作流没有用超出功能分支工作流的概念和命令,而是为不同的分支分配一个很明确的角色,并定义分支之间如何和什么时候进行交互。
除了使用功能分支,在做准备、维护和记录发布也使用各自的分支。
当然你可以用上功能分支工作流所有的好处:Pull Requests、隔离实验性开发和更高效的协作。
工作方式
Gitflow工作流仍然用中央仓库作为所有开发者的交互中心。和其它的工作流一样,开发者在本地工作并push分支到要中央仓库中。
历史分支
相对使用仅有的一个master分支,Gitflow工作流使用2个分支来记录项目的历史。master分支存储了正式发布的历史,而develop分支作为功能的集成分支。
这样也方便master分支上的所有提交分配一个版本号。

剩下要说明的问题围绕着这2个分支的区别展开。
功能分支
每个新功能位于一个自己的分支,这样可以push到中央仓库以备份和协作。
但功能分支不是从master分支上拉出新分支,而是使用develop分支作为父分支。当新功能完成时,合并回develop分支。
新功能提交应该从不直接与master分支交互。

注意,从各种含义和目的上来看,功能分支加上develop分支就是功能分支工作流的用法。但Gitflow工作流没有在这里止步。
发布分支

一旦develop分支上有了做一次发布(或者说快到了既定的发布日)的足够功能,就从develop分支上fork一个发布分支。
新建的分支用于开始发布循环,所以从这个时间点开始之后新的功能不能再加到这个分支上——
这个分支只应该做Bug修复、文档生成和其它面向发布任务。
一旦对外发布的工作都完成了,发布分支合并到master分支并分配一个版本号打好Tag。
另外,这些从新建发布分支以来的做的修改要合并回develop分支。
使用一个用于发布准备的专门分支,使得一个团队可以在完善当前的发布版本的同时,另一个团队可以继续开发下个版本的功能。
这也打造定义良好的开发阶段(比如,可以很轻松地说,『这周我们要做准备发布版本4.0』,并且在仓库的目录结构中可以实际看到)。
维护分支

维护分支或说是热修复(hotfix)分支用于生成快速给产品发布版本(production releases)打补丁,这是唯一可以直接从master分支fork出来的分支。
修复完成,修改应该马上合并回master分支和develop分支(当前的发布分支),master分支应该用新的版本号打好Tag。
为Bug修复使用专门分支,让团队可以处理掉问题而不用打断其它工作或是等待下一个发布循环。
你可以把维护分支想成是一个直接在master分支上处理的临时发布。
示例
下面的示例演示本工作流如何用于管理单个发布循环。假设你已经创建了一个中央仓库。
创建开发分支


第一步为master分支配套一个develop分支。简单来做可以本地创建一个空的develop分支,push到服务器上
以后这个分支将会包含了项目的全部历史,而master分支将只包含了部分历史。其它开发者这时应该克隆中央仓库,建好develop分支的跟踪分支
现在每个开发都有了这些历史分支的本地拷贝。
小红和小明开始开发新功能
这个示例中,小红和小明开始各自的功能开发。他们需要为各自的功能创建相应的分支。新分支不是基于master分支,而是应该基于develop分支:

后面的功能都在这里,将不再重复贴图。
他们用老套路添加提交到各自功能分支上:编辑、暂存、提交
小红完成功能开发

添加了提交后,小红觉得她的功能OK了。她可以直接合并到她本地的develop分支后push到中央仓库:
获取,更新develop分支状态(切换到develop分支,拉取),点击git工作流,完成功能,推送。
在合并功能前确保develop分支是最新的。注意,功能决不应该直接合并到master分支。
冲突解决方法和集中式工作流一样。
小红开始准备发布

这个时候小明正在实现他的功能,小红开始准备她的第一个项目正式发布。
像功能开发一样,她用一个新的分支来做发布准备。
这个分支是清理发布、执行所有测试、更新文档和其它为下个发布做准备操作的地方,像是一个专门用于改善发布的功能分支。
只要小红创建这个分支并push到中央仓库,这个发布就是功能冻结的。任何不在develop分支中的新功能都推到下个发布循环中。
小红完成发布

一旦准备好了对外发布,小红合并修改到master分支和develop分支上,删除发布分支。合并回develop分支很重要,因为在发布分支中已经提交的更新需要在后面的新功能中也要是可用的。
发布分支是作为功能开发(develop分支)和对外发布(master分支)间的缓冲。只要有合并到master分支,就应该打好Tag以方便跟踪。
最终用户发现Bug

对外发布后,小红回去和小明一起做下个发布的新功能开发,直到有最终用户开了一个Ticket抱怨当前版本的一个Bug。
为了处理Bug,小红(或小明)从master分支上拉出了一个维护分支,提交修改以解决问题,然后直接合并回master分支。
就像发布分支,维护分支中新加这些重要修改需要包含到develop分支中,所以小红要执行一个合并操作。然后就可以安全地删除这个分支了。
到了这里,但愿你对集中式工作流、功能分支工作流和Gitflow工作流已经感觉很舒适了。
你应该也牢固的掌握了本地仓库的潜能,push/pull模式和Git的分支和合并模型。
记住,这里演示的工作流只是可能用法的例子,而不是在实际工作中使用Git不可违逆的条例。
所以不要畏惧按自己需要对工作流的用法做取舍。不变的目标就是让Git为你所用。
补充
获取与拉取的区别
获取是从中央仓库检查分支是否有更新。如果有更新,则得到更新的详细信息,如提交信息,变更差异等等。
拉取是将中央仓库与本地仓库进行同步,将差异同步到本地。
丢弃、移除、忽略的区别
丢弃是指将修改的部分丢弃,即恢复到修改前的状态。
移除是指删除这个文件,如果之前没有提交过这个文件,移除后将无法找回该文件。
忽略是指不再对该文件进行差异检查和提交。忽略会在.ignore文件中增加一项,同步到中央仓库,这样,所有环境都将忽略该文件。如果该文件已经在提交历史中,该文件不会被删除。
规约
创建高度聚焦的提交,方便查看检索,提交信息格式:功能名称--新增/修复--描述
参考文档
深入理解学习Git工作流