商汇粹外网资源平台

搜索
查看: 2070|回复: 5

Git多个分支如何正确的共享代码,并且保持分支独有的代码? ...

[复制链接]

该用户从未签到

1

主题

9

帖子

55

积分

注册会员

Rank: 2

积分
55
发表于 2022-10-22 10:42:41 | 显示全部楼层 |阅读模式
我们的应用场景是这样的:

  • 公司内网版本基于master开发, 同时给客户提供定制功能, 比如分支名称为master_B
  2.  由于产品还在开发过程中, 所以大部分功能两个分支都是需要的
3.  两个分支又有部分代码不能共享,比如有一些功能只有内部需要使用,另一部分代码只有客户需要
现状:
现在刚从SVN迁移到Git, 目前主要基于master开发, 本地开发时使用基于特性master的特性分支, 开发完成之后pull一下远程master分支代码,并且提交到Gitlab,提Merge Request。 如果两个都需要就提两个MR, 但是这样会把master的代码带入到master_B 上去, 并且master_B 独有的代码也经常可能冲突。


这种场景应该如何正确的使用Git?
回复

使用道具 举报

该用户从未签到

5

主题

24

帖子

82

积分

注册会员

Rank: 2

积分
82
发表于 2022-10-22 10:54:21 | 显示全部楼层
我接触的大型项目里,单一 code base 满足 multiple targets 的情况,没有采用分支来解决的。分支是完成临时代码开发,或者 release 时冻结主要 feature 的。分支的命运只有两个。一是和 master 原来越远(release),二是短期内合并到 master 并且结束自己的一生。
Multiple targets 从来都是在一个分支内维护的。或者用 conditional compile,或者用 common header 加上不同的实现代码,或者底层做成 shared library 由上层调用。
回复

使用道具 举报

该用户从未签到

4

主题

10

帖子

46

积分

新手上路

Rank: 1

积分
46
发表于 2022-10-22 11:06:01 | 显示全部楼层
考虑一下能不能把定制的功能设计成plugin,否则一定后患无穷
回复

使用道具 举报

该用户从未签到

0

主题

1

帖子

25

积分

新手上路

Rank: 1

积分
25
发表于 2022-10-22 11:17:41 | 显示全部楼层
其实也可以考虑不停地用master对其他分支进行pull request
回复

使用道具 举报

该用户从未签到

1

主题

4

帖子

36

积分

新手上路

Rank: 1

积分
36
发表于 2022-10-22 11:29:21 | 显示全部楼层
试试submodule?
回复

使用道具 举报

该用户从未签到

2

主题

10

帖子

44

积分

新手上路

Rank: 1

积分
44
发表于 2022-10-22 11:41:01 | 显示全部楼层
功能分支工作流的核心思想就是所有功能的开发都应隔离在专有分支之内,而不应该在主分支内进行任何功能开发。进行如此封装可以避免多个开发者在开发特定功能的同时对主代码库产生负面影响。这也同时意味着主分支内永远没有未开发完成的代码,对于持续集成来说非常具有优势。
将功能开发封装在单独的功能分支中同时也使得pull request产生更多价值。在Git工作流程中,开发者之间可以通过pull request开展一系列对于开发内容的讨论。在pull request的过程中,开发者们可以在新代码被集成进主分支之前,有机会对具体代码进行审核。或者在另外一种场景中,当你开发受阻时,可以新开一个pull request,请求其他团队成员对具体代码提出建议和启发。重点在于,由于pull request流程的存在,让团队成员之间互相审视对方的代码变得简单到不可思议。
工作方式

功能分支工作流基于一个中心化的仓库,其中的主分支代表正式项目代码。开发者们每次开启一个新功能的开发时,需要新建一个分支,而不是直接向主分支提交开发代码。功能分支应该以有具体含义的名称命名,比如 animated-menu 或者issue-#1061这样的名字。这么做的目的是为了让分支承载的开发任务足够明确,足够聚焦。Git本身并不会对功能分支和主分支区别对待,为其提供不同的特性支持,所以开发者可以在功能分支上执行同样的操作:编辑,暂存,然后提交变更。
此外,功能分支可以(也应该)推送到中心仓库。推送到中心仓库的代码可以共享给其他开发者。另外,由于只有主分支是一个比较特别的分支,所以在中心仓库中存储若干个功能分支并不会产生什么问题。当然这也是一种用来备份本地提交的方法。下面我们就来演示一个功能分支的使用流程。
从主分支开发

所有的功能分支都应该创建自最新的主分支代码。在接下来的演示中,我们假设主分支名为main
git checkout maingit fetch origin git reset --hard origin/main
以上命令先将本地分支切换到main分支,然后更新最新的提交记录,并且最后使用reset命令把本地的main分支指向origin/main远程分支的最新提交。当然如果你对于reset不太熟悉,也可以使用如下更加常见的命令
git checkout maingit fetch origingit pull origin main
创建新分支

基于本文最开始所说的关于功能分支的核心思想,当开发一个新功能时,需要为其专门创建一个独有分支。创建完成之后,别忘了切换到新创建的分支上。
git checkout -b new-feature
以上命令通过-b选项基于当前所在分支(也就是main分支),创建一个之前并未存在的new-feature分支。
更新,添加,提交以及推送

在功能分支上,编辑、暂存并且提交的方式与其他任何分支完全一样。所以就像你正常使用Git一样,在该分支上进行任何你认为需要进行的操作。最后在新功能开发完成时提交变更。
git statusgit add <some-file>git commit
向远程仓库推送分支

时不时地把本地分支推送到远程仓库是个好习惯。这一方面可以随时将本地变更备份在远程仓库中,另外在与其他开发者合作方面,允许他人查看你分支上的最新代码。
git push -u origin new-feature
以上命令会把new-feature分支推送到中心仓库(origin),添加的 -u 选项将其添加为远程追踪分支,以便未来执行git push操作时git自动判断需要推送到哪个远程仓库,就不再需要每次都添加origin之类的参数了。推送之后,就可以通过仓库托管软件新建pull request / merge request (github / gitlab / bitbucket etc.)。在这里可以指定其他开发者作为代码评审人,在合并之前对新提交的代码进行评审。
关于反馈

如果在pull request或者merge request页面,团队成员进行了代码评审并且通过了这次提交,那么就可以进行代码合并。但还有另外一种情况,也就是审查人员可能会提出一些修改建议,此时开发者可以在本地针对这些建议进行修改,然后再次执行一系列编辑,暂存,提交,推送的操作。此时针对这些建议的新修改会自动在pull request/merge request中呈现出来。
合并pull request

如果其他成员提交了同样段落的修改,pull request页面会告诉你此次提交有冲突发生,此时你需要先解决这些冲突。如果没有冲突或者冲突已经解决,并且通过了代码评审,那么就可以将分支合并进main分支。
Pull requests

除了可以隔离功能分支与主分支,分支还通过pull request提供了在合并之前针对开发内容进行讨论的能力。一旦有人完成了某个功能的开发,不要直接马上合并进main分支,请提交一个pull request并请求其他人帮忙,然后再合并进main分支。这样在新开发的代码融入主代码库之前,其他开发者有机会对其进行审查。
进行代码评审是pull request过程所提供的一个重要收益。虽然在pull request中进行的代码评审通常是针对一次合并所涉及到的新增代码,但代码评审本身毕竟是一种通用的关于代码本身的讨论。这也就意味着你可以在开发过程中的任何节点进行代码评审。比如在开发过程中需要其他人对正在开发的功能提供一些具体的帮助,直接发起一个pull request,让其他合作者深入到具体代码中来提供帮助吧。
一旦一个pull request被接受,接下来的发布流程就与我们在其他文章中讨论到的中心化工作流一致了。首先你需要确保本地的main分支与远程仓库的main分支同步,然后合并功能分支到main分支内,再推送回中心仓库即可。
示例

接下来的示例展示了使用功能分支工作流的一种场景。该场景描述了在团队内部,针对一个新功能的pull request进行代码评审的场景。
韩梅梅开始开发一个新的功能


在进行任何代码开发之前,先创建一个独立的分支。使用如下命令:
git checkout -b hanmeimeis-feature main
通过上面的命令,韩梅梅基于main分支创建了一个新分支,名叫hanmeimeis-feature,-b 选项意味如果该分支不存在就创建它。在此分支上韩梅梅进行开发:
git statusgit add <some-file>git commit
韩梅梅开发告一段落,去吃午饭


韩梅梅在早上进行了几次提交。在中午吃饭之前,是个好时间点推送本地修改到远程仓库。这可以备份韩梅梅早上的工作,也可以让其他团队成员获取到韩梅梅早上提交的代码。
git push -u origin hanmeimeis-feature
上面的命令把hanmeimeis-feature分支推送到远程仓库。-u 选项会自动把这个分支添加为远程追踪分支,这样以后再进行git push操作时就不需要通过参数指定推送的具体远程仓库了。
韩梅梅开发完成


午饭归来,韩梅梅又做了几次提交,新功能终于开发完了。但是在合并到main分支之前,她需要先发起一个pull request让其他人知道她已经开发完成。首先,她需要推送本地代码,保证远程仓库的分支是最新的。
git push
接下来,韩梅梅在仓库托管软件的UI界面上发起一个pull request,请求将hanmeimeis-feature分支合并到main分支,此时团队其他成员就会自动收到托管软件发出的通知。在pull request的页面上,对于指定代码段落的评论会直接显示在这段代码旁边,所以可以很方便的就具体代码提出问题。
李雷收到pull request通知


李雷收到了通知,然后打算看看hanmeimeis-feature里都有些啥内容。看了之后,李雷认为在合并之前应该再做一点点修改,于是他俩在pull request中进行了一番讨论。
韩梅梅进行了修改


韩梅梅又一次进入了经典流程:编辑,暂存,提交,推送。之后她所有的更新就出现在了pull request页面上,于是李雷又开启了评论模式。
其实如果李雷愿意的话,他完全可以自己把hanmeimeis-feature分支拉到本地,然后自行修改。李雷进入经典流程之后作出的修改也同样会自动出现在pull request页面。但他没有这么做,可能因为他觉得自己是领导吧。
韩梅梅发布新功能


当李雷觉得韩梅梅的代码可以进行合并了,就需要有人去执行这个合并操作,然后新的代码就进入主分支里(这个操作谁都可以做,韩梅梅可以,李雷也可以,甚至是Jim或者Lily和Lucy)
git checkout maingit pullgit pull origin hanmeimeis-featuregit push
以上流程会在提交历史上留下一个合并提交的节点。有些人喜欢这样,因为这种合并提交历史可以明确的显示出何时何地进行了两个分支的合并。也有一些人更喜欢线性的提交历史,如果你是这样的人可以在功能分支执行rebase main分支的操作,这样功能分支的所有提交就会位于main分支的顶端,这样就可以进行一次快进合并。
与此同时,Tom也在经历着韩梅梅同样的事情:
当韩梅梅和李雷一直在讨论和合并hanmeimeis-feature时,Tom也在对自己的功能分支进行同样的操作。所以可以看到通过隔离功能分支的开发,每个人都可以独立进行开发工作,而且当确实需要与其他人共享代码时,也很容易办到。
总结

在本文档中我们讨论了git功能分支工作流。这个工作流聚焦于处理那些针对不同业务功能进行独立开发的分支。我们还以一个具体的例子展示了功能分支工作流是如何一步一步进行的。关于功能分支工作流我们得到以下结论:

  • 专注于分支模型
  • 同样可以被用于其他面向仓库的工作流程
  • 通过pull request和合并评审提升协作效果
在合并功能分支操作中使用git rebase可以避免让过多不相关的提交记录出现在git历史中。在团队中使用功能分支模型可以提升团队的协作表现。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表