得益于git优秀的分布式版本控制设计,为git-flow加入多人协作场景非常容易。
由于一些业务系统不需要有明确的“版本”的控制,我将git-flow模型做了一些简化,去除了release分支,并且在feature-b上模拟了多人协作的场景,如图:
原Git-Flow模型(点击查看出处及大图):
解读git-flow及多人协作场景:
Ø master和dev分支是一个平行分支。其中master用于发布(上线),dev用于所有feature分支及bugFix分支的汇总,然后合并到master分支。
Ø 某些feature需要多人协作(feature-b),从git的角度来说,这一过程可以被描述为:在远程仓库创建该feature分支(从dev派生)
Ø 各开发者在本地对该分支进行修改,将更改结果push到远程(上图中feature-b分支中不同颜色的点代表来自不同开发者的commit);所有开发者push完毕后,该分支(feature-b)被合并到dev
Ø dev测试通过后则将dev合并到master(需要注意的时候,由于master完全平行于dev,所以这个合并不应该出现任何冲突,亦不需要测试)。
Ø 用master分支上线
为什么要去除release分支?对于一些业务系统来讲,线上只会存在其各版本中的一个,那么此时master的tag就可以起到标记版本的作用。如果有单独标记版本的需求,则可以选择完全按照GitFlow模型,加入release分支。
如果是new to git,建议完全按照下面的步骤执行整合。
我本地测试环境:
Git客户端
JClipse
在这里我们使用统一的git客户端,需要注意的是,请确保安装的git客户端被加入到%PATH%中。
初始化设置
配置用户的名称及邮箱,
git config --global user.name "Yourerp"
git config --global user.email"[email protected]"
配置记住用户名及密码以方便操作:
git config--global credential.helper store
本教程的导入方式与目前互联网上的其他方式有所不同,配合git的stash命令,分支切换将非常方便。
1, clone远程仓库的相关信息及master分支:
git clonehttp://source.jd.com/app/my-app.git
2, 进入某仓库,从远程检出你感兴趣的分支。这里我们选择检出dev分支:
cd my-app
git checkout -bdev origin/dev
git checkout -bls origin/feature-ls
.. ..
3, 将刚才clone的本地仓库添加的eclipse的Git Repositories视图:
a) Window-> show view -> other -> Git Repositories
b) 在git repositories中选择 add an existing localGit repository,选择对应目录,完成后如图:
右击Working Directory,选择Import Projects…,用Import existing projects选项进入next,然后finish。这样,Project Explorer视图中就出现了该项目(如果该项目为maven-parent,则会自动导入该parent的modules项目)。
至此,DEV分支就被导入到eclipse了。
Git指令:
gitcheckout –b branch-name-for-local
commit some changes……
git push origin branch-name-for-local:branch-name-for-remote
注意,本地分支和远程分支可以不同命。
接下来,我给新建分支下的pom.xml添加了一些内容并保存,此时,该文件的图标发生了变化,具体含义请参见Windows->Perferences->Team->Git->LabelDecorations.
接下来,就是:
1, 将待更改文件添加到“暂存区”
Git指令:
git add my-file
Eclipse插件:
2, 将已添加至暂存区的文件commit到本地仓库
Git指令:
git commit –m “msg for this commit”
Eclipse插件:
右击待提交文件,选择Team->Commit…,输入提交说明,然后commit(请注意不要随意使用commit and push)
3, 将本地提交push到远程
Git指令:
git push origin branch-name-u-want-to-push-to-origin
Eclipse插件:
在eclipse中稍微麻烦点儿,如图:
现在,我们的提交已经被push到远程仓库,其它开发者需要将其合并到他们的本地库。
指令:
git pull
Eclipse插件:
右击某仓库,选择pull操作,执行完毕之后,远程仓库的更改就被合并到本地了。
现在,feature-b分支的开发、测试完毕,时候合并到dev中了。按照git-flow模型,合并后的feature-x分支应当被删除,实际操作中,我们可以延迟这一操作的时间。
Git指令:
git mergetarget-branch-name --no-ff
Eclipse插件:
右击想要合并的master分支,选择merge,可以看到,能够合并的文件均已被合并,有冲突的则会被标记为冲突状态待你解决。
现在,我们有了若干个冲突了的文件亟待解决(oh,shit!).
Git使用
<<<<<<<
=======
>>>>>>>
来标记冲突,文字解释起来比较麻烦,请参考下图:
当你手动解决冲突之后,右击该文件,选择Team->add to index,这样就然后就可以提交啦。
Git的回退命令有两种,分别是checkout,reset。对于不同状态的文件,使用的命令也不尽相同,下面一一说明。
文件处于新增状态时,直接删掉即可。
文件已经通过git add 添加到暂存区之后,如果想要回退到最后一次提交时的内容,使用reset命令将该文件重新放回工作区:
命令:
git reset HEAD
Eclipse插件:
右击该文件父目录,选择Team-> Synchronize Workspace,在新弹出的视图中右击该文件,选择override
命令:
git checkout –file-name
Eclipse插件:
操作同已添加至暂存区的情况。
命令:
git reset --hard commit_id #回退到某个commit
git reset –hard HEAD #回退到最近一次提交
git reset –hard HEAD^ #回退到最近两次提交
使用gitlog --pretty=oneline来查看提交记录
Eclipse插件:
待补充。
指令:
git stash
这是一个非常有用的指令。它的意思是将当期的工作区保存起来,之后恢复到和HEAD版本一模一样的状态。
这个指令的使用场景是(虚构):
你正沉浸在feature-x开发的欢愉之中,突然对面的产品妹子来找你,说是线上出大事儿了!!!某商品的结算金额原本是123$,结果被显示为123¥…..
你心中一万只草泥马飘过,真想怒摔键盘,辞职走人,但交接也得一个月不是么,干活吧。
0,你发现暂存区里面添加了20个文件,但是由于还有40个文件没有开发完毕,所以提交到本地不太合适,删掉(拷贝走)更是费事儿。于是:
1,你使用git stash将当前的工作区状态保存,然后你发现工作区被恢复到最近一次提交的样子。
2,你创建了一个本地分支bugFix-xxx,开始开发;开发完毕后你将该分支合并到了dev与master中,上线后通知旁边正在看电影(也有可能是在嗑瓜子)的leader去线上验证。
4, 验证通过,你使用git stash pop将最后一次stash的工作区状态恢复,继续feature-x的开发。
PS:我们可以保存多个stash,然后单独指定恢复某个stash。但是这个指令在我本地的git客户端总是无法执行成功,所以这里就不多做介绍了。请使用git stash –help了解更多。
在eclipse中,这个功能的入口是在右击repository->StashChanges….
这个节点显示了已经保存的stashes:
注意灰色的文字,那是该stash的描述。
git stash这个指令非常强大。结合eclipse插件,我们可以实现非常方便的上工作下文切换。鉴于这个功能可以在分支切换及合并上节省掉大量的时间,我们一定要掌握它!
这个话题的讨论比较多,我这里列了一些可行性比较高的“最佳实践”:
1, 每个commit都应当有个业务含义。意思就是说没有必要以文件为单位去commit。
2, 尽可能地使用分支去完成任务。这个分支可以是本地分支,合并完之后即被丢弃(删除)。Git中创建分支非常快也非常方便。
3, 利用stash功能完成上下万切换,这个功能也进一步支持了大量地使用分支。
Git是个一个非常优秀的分布式版本管理系统。
理解git思维的关键在于理解git中的几个“区”:
l 工作区。就是你日常开发的地方,这里面的文件可以被你任意更改、添加
l 暂存区。你的更改被添加到这个区,可以(等待)被提交。
l 本地仓库。暂存区内的文件被提交至此。
l 远程仓库。本地的更改应当被push到远程仓库以让其他成员看到。
Git-flow模型是一种基于git的分支管理模型。如果大家不满足与git flow客户端命令的“不可定制”(比如合并完某feature分支后不想删除该分支),那么完全可以利用git相关指令完成目标操作。
参考资料:
[1] A successful Git branching model
[2] Pro Git汉译版