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

5
我知道如何使用 git rebase -i 手动拆分提交,但是如何按文件自动拆分分支中的每个提交呢?
例如,提交 A 修改了 3 个文件,f1、f2 和 f3。拆分后,会有 3 个提交 A-f1、A-f2 和 A-f3。
我想这样做是为了让大规模重写更容易,因为我只需要压缩一些小的提交。

1
按文件拆分提交并不是很明智,因为这样会导致许多提交中只有一个文件更改了其接口,但协作者没有反映这种变化。如果你不在意细节,最好选择合并而不是拆分。 - jonrsharpe
2个回答

10

脚本

以下脚本按文件拆分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>

如果您想在交互式 rebase 过程中拆分单个提交记录,请按照以下方式使用:

p Commit to split
x git-split

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


有趣的脚本,比我的答案更详细。+1 - VonC
@VonC 你的回答很好地概述了要做什么并让我开始了。 总的来说,我更喜欢一个适合复制粘贴的一行代码,而不是我的脚本 :) - raphinesse
@Ancurio 很高兴你喜欢这个脚本。你使用的是哪个操作系统?是否已安装 ed(运行 which ed 进行检查)? - raphinesse
@Ancurio 嗯,也许 echo '0a\n$SHA $f\n\n.\nw' 并不像我想象的那样具有可移植性。你能否尝试将其替换为 printf '0a\n$SHA $f\n\n.\nw\n'(注意末尾多出的 \n)? - raphinesse
很棒的解决方案。GIT_EDITOR行和sed很酷,但有点过头了:要在提交消息前加上前缀,你可以用(printf "%s %s\n\n" "$SHA" "$f"; git show -s --format=%B "$SHA") | git commit -F -来代替。 - undefined
显示剩余5条评论

2

每次提交代码,您都需要:

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

然后,您可以通过逐个提交文件构建的新提交来重置当前分支。


1
自己记录一下:这是我在Stack Overflow上的第16000个回答(98个月内),距离15000个回答不到6个月。在那之前,还有14000个回答13000个回答12000个回答11000个回答10000个回答9000个回答8000个回答等等。 - VonC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接