小技巧使用Git从其他分支merge个别文件

10次阅读

共计 2323 个字符,预计需要花费 6 分钟才能阅读完成。

小明发现在实际项目开发过程中,总会遇到各种各样的情况,比如一个大型的项目或版本迭代可能不是一次上线,可能会分好几次上线,这时候就会涉及创建多个分支,分别开发。

项目背景

产品经理:我们本次开发三个功能,列表页功能、详情页功能、系统消息功能,分两次上线,先上列表功能,再上详情页和系统消息。

小明:好的吧。

紧接着,小明就将本次需求分为 2 个分支,分别为 A、B。

  • A:开发列表页功能
  • B:开发详情页功能、系统消息功能

原计划:产品经理说先上列表功能,那小明就先开发 A 分支,列表功能很快开发完成(厉害吧)。

计划有变 :风云变幻,第二天小明按照计划开发 B 分支,开发到一半,产品经理突然说目前的系统消息功能(位于 B 分支)比较紧急,需要和列表功能(位于 A 分支)一起上线,当时小明就懵逼了。赶紧暂停开发详情页(位于 B 分支,虽然已经开发了一部分),转战系统消息功能的开发。当系统消息功能开发完成之后,就需要考虑将系统消息功能(位于 B 分支)和列表功能(位于 A 分支)放在一个分支上提测(开发一部分的详情页功能暂先不需要合并)的问题,这时候 分支合并 就要派上用场了。

分支合并

说起 分支合并 ,大家第一个想到的命令肯定是git merge,因为这是 分支合并 的常用命令。

使用 git merge 合并分支会将两个分支的 所有内容 进行比较合并,因此我们如果想合并两个分支中的 一部分,显然直接使用这个命令是行不通的。

So what happens next ? 嘿嘿,有两种方案可供我们选择:

强制合并

从其他分支 merge 指定文件到当前分支,git checkout是个合适的工具。

语法如下:

git checkout source_branch <path>...

我们使用 git checkout 将 B 分支上的系统消息功能添加到 A 分支上

$ git branch
  * A  
    B
    
$ git checkout B message.html message.css message.js other.js

$ git status
# On branch A
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#    new file:   message.css
#    new file:   message.html
#    new file:   message.js
#    modified:   other.js
#

合并完成

但是……

注意:在使用 git checkout 某文件到当前分支时,会将当前分支的对应文件强行覆盖

因此,合并 A 分支上没有存在的文件没问题,但是如果合并 A 分支上原先就存在的文件(比如两个分支上都对 other.js 进行过修改),位于分支 A 上的文件 other.js 就会被 checkout(分支 B)过来的other.js 覆盖,导致分支 A 上之前开发的 列表功能 付之东流,这样做肯定是优雅的!

那如何避免同一个文件不强制覆盖,有没有更好的解决方案呢(调一下味口)?我们一起来看一下第二种方案。

智能合并

思路:曲线救国,我们通过git merge 强大的分支合并功能来完成此次无缝合并。

  1. 首先使用 git checkout 根据 A 分支创建一个 A_temp 分支(避免影响 A 分支)
$ git checkout -b A_temp
Switched to a new branch 'A_temp'
  1. 然后将 B 分支合并到 A_temp 分支,此时两个都经修改过的文件会跑出冲突,我们只需解决冲突即可。
$ git merge B
Updating 1f73596..04627b5
Fast-forward
 message.css                     | 0
 message.html                    | 0
 message.js                      | 0
 other.js                        | 1 +
 4 files changed, 1 insertion(+)
 create mode 100644 message.css
 create mode 100644 message.html
 create mode 100644 message.js
  1. 再次切换到 A 分支,并使用git checkout 将 A_temp 分支上的系统消息功能相关文件或文件夹覆盖到 A 分支,此时可以大胆的覆盖!因为我们已经在第二步处理过冲突问题。

$ git checkout A
Switched to branch 'A'

$ git checkout A_temp message.html message.css message.js other.js

$ git status
# On branch A
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#    new file:   message.css
#    new file:   message.html
#    new file:   message.js
#    modified:   other.js
#
  1. 最后,有强迫症的患者可以卸磨杀驴,把刚刚根据分支 A 创建的 A_temp 删除。

    $ git branch -d A_temp

OK,到此分支合并就完结了,现在我们就可以自信地召唤产品经理(我们公司产品兼测试)测试这两个功能。

扩展

另外给大家介绍一下git merge 使用的小技巧

举例:要把 master 分支合并到 dev 分支

git checkout dev // 切换到 dev 分支
git merge master --no-ff // 使用 --no-ff

默认使用 merge 命令是ff,即 fast-forward,这种方式从 Git 合并历史中是无法查看到是哪几个提交对象在一起实现了一个功能。

--no-ff 标记会在分支合并的时候,创建一个新的提交对象,可以避免丢失master 分支的历史信息,并且把所有的功能叠加在一起提交上去。两者的区别如下图所示,大家可以自己体验一下两者的区别。

以上就是小明工作中使用 git 合并总结的经验,希望能帮助到大家,仅供参考,有错误请指出,谢谢!

正文完
 0