首页 > 解决方案 > 创建 git commit C,它是 B 和 A 之差的倒数

问题描述

所以,我有一个私下工作多年的 git 存储库。基本上,我只使用了一个分支(MASTER),而 git 对我来说基本上就像一本日记。现在,我想公开此源代码,但我想删除我无权重新分发的文件。我还想删除一些我不想公开的评论。

不过,这些私人评论和不可分发的文件对我来说仍然很重要。

假设我最近的提交称为 A。我可以创建一个公共分支 (PUBLIC),并删除所有不能公开的内容并进行新的提交。我们将把那个新的提交称为 B。然后我可以通过一些选项克隆那个存储库,删除历史记录,然后发布新的存储库和分支。然后我可以从现在开始在这个公共分支中与我未来的合作者一起工作。

这适用于公共方面,但我不知道如何有效地捕获已删除的内容。当然,我的原始存储库中有我的旧分支,但是对它进行排序以找到我后来忘记从新公共分支中删除的小评论和更改并不是很有效。

有没有办法使具有新提交 C 的第三个分支(PRIVATE)代表 A 和 B 之间的区别?

例如:

Commit A (MASTER)
 |  |   - File 1 (text file)
 |  |   - File 2 (text file)
 |  |   - File 3 (binary file)
 |  |   - File 4 (text file)
 |  |   - File 5 (text file)
 |  |   - File 6 (text file)
 |  |   - File 7 (text file)
 |  |   - File 8 (text file)
 |  |   - File 9 (text file)
 |  |
 |  Commit B (PUBLIC)
 |     - File 1 (text file)
 |     - File 2 (text file)
 |     - File 4 (text file)
 |     - File 7 (same except for line 2 removed)
 |     - File 8 (same except for line 4 edited)
 |     - File 9 (same except for a new line inserted between line 8 and line 9)
 |     - File 10 (new text file)
 |     - File 11 (new binary file)
 |
Commit C (PRIVATE)
   - File 3 (binary file)
   - File 5 (text file)
   - File 6 (text file)
   - File 7 (only shows line 2)
   - File 8 (only shows the original line 4)

基本上我正在尝试获取分支 MASTER,将其分支到一个新的分支 PUBLIC,然后自动将分支 MASTER 分支到一个新的分支 PRIVATE,其最新提交在 PUBLIC 的最新提交中不包含任何内容。基本上,我想自动拆分,或拆分分支 MASTER,只是删除一些东西。


更新

我做的一件事是,在 PUBLIC 分支上创建 Commit B 后,切换到 PRIVATE 分支,然后运行

rm -r *
git diff --binary --no-ext-diff B..A|git apply --reject

这将适用于File 3, File 5, File 6,但对于File 7and File 8,它会与No such file or directory.

如果我改为运行

rm -r *
touch "File 7"
touch "File 8"
git diff --unified=0 --binary --no-ext-diff B..A|git apply --reject

这将适用于File 3, File 5,File 6File 7,但File 8它会将一些东西(更改的行)放在一个名为的文件中File 8.rej。这越来越接近我想要的了,但是在touch这里使用命令是不切实际的,因为我不知道实际更改了哪些文件。


更新 2

我可以使用以下内容自动触摸修改过的文件:

git diff --diff-filter=M -z --name-only B..A| xargs -0 -IREPLACE touch REPLACE

我还可以使用:

find . -type f -name '*.rej' -print0 | xargs -0 rename -f 's/.rej$//'

如果我想用 .rej 文件覆盖空的(接触的文件)并摆脱 .rej 文件。但是,我不确定是否可以部分应用文件上的补丁,因此可能会有一些情况下原始文件有一些更改(触摸的文件可能并不总是保持空白),而其他文件则进入 . rej 文件。因此,这一步可能并不完全安全。

我认为我现在选择的是

rm -r *
git diff --diff-filter=M -z --name-only B..A| xargs -0 -IREPLACE touch REPLACE
git diff --binary --no-ext-diff B..A|git apply --reject

跳过该--unified=0选项会将行删除和行更改都放入 .rej 文件中(我得到 aFile 7.rejFile 8.rej)。

在这种情况下,我在 PRIVATE 分支中得到的是,在 PUBLIC 分支中删除的任何文件都将被恢复,任何有删除或更改的文件,我基本上在它自己的文件中为每个文件获得一个单独的差异。我也选择将 .rej 文件留在那里,因为如上所述,我不知道这样做是否安全。

但是,此过程不适用于在 PUBLIC 分支中重命名的文件。如果在 PUBLIC 分支中重命名文件,则原始文件将在 PRIVATE 分支中完全恢复(就像它被删除一样)。如果文件被修改和重命名,整个文件也会在 PRIVATE 分支中完全恢复,因此您无法判断该文件中是否有任何更改或删除。

标签: gitsplitbranchdiffcommit

解决方案


推荐阅读