Git中合并多个提交的各种方法

为了保持分支提交历史的清晰、独立,我们经常需要将几个提交合并成一个;但 Git 没有专门为合并提交提供相应的命令,为解决这个问题,我专门研究了几种方法来实现 提交的合并;如下:

目录

内容

1. 概念

为了方便下文的描述,这里先定义几个概念;
若干个连续的提交 称为 提交段,即,一段提交的意思;也称 提交范围 ,在没有个歧义的情况下,也可简称 范围
提交段中最开始(最早)的那个提交 称为 起始点
提交段中最晚的那个提交 称为 结束点

提交段相关概念

2. 方式1:修复最后一次提交

通过给 commit 命令添加 --amend 选项,可以修改最后一次的提交;它是将当前变更与最后一次提交的变更合并,并创建一个新的提交对象,然后用这个新的提交对象替换掉最后一次提交;

git commit --amend [-m <提交说明>]

示例:
假设最后一次提交是 C2,如下图所示:

amend前

执行 git commit --amend 命令后:

amend后

3. 方式2:用reset重置

3.1. 思路

先用 reset 命令 重置到 需要被合并的提交的起始点的父提交;被还原的提交默认会被放置在暂存区中,然后再手动提交暂存区的内容,从而实现将被还原的所有提交合并成一个;

3.2. 步骤

  1. 用 reset 命令 重置到 需要被合并的提交的起始点的父提交;
    • 语法: git reset [--mixed | --soft] <起始点的父提交> ; 重围最后的n个提交,也可用 git reset [--mixed | --soft] HEAD~n
    • 示例: git reset --soft aa29fdgit reset HEAD~3
  2. 用重新提交被还原的提交:git commit -m <提交说明>

4. 方式3:用交互式rebase合并

4.1. 思路

交互式的 rebase 命令,可以在变基的过程中更改提交,应用这个特性,我们可以将一系列的提交变基到它们原来所在的基上,而不是新的基上,从而可以实现对一系统列提交进行更改的操作;

4.2. 步骤

  1. 用交互式 rebase 命令对 需要被合并的提交 进行变基操作;

    • 语法: git rebase -i <起始点的父提交> ; 合并最后的n个提交,也可用 git rebase -i HEAD~n
    • 示例: git rebase -i aa29fdgit rebase -i HEAD~3

    然后会弹出如下交互式界面:


    交互式rebase默认界面

    说明,在互动界面中:

    • # 开头的是注释,前面不以 # 开头的是命令,默认都是 pick 命令,表示选中其后面的 提交。
    • 这些命令会被从上到下执行;
    • 可以对这些命令重新排序;
    • 如果删除一行,则对应的提交将会丢失;然而如果删除了全部内容,变基操作将会终止;
    • 空提交会被注释掉;

    所有的命令如下:

    • pick <提交> | p <提交>:选中提交;
    • reword <提交> | r <提交>:选中提交,并且修改提交说明;
    • edit <提交> | e <提交>:选中提交,但在执行当前提交时会暂停,此时允许你修改这个提交;
    • squash <提交> | s <提交>:选中提交,但会将当前提交合并到上一个提交中去;
    • fixup <提交> | f <提交>:与squash相同,但不会保存当前提交的提交说明;
    • exec <命令> | x <提交>:使用 shell 运行命令
    • break | b:在此处停止(使用 git rebase --continue 继续变基)
    • drop <提交> | d <提交> :删除提交
    • label <label> | l <label> :为当前HEAD打上标记
    • reset <label> | t <label> :重围HEAD到该标记
    • merge [-C <提交> | -c <提交>] <label> [# oneline]:创建一个合并提交,并使用原始的合并提交说明(如果没有指定原始提交,使用注释部分的 oneline 作为提交说明)。使用 -c <提交> 可以编辑提交说明;
  2. 将需要合并的提交前端的命令改成 squash(或 s) 和 fixup(或 f),然后即同交互式界面;在交互式界面中,只有 squash 和 fixup 命令可以用来合并提交。如下图所示:

    更改交互式rebase界面中的命令

  3. 修改完成后,退出交互式界面(vim输入 :wq 保存并退出),然后按照交互式界面中设定好的命令顺序进行 rebase 操作;

5. 方式4:创建新分支并用rebase合并

如果被合并的提交段并不在分支的末端,而是在分支的中间,如下图:


被合并的提交在中间

我们也可以用交互式rebase的方法进行合并,只是需要在 交互式界面中 对不需要被合并的提交应用 pick 命令,但如果 被合并的提交是距当前HEAD很久远的提交,交互式界面中就会出现太多不相关的提交,便利查找想要合并的提交变更困难,我有一个方法可以简化这种操作,如下:

5.1. 思路

先基于被合并的提交段的终点提交创建一个临时的用于合并提交的分支A,则需要被合并的提交就会在在分支A的未端,然后在分支A上使用其它合并提交段的方法(如:方式1、方式2、方式3 等等)对提交进行合并,合并完成后,再将原分支中 终点提交 之后的所有提交变基到 分支A 上;

5.2. 步骤

合并中间提交段动画

高清版的动画请见合并中间提交段动画-高清.gif 提取码:MI8K

  1. 基于需要被合并的提交段的终点提交 创建 新的临时分支T,并切换到该新分支上 git checkout -b 分支T <终点提交>
  2. 用其它合并提交段的方法(如:方式1、方式2、方式3 等等)在 分支T 上对需要被合并的提交进行合并操作;
  3. 切换到 原来的分支 ,并通过命令 git rebase --onto 分支T <终点提交> 将原分支上 被合并的提交段 的终点提交 之后的所有提交 变基到 分支T上;

6. 方式5:用rebase的autosquash合并

这种方法与方式3:用交互式rebase合并的原理是一样的,只是不用手动更改交互式界面中的命令为 squashfixup 了;它会自动根据提交说明中命令标识来在 交互式rebase 界面中自动自动更改相应的命令;

6.1. 使用方法

  1. 在进行提交时,如果这次提交需要与之前的某个提交合并,则使用 git commit --fixup=<合并的目标提交> 或者 git commit --squash=<合并的目标提交>; 这会生成一个带有标识的的提交;

    • 合并的目标提交: 指的是 需要与哪了提交进行合并;
    • squash: 标识当前提交需要合并到指定的提交中去;
    • fixup: 标识当前提交需要合并到指定的提交中去,但合并后不会保留当前提交的提交说明;
  2. 在需要合并的时候,执行命令 git rebase -i --autosquash <起始点的父提交> ,这时会弹出一个与 方式3:用交互式rebase合并 中的第1步的一样的交互式界面,并且上一步中被标识的提交会被自动修改成 fixupsquash

  3. 修改完成后,退出交互式界面(vim输入 :wq 保存并退出),然后按照交互式界面中设定好的命令顺序进行 rebase 操作;

相关文章

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容