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

Posted

技术标签:

【中文标题】如何按文件拆分每个提交?【英文标题】:How to split every commit by file? 【发布时间】:2017-04-03 13:52:08 【问题描述】:

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

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

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

【问题讨论】:

按文件拆分提交并没有什么意义,因为这样您将有许多提交,其中一个文件更改了其接口,但其协作者没有反映该更改。如果您不关心细节,那就错在挤压而不是分裂。 【参考方案1】:

脚本

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

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

【讨论】:

有趣的脚本,比我的回答更详细。 +1 @VonC 您的回答很好地概述了该怎么做,让我开始了。总而言之,我更喜欢复制粘贴友好的单行而不是我的脚本,虽然:) 很棒的脚本,只是 GIT_EDITOR 行不适合我。我将其更改为 git commit -m "$SHA: $f" 以获得更简单的提交消息,现在脚本运行良好 =3 @Ancurio 很高兴你喜欢这个脚本。你在哪个操作系统上?是否安装了ed(运行which ed 进行检查)? @raphinesse yes which ed 积​​极响应。我在 Fedora 31 上。【参考方案2】:

对于每次提交,您都需要

先到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

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

然后,您可以通过 commit-file 构建的新提交文件重置当前分支。

【讨论】:

自我说明:这是我在 Stack Overflow 上的 第 16000 个答案(98 个月内),距离15000th answer 不到 6 个月。在此之前14000th answer,1300th answer。 12000th answer; 1100th answer, 10000th answer, 9000th answer, 8000th answer, ...

以上是关于如何按文件拆分每个提交?的主要内容,如果未能解决你的问题,请参考以下文章

sh 按文件拆分提交

如何在 Git 存储库中按作者计算每个文件路径名的提交次数?

R:具有多个标题的列表-如何按标题拆分(每个标题的行数不等)

按年份和 ID 拆分 txt 文件,并将每个新的 txt 文件重命名为“Year_ID.txt”

如何按没有的百分比拆分文件。行数?

将文件按行拆分到 bash 中的特定子文件夹中