腾讯程序员的Git大法:我是这样搞定分支的
👉导读
👉目录
01
方案一:讲道理
方案二:心一横
方案三:心又一横
方案三:心再次一横
你想了想似乎很有道理,但似乎又没有道理,这里到底应该选择哪一种其实也是一个有意思的点。
但这其实不是这篇文章的重点,因为不论是哪种方案,都会遇到一个相同的问题:如何将一个分支部分文件/文件夹优雅地合并到另一个分支。
02
git checkout A //切换到A分支git branch A //新建A分支git checkout A //切换到A分支
git checkout -b A //新建A分支并切换到A分支恢复 WorkSpace 文件
git checkout [<commit>] [--] <paths><commit> 是可选项,如果省略则相当于从暂存区(index)检出。这和 git reset 重置命令(例如 git reset HEAD <file>)大不相同:重置的默认值是 HEAD,而检出的默认值是暂存区。因此重置一般用于重置暂存区(除非使用--hard参数,否则不重置工作区),而检出命令主要是覆盖工作区(如果<commit>不省略,也会替换暂存区中相应的文件)。该命令(包含了路径 <paths> 的用法)不会改变 HEAD 头指针,主要是用于拿指定版本的文件覆盖工作区中对应的文件。如果省略<commit>,则会拿暂存区的文件覆盖工作区的文件,否则用指定提交中的文件覆盖暂存区和工作区中对应的文
举个例子:
如果要放弃修改工作空间内容:
在git add命令执行前可以使用git checkout -- add.txt // 用暂存区的内容覆盖工作区的内容在git add命令执行后可以使用git checkout HEAD -- add.txt // HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文
git checkout feature/product_listgit checkout feature/user_manager /src/product/*
整个目录覆盖将作为一个完整的提交合并过来,不利于提交信息的追溯。 如果只有新增文件或者 src/product 文件夹下只有 feature/user_manager 分支进行修改,feature/product_list 没有修改,则没问题,如果两边都修改了,则存在代码和并和代码冲突的问题,这里并不能解决。 feature/user_manager 删除文件操作并不会同步过来,比如你在 feature/user_manager 分支删除了 src/product/test.xx 文件,但 feature/product_list 分支保留了 src/product/test.xx,这个时候 git checkout feature/user_manager /src/product/*并不会删除 feature/product_list 分支的 src/product/test.xx 文件(对,是的,不要怀疑)
03
使用 git merge 命令
事实上 git merge 与 git rebase 是项目中经常使用的命令,有的时候会混淆了两个命令的概念,这里做一下简单的区分。
git merge 即就是常规的合并:
git merge feature //将分支 feature 合并到当前分支上git checkout feature //切换当前分支为featrue分支git rebase master // 将当前分支变基到当前分支(即feature分支)
git merge 就是真实意义上的合并,把两个分支的指针指向一起,同时将历史修改按时间顺序进行排布。 git rebase 就是分支变基,把合并进来的修改记录放在当前分支修改的前面。(时间上的前面) git rebase 因为没有两个交叉修改记录看来很清爽,方便 CR。 git merge 因为保留的完整的修改记录,适合往联合开发环境下的主干或者主分支进行合并。(换句话说,合并到 master,一般使用的 merge) 当然实际项目中,一般在合并回 master 前,待合并分支先做 rebase,然后解决冲突,代码 CR,再合并,这样合并的时候就不会出现代码冲突,即可以自动化流水线完成。
git checkout feature/product_listgit checkout -b feature/product_list_temp
git merge feature/user_manager --on-off将 feature/user_manager 分支合并到 feature/product_list_temp 后,这里通过 merge,将 src/product 文件夹下的代码进行合并,并解决了冲突,这时 src/product 的文件夹的代码被智能合并了,代码冲突解决了,同时保留了合并的历史记录。
再用强制合并方式中的 git checkout 命令强制把 product_list_temp 分支的 src/product 文件夹合并到 product_list 分支。
git checkout feature/product_listgit checkout product_list_temp src/produc
这里解决了强制合并方式的问题2。
至于问题1,保留 product_list_temp 分支吧,嗯,虽然不太优雅,但在大的需求修改下,没有人力做细致合并的话,这样也是一个工程上有效的办法。
参考资料:https://blog.csdn.net/weixin_43758377/article/details/123394291
04
智能合并的方式基本解决了强制合并方式的问题2,但也留下了问题1的坑,那有没有优雅的方法呢?
这里就要具体问题具体分析,首先,如果在 feature/user_manager 分支严格按照需求的顺序进行开发,那在用户配置管理子功能开发完毕的这个 commit_id,其实可以通过 git checkout 命令恢复回来,然后新拉个分支的方式合并回 feature/product_list 的方式解决。
在 feature/user_manager 分支上通过 checkout commmit_id 在本地会滚到那在用户配置管理子功能开发完毕的节点。
git checkout feature/user_managergit checkout commmit_id
git checkout -b feature/tmp_user_managergit checkout feature/product_listgit merge -b feature/tmp_user_manager
git checkout mastergit merge -b feature/product_list
当然,如果在 feature/user_manager 分支交叉顺序对两个子需求进行开发,但每次提交都能是独立为某一个子需求开发提交出来,其实可以通过 git chery-pick 来解决。
智能合并中讲了 git mergr 和 git rebase 两个合并命令的区别,其实还有一种合并命令——gir chery-pick。
使用 git chery-pick 命令
git chery-pick 相对于上面两个合并分支的命令,git chery-pick 主要是将某次/某几次提交进行合并。
git cherry-pick 的使用场景就是将一个分支中的部分的提交合并到其他分支,使用以下命令以后,这个提交将会处在 master 的最前面。
git checkout mastergit cherry-pick <hashA> <hashB>
git checkout feature/product_listgit checkpick <hashA> <hashB> ...
05
一般来说,当你去问组内项目经验丰富的工程师时,大概率他会建议你用智能合并的方式。
如果你在纠结,这样就没有整个文件夹的修改记录了,项目经验丰富的工程师会建议在这次合并的 commit 上写上“欲看记录,去 product_list_temp 分支”看,并强调不要删除该分支。
如果你说,我不想这个方案,我就是想在当前分支看到所有修改,并优雅地合并某个文件夹的内容。
这个时候,绝大部分项目经验丰富的工程师会对你执着的精神表示认同,并不想再理你了。
但,既然看到这里了,笔者一定会一个兜底方案。
git checkout --patch source_branch src/product优雅的代价就是花一定的前置时间打基础。
git checkout -p 类似已交互的形式打补丁。
git 会跟你逐个掰扯 source_branch 分支上的 src/product 文件夹下的这些文件怎么处理。
是的,只要你愿意一个一个文件掰扯,你就能得到一个有完整提交记录的文件夹。
这时,你可能会有一个疑问,那和我一个一个修改文件有什么区别?
区别就是这样同时保留了代码提交的修改记录!
所以当你花了1个小时去逐个对齐了这个文件夹下每个文件的修改点后,你就可以跟测试说:提测!
第一时间看鹅厂技术