从现有提交中挑选和排除文件来创建新提交?

Creating a new commits out of picking and excluding files from existing commits?

在工作场所,团队在自己的功能分支中完成工作,合并开发分支中的功能,然后最终将提交的内容挑选到生产分支中。服务器提供来自生产分支的文件。也就是说,生产分支里的东西就是public网站上展示的东西。换句话说,团队 cherry 不是通过 FTP 上传文件,而是从包含新文件的功能分支中选择提交到生产分支,然后在 Web 服务器上执行 git pull origin production 以更新文件。

我不熟悉这样的工作流程,因为我通常通过 FTP 上传,而且我可以完全自由地只上传需要的文件。我想知道,在这样的工作流程中,是否可以根据现有提交重新创建包含选定文件的新提交?

举个例子,假设我在 MyFeatureBranch:

中做了 2 次这样的提交(Commit ACommit B 之前)
Commit B:
Removed 1 line from FileA.
Added 2 lines to FileB.
Deleted FileC
Added 1 line to package.json

Commit A:
Added 2 lines to FileA.
Removed 5 lines from FileB.
Created package.json.

如何在 Commit B 之上创建一个 Commit C,其中包含文件 FileA 和 [=] 的 Commit ACommit B 中的合并更改20=] 但 排除 文件 package.json(或更多要排除的文件)?

我不能使用 gitignore,因为我仍然需要将更新的 package.json 推送到 develop 分支。

我打算有一个像这样的 Commit C 是为了我可以轻松地从 MyFeatureBranchproduction 分支做一个 git cherry-pick CommitC,并获得我所有的更新(想要和不需要的文件)现在投入生产。我也许可以一一挑选提交,但 package.json 仍将被复制到生产分支中,因为它在 Commit A.

那么,是否可以从选定的文件中创建新的提交并从现有提交中排除文件?

首先: 按照您描述的方式使用 cherry-picking 似乎不是一个好的工作流程。这将使 git 的工作比所需的困难得多,因为有多个分支包含大部分相同的代码但缺少共同的历史记录。修改该工作流程并以更简单的方式解决 cherry-picks 解决的问题可能是个好主意。

您还应该与已经遵循此工作流程的团队核实他们如何解决所描述的问题。也许存在一些避免执行此解决方法的工作流程,而您只是不知道?


如果您确实需要,我会向您推荐这种生成 Commit C 的方法,因为此过程相当容易遵循,同时仍保持文件的干净历史记录。您可以在下面找到一些可能也有效的替代方案的提示。

从提交 A 的父提交中签出一个新分支。您可以使用 git log 或仅使用 A^(其中 A 是提交 A 的哈希值)找到该提交,这将始终引用A 的父提交(假设 A 不是合并提交,它也不适用于 cherry-picking 进程)。

git checkout -b cherry-pick-preparation A^

cherry-pick-preparation 是用于准备 cherry-pick 的新分支的名称。您需要在挑选提交后删除它或下次使用其他名称。也可以在不创建新分支的情况下完成所有这些操作,但是我会避免这样做,以确保您在出错时可以返回工作。

现在从您的分支中选择所有更改而不提交它们。 B 可以是最后一次提交的哈希值,也可以只是分支的名称。

git checkout B -- .
git reset HEAD .

这会将您的所有文件设置为与 B 中相同的内容。您可以使用 git statusgit diff 进行查看。 您现在可以撤消您不想稍后挑选的所有内容。如果您需要重置完整的文件,您可能需要执行 git checkout -- file1 file2 file3 来重置这些文件。 完成后提交更改。生成的提交可以在其他任何地方挑选。


您还可以查看 Interactive Rebasing,它允许您在不创建新分支的情况下更改分支的历史记录。您可能希望 "edit" 更改您的提交并删除您不想挑选的更改,并 "squash" 将您的提交合并为一个。


您还可以在 A 和 B 之上添加提交 C,这只会撤消您在生产中不想要的更改,然后挑选所有三个提交。生成的文件将与以前相同 - 但在历史记录中 package.json 的更改是可见的。这很可能不是一个好主意,因为之后很难跟踪文件的历史记录。