最近在合并上游代码,遇到了一个问题:某个 commit 杂糅了几个不同的特性修改,这可能会导致 rebase 上游代码时需要再对该 commit 进行额外的代码冲突处理

解决方法:合并上游分支前,拆分杂糅的 commit,并将其中不同的特性修改合并(Squash)回相关的 commit。可以直接通过命令行进行操作,可以参考:
Break a previous commit into multiple commits
。也可以通过 JetBrains 家内置的 Git 进行操作,下面会介绍 IDEA 图形化操作的方法

非先前 commit 的拆分

对于刚提交的 commit,要拆分多个 commit 是非常容易的,因为我们只要
soft reset
commit,将 commit 内容撤销回至
暂存区
,就可以随意提交 commit

如果对于
soft reset
不太了解,可以参考我之前的博客:
Git 中的回退操作:reset 和 revert

先前 commit 的拆分

先前 commit 指的是:在目标 commit 后已经有了若干个 commit。它无法直接通过
soft reset
进行拆分,因为这样会丢失后续的 commit,如下图,我们需要拆分
B
commit,我们就无法直接使用
soft reset
,因为这样会丢失
C

D
commit 的修改

所以我们需要使用 rebase,具体步骤:

  1. 在 交互式 (interactive) rebase 中将
    B
    标记为
    edit
    ,这时
    B
    后面的 commit 会被暂时隐藏起来
  2. 使用
    soft reset

    B
    撤销回
    暂存区

  3. B
    的修改内容分多个 commit 提交
    B1

    B2
  4. 使用 rebase 的
    continue
    将刚才隐藏的
    C

    D
    恢复回来

实例准备

演示使用 IDEA,其实 JetBrains 家的使用逻辑差不多,示例仓库使用:
Learn Go with Tests

git clone git@github.com:quii/learn-go-with-tests.git

需要用到 Rebase,IDEA 默认保护主分支,改写 commit 记录的功能会被禁用

需要先取消分支保护,移除
Protected branches
中的
master;main

假设我们需要将下面 commit 拆分为两个:

1. 启动 Rebase 并标记目标 commit 为 edit

点击
Interactively Rebase from Here...

选择需要拆分的 commit,右键选择
Stop to Edit
,然后再点击
Start Rebasing

这时有右下角会提示您正在处于
Rebase
状态
选择框可以选择
Continue
即继续 Rebase,
Abort
则会退出 Rebase

commit 列表也会显示感叹号

2. 使用 soft reset 将 commit 撤销回 暂存区

我们需要先 soft reset 到目标 commit 的上一个 commit
选择上一个 commit,右键选择:
Reset Current Branch to Here...

选择
Soft
,这样目标 commit 的修改就会退回到暂存区

3. 将暂存区改动分为若干个 commit 提交

这个时候我们就可以继续分开提交两次 commit

查看 log,两条 commit 被成功提交

4. 使用 rebase 的 continue 恢复剩下的 commit

这时候我们需要继续 Rebase,将剩下的 commit 还原回去:点击右下角分分支按钮,选择
Continue Rebase

完成 Rebase 后,剩余的 commit 就会被追加到我们新提交的 commit 后面,至此我们就完成了先前 commit 的拆分

Rebase edit 的拓展

因为这里的案例只是拆分 commit,没有对 commit 进行修改,如果是修改的话,修改完成后需要使用
git add
将文件标记为已修改,才能使用 rebase 的
continue
,这样该 commit 就会被修改。后续的 commit 有可能与本次的改动产生冲突,需要手动处理冲突

参考资料

Break a previous commit into multiple commits

标签: none

添加新评论