# GitPratice **Repository Path**: softwareQM01/git-pratice ## Basic Information - **Project Name**: GitPratice - **Description**: 通过一系列短暂操作做Git的小实践 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2021-05-25 - **Last Updated**: 2023-02-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README [本次实验DOC文件链接](https://www.kdocs.cn/l/cm2djCan6Zcw)或者扫描下方二维码 (2021年6月8号前有效) [![2ueRc4.png](https://z3.ax1x.com/2021/06/01/2ueRc4.png)](https://imgtu.com/i/2ueRc4) 姓名: * 黄国立 * 罗财志 * 马灿佳 * 林宏展 邮箱: * 1376397133@qq.com * 1871481304@qq.com * 3031859918@qq.com * 528141257@qq.com 命令行方式: ```shell git clone https://gitee.com/softwareQM01/git-pratice # 假设同样目录下已经有git-pratice或者网页项目已更新,在git-pratice下使用以下命令达到最新修改 git pull --rebase ``` 1. 创建develop分支有两种方式 + 第一种是在创建Repository的时候选择分支模型为“生产/开发模型(支持master/develop类型分支)” + 第二种是在创建完Repository之后手动创建develop分支。本文选择第二种 + 在showcase项目页面依次点击`master`->`管理` ![输入图片说明](https://images.gitee.com/uploads/images/2019/0612/232523_70cd6c3c_338593.png "branch management") + 在接下来的页面点击`新建分支`,起点选择`master`,新分支名称为`develop`,点击提交就创建成功了 2. 至此`organization repository`就创建成功了 3. 接下来我们可以通过点击showcase项目右上角的fork来创建`Own Repository` ![输入图片说明](https://images.gitee.com/uploads/images/2019/0612/233108_5b4acf85_338593.png "fork") 8. 选择自己的账户,点击确定,就创建成功了 ![输入图片说明](https://images.gitee.com/uploads/images/2019/0612/233309_980a6840_338593.png "create fork") 9. 创建成功后会进入`Own Repository`的showcase项目主页 ![输入图片说明](https://images.gitee.com/uploads/images/2019/0612/233433_c1754352_338593.png "own repository") 10. 至此`Own Repository`创建完成 11. 然后可以点击showcase项目的`克隆/下载`,拷贝弹出的连接信息。 ![输入图片说明](https://images.gitee.com/uploads/images/2019/0612/233636_a0c24631_338593.png "urls") 12. 在本地电脑的terminal执行git clone命令下载代码 ```bash $ git clone https://gitee.com/luoyan35714/showcase.git Cloning into 'showcase'... remote: Enumerating objects: 4, done. remote: Counting objects: 100% (4/4), done. remote: Compressing objects: 100% (4/4), done. remote: Total 4 (delta 0), reused 4 (delta 0) Unpacking objects: 100% (4/4), done. ``` 13. 假如现在我们有一个新的需求要做,该怎么办呢,从上面的流程图我们可以知道,所有的最新代码会先体现在develop分支,所以我们要先切换到develop分支,然后从develop分支创建我们的feature分支。但是由于第一次clone代码到本地,本地并没有develop分支,所以我们要先检出develop分支 ```bash $ cd showcase/ $ git branch -a * master remotes/origin/HEAD -> origin/master remotes/origin/develop remotes/origin/master $ git checkout -b develop remotes/origin/develop Branch develop set up to track remote branch develop from origin. Switched to a new branch 'develop' $ git branch * develop master ``` 14. 基于develop分支创建新的feature分支 ```bash $ git checkout -b feature/hello-world Switched to a new branch 'feature/hello-world' ``` 15. 做了一些开发,并且提交了代码 ```bash $ echo "HelloWorld" > helloworld.md $ git add . $ git commit -m "add hello world file" [feature/hello-world db6543e] add hello world file 1 file changed, 1 insertion(+) create mode 100644 helloworld.md ``` 16. 推送到远程`Own Repository` ```bash $ git push origin feature/hello-world Counting objects: 3, done. Delta compression using up to 8 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 320 bytes | 320.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0) remote: Powered By Gitee.com To https://gitee.com/luoyan35714/showcase.git * [new branch] feature/hello-world -> feature/hello-world ``` 17. 接下来我们回到`Own Repository`的网站,点击`master`查看发现多了一个分支 ![输入图片说明](https://images.gitee.com/uploads/images/2019/0612/234827_e7dfb99b_338593.png "hello world branch") 18. 点击分支右侧的`+Pull Request`,在下一个页面中,选择源分支为我们刚刚提交的分支,目标分支为`Organization Repository`,此处即`org_showcase/showcase`的`develop`分支,然后填写相关PR信息之后,点击创建,一个小提示是,在屏幕的右侧还可以填写一些人员信息,会自动@流程相关的人员进行下一步操作,并且自动给这些相关人员发送通知。 ![输入图片说明](https://images.gitee.com/uploads/images/2019/0612/235137_787fb111_338593.png "create PR") 19. 这个时候团队就可以坐在一起互相做CodeReview了,当Review完之后,可以在PR页面,点击`合并`将代码合并进`develop`分支。当然,如果代码有问题,也可以尽情的不管在代码上,还是文件级别,再或者是PR级别填写一些评论。 ![输入图片说明](https://images.gitee.com/uploads/images/2019/0612/235547_a1a75682_338593.png "Merge") 20. 当一个迭代结束,便可以将Organization Repository的develop合并到master分支,进行持续集成 架构型团队 ----------------- 对于架构型团队,我们前面说过,会定期交付版本供其他产品或者项目使用,并且还要维护之前交付过的部分版本。这里面最难的难点便在于如何支持多版本的维护。首先现在java中比较主流的版本管理(Version Management)是”Major_version.Minor_version.Revision_version“方式,其中Major_version是指有大的本质性的变更,通常是向后不兼容的变更,Minor_version是指功能性的变更,Revision_version是指bug修复或者局部功能完善之类的变更。 那么先从Major_version开始说起,架构型团队通常会维护多个Major_version,原因是大多数时候每个Major_version之间是互相不兼容的,也就是说之前使用本项目的团队如果升级到最新的Major_version是不被承诺一定好用的。那么随着项目的发展,随着功能的增加,随着技术的演进,就必须维护多个Major_version,这部分可以通过在gitee上创建多个Major_version分支来解决,甚至可以分开创建多个Repository解决。 ![输入图片说明](https://images.gitee.com/uploads/images/2019/0619/223724_5134887c_338593.png "multiple develop branch") 对于Minor_version,可以选择只维护最新版本,由于最新的版本是向后兼容的,所以使用此项目的团队可以随意升级到最新版本而不需要任何担心。 ![gitflow framework](https://images.gitee.com/uploads/images/2019/0612/091028_017a4555_338593.png "gitflow-release.png") 上面这张图就是针对Minor_version进行说明。举个例子,在2-3-stable发布之后,2-4-stable发布之前,此时2-3-stable即最新版本,所以有任何更新都可以直接被合并到2-3-stable,但是一旦当2-4-stable发布之后,2-3-stable就会成为永久交付状态,不会有任何新的commit被合并,所有的新的commit只会被合并到2-4-stable,如果客户在使用2-3-stable或之前版本遇到BUG或者漏洞的时候,推荐的最佳选择就是升级到Minor_version的最新版本。 对于Minor_version的最新版本号建议使用branch进行控制,而对于之前的版本号,建议使用tag进行管理。下图展示了如何在码云上进行上述的操作。 还在开发中的版本 Branch: ![输入图片说明](https://images.gitee.com/uploads/images/2019/0619/224942_5b5d3443_338593.png "branch") 已经交付的版本Tag: ![输入图片说明](https://images.gitee.com/uploads/images/2019/0619/225118_289abfef_338593.png "tags") 最后对于Revision_version, 在之前的图中,即使最新的Minor_version已经发布,但是如果有新的功能或者修复依旧会被合并到最新的Minor_version上,那么每次的合并就需要增加一个Revision_version号码,这部分的更新记录建议也是放在tag进行管理,原因是已经被交付的Revision_version永远不会改变,当有更新的时候只会增加Revision_version的号码。 ![输入图片说明](https://images.gitee.com/uploads/images/2019/0619/225817_af1c6f63_338593.png "tags") 产品型团队 ----------------- 对于产品型团队,这种团队会定期交付或部署产品,但是几乎不需要对之前的版本进行维护。原因是产品会直接部署在线上,客户看到的永远是最新的功能。 ![gitflow production](https://images.gitee.com/uploads/images/2019/0612/091057_ee39fb61_338593.png "gitflow-production.png") 如上图,在gitlab flow模型中有一个上游优先("Upstream First")的策略,假设我们现在有三个branch,"master", "pre-production", "production"。其中"master"的代码会部署在开发环境,供开发人员测试使用,"pre-production"会部署在测试环境,供测试人员使用,"production"会部署在真实的产品环境。基于这种环境模型下只有在开发环境测试通过的代码才可以被部署在测试环境供测试人员进行测试,只有在测试环境测试通过的代码才可以被部署在产品环境供客户使用,那么我们很容易推导出代码的持续集成策略也就是只能从"master"到"pre-production"再到"production"进行流转。 基于上述的合并策略,还可以在码云上配置webhook与jenkins等其他devops工具集成,通过Pull request或push branch的动作触发并实现自动化的持续集成和持续交付。 ![输入图片说明](https://images.gitee.com/uploads/images/2019/0619/232051_fab23c5e_338593.png "webhooks") Hotfix ----------------- 以上我们讨论了一些针对正常的需求进行开发的场景,但是还有一种场景是线上出现紧急问题,必须马上进行开发和交付部署。在敏捷团队中通常是有迭代的,而一个迭代中团队通常会并行开发多个功能,有的已经合并到master,有的还没有,如果现在走正常feature branch合并的路子,就会有两个结果,要么是某些已被合并但未被完整测试的功能会连同问题修复代码一起被合并,要么是等迭代结束一起合并。显然在紧急问题情况下,这两种情况都不是我们希望见到的。 于是就引申出了另一种解决方案,如下图 ![输入图片说明](https://images.gitee.com/uploads/images/2019/0620/094658_a393cad0_338593.png "gitflow-hotfix.png") 整体的步骤跟传统的feature branch开发类似,但是有一些小的流程改动 1. 在流程"04 git checkout/git merge"的步骤中hotfix的branch代码应该基于最后一次交付或部署到产品环境的代码进行创建新的hotfix分支,原因是develop分支已经被新开发的feature所污染了,有些未被完整测试的代码已经存在develop分支上。 2. 在流程"06 pull request/code review"中是直接向已经交付的最终环境进行合并,即架构型团队的2-4-stable和产品型团队的production分支,然后在合并到已交付分支之后才将hotfix合并到develop分支。这里的原因也是一样的,在organization repository的develop和master也有被新开发的feature所污染的可能性,所以为了避免这种情况,应该直接向最终已交付的分支进行合并是最合适的! 写在最后 ----------------- 以上就是我们在综合了一些方法论和自己团队的实践之后的一些最佳实践总结,虽然并不能够解决所有的问题,但是还是可以帮助大家解决一些问题。当然技术之路永远是在演进的过程中,也相信会有更多的好的方法论会被发现,好的最佳实践会被使用并且分享,帮助我们更方便的解决代码的问题! 参考文档 ----------------- git flow: [https://nvie.com/posts/a-successful-git-branching-model/](https://nvie.com/posts/a-successful-git-branching-model/) git labflow: [https://about.gitlab.com/2014/09/29/gitlab-flow/](https://about.gitlab.com/2014/09/29/gitlab-flow/) github flow: [https://guides.github.com/introduction/flow/](https://guides.github.com/introduction/flow/) Git的三种workflow和最佳实践: [https://www.hifreud.com/2019/02/25/git-workflow/](https://www.hifreud.com/2019/02/25/git-workflow/) Git 工作流程: [http://www.ruanyifeng.com/blog/2015/12/git-workflow.html](http://www.ruanyifeng.com/blog/2015/12/git-workflow.html) 语义化版本 2.0.0: [https://semver.org/lang/zh-CN/](https://semver.org/lang/zh-CN/)