如何按文件拆分每个提交?

How to split every commit by file?

我知道如何使用 git rebase -i 手动拆分提交,但如何按文件自动拆分分支中的每个提交?

例如,提交 A 修改了 3 个文件,f1、f2 和 f3。拆分后,有 3 个提交 A-f1、A-f2 和 A-f3。

我想这样做是为了让主要的重写变得更容易,因为我只需要压缩一些小的提交。

对于每次提交,您需要

  • 先到list all files in that commit

    git diff-tree --no-commit-id --name-only -r <SHA1>
    
  • 然后对于每个文件,extract that file

    git show <SHA1>:/path/within/repo/to/file
    

在专用分支的工作树中执行此操作,并为提取的每个文件添加并提交。

然后你可以通过提交文件新建一个提交文件来重置你当前的分支。

剧本

以下脚本按文件拆分 HEAD

#!/usr/bin/env bash
set -e

SHA=$(git rev-parse --short HEAD)

# Change to repo root directory
cd $(git rev-parse --show-toplevel)

git reset HEAD^

git diff-tree --no-commit-id --name-only -r $SHA | while read -r f; do
  git add "$f"
  GIT_EDITOR="echo '0a\n$SHA $f\n\n.\nw' | ed -s" git commit -c $SHA
done

生成的提交消息的格式为:

<original SHA> <file name>

<original commit message>

用法

以下假设你可以运行上面的脚本为git-split.

如果你想按文件拆分一个范围内的所有提交,可以这样使用:

git rebase --interactive --exec git-split <branch>

如果你想在交互式变基期间拆分单个提交,请像这样使用它:

p Commit to split
x git-split

欢迎对脚本进行任何改进。