如何拆分包含重构的 Git 提交?

How to split a Git commit that contains a refactoring?

我在我的本地 Git 存储库中创建了一个提交,其中包括功能更改和重构。回想起来,如果我为重构创建一个单独的提交会更好:重构是重命名,因此导致许多文件中的差异。在所有这些重命名差异之间,很难看出功能上的变化。这例如使代码审查变得比它需要的更难。

那么,有解决这个问题的简单方法吗? IE。是否可以将提交拆分为重构提交和功能更改提交?

我试图通过对差异的手动分类来拆分提交 - 正如 Break a previous commit into multiple commits 的答案中所建议的那样 - 但这真的很乏味。有没有更简单的方法?

是的,有一个简单的方法 - 假设您可以轻松地重复重构。该方法是创建一个仅包含重构的提交,然后 "subtract" 它来自混合提交。

您可以通过以下方式进行:

  1. 检查您当前所在的分支,e.g.git branch。对于其余步骤,我们假设您从分支 master
  2. 开始
  3. (可选)创建备份分支:git branch backup
  4. 恢复提交拆分前的状态。这是通过检查要拆分的提交的父提交来完成的:git checkout HEAD^
  5. 再次重构并提交 git add --all && git commit
  6. 通过"subtracting"来自混合提交的重构提交创建包含剩余更改的提交:

    git reset --hard master
    git reset --soft HEAD@{1}
    git commit -c HEAD@{1}
    git branch -f master
    git checkout master
    
  7. (可选)验证两个新提交实际上包含相同的修改:git diff backup 应该没有差异。

  8. (可选)查看您创建的两个提交。如果您不喜欢这个结果,您可以将它们重新组合在一起(或使用 git reset --hard backup 还原)并重新开始。否则,删除backput分支:git branch -D backup

解释splitting commits section of the git-rebase documentation

  1. 使用 git rebase -i <commit> 开始交互式变基,以便在要拆分的提交之前进行一些提交。

  2. 将要拆分的提交标记为 edit

  3. 当 rebase 到达您要拆分的提交时,执行 git reset HEAD^ 让您处于组合更改在您的工作目录中但未提交的状态。

  4. 进行两次提交:一次是重构,一次是重命名。[*]

  5. 执行 git rebase --continue 以在顶部重播任何以后的更改。

显然,通常的警告适用于只有在您尚未共享您的更改时才执行此操作。

--

[*] 编辑

在此阶段,您有大量未暂存的删除内容和大量未暂存的新文件,它们具有不同的名称和可能已编辑的内容。

要重新应用重构,您可以这样做:

一个。复制新文件名旧文件名(对于每个重构文件);它们将显示为修改

b。 git 以通常的方式添加并提交这些更改

c。再次从磁盘中删除旧文件

然后您所有的重命名都会出现在工作文件夹中,并且可以按原样形成第二次提交。