在 2 git 次提交之间按文件 diff/patch 导出压缩文件?

Export a condensed file by file diff/patch between 2 git commits?

我发现这段代码可以从存储库中的特定位置导出补丁

git log --author=jdoe oldbranch..newbranch -p -- path/to/subdirectory > myChangesInSubdirectory.patch

当然,它是通过提交而不是全部揉在一起进行的,因为这就是补丁的作用。但我希望能够基本上说 "Here are the files in a particular folder that changed between commit a and commit b and what changed in them" 而无需对同一文件进行多次更改。

我可以从原始标签中手动创建一个新的 repo,然后复制到另一个分支并以这种方式进行一次提交,但我正在尝试找到一种单行 CLI 方式来输出它。

有很多方法可以做到这一点,具体取决于您想要的精确结果。

如果您想要区分两个特定的、已经存在的提交(可能也仅限于特定的文件/目录),git diff 会做到:

git diff rev1 rev2

或:

git diff rev1 rev2 -- path1 path2 ... pathN

如果您想要提交在特定日期范围内的更改,排除该范围之外的更改,则有点复杂。例如,考虑以下图形片段:

... - D - E - F - G - J - K ...
            \       /
              H - I

进一步假设提交 D 的日期是 "last Wednesday",但是提交 E 的日期是 "two months ago",因为提交 E 是向前的-从更早完成的事情移植(重新定位或类似)。同时提交 FG 是最近的,H 也是如此,但是 I 也像 EJK 也是最近的,但您认为 K 也是 最近的。因此,您想要的提交是 D 而不是 EFG;和 H 但不是 I.

在这种情况下,要将所有这些更改(而不是其他更改)作为一个补丁,您需要在 D 之前创建一个新分支,您可以在其中挑选(或等效)每一个承诺。您可以单独挑选它们,然后使用 git diff 生成从 "just before D" 到 "final result" 的补丁。在这种情况下,仍然有一种单行(ish)方法可以做到这一点,因为您没有进行任何合并:

git checkout -b deliver D^ && git cherry-pick \
    $(git rev-list --since=... --until=...) && \
git diff D^ HEAD [-- paths]

在这里,我们使用 git rev-list 选择所需的提交并将生成的 SHA-1 提供给 git cherry-pick,后者将它们添加到从以下位置创建的新分支 (deliver)提交 D^。假设一切顺利——不一定是一个好的假设——最终的 git diff 将我们的起点 D^ 与所有挑选之后的结果 HEAD 进行比较。

(这可以简化,如果你至少称之为简化 :-),通过创建 deliver 分支 after commit D 因为我们计划包括它。但是,我假设 --since--until 值是您决定首先包含哪些提交的方式,所以我认为这样更清楚一些。)

如果您打算在此处包含合并提交 J,这一切都会崩溃:合并提交可以是 "evil merge"(有关详细信息,请参阅 here and here),而这些不能是简单地挑选。因此,如果您 有一些奇特的要求,需要 运行 git rev-list 选择要包含的提交,请仔细检查。 (请注意,您可以使用 --merges 自动查找合并。)