Git:如何按文件(而不是按提交)拆分分支?

18

底线:

我想将一个拉取请求分成两个较小的拉取请求,具有不同的文件子集。 我不想按提交拆分,我想按文件拆分。

详细信息:

假设我有一个名为branch_1的分支(从master分支派生),其中我修改了2个文件:file_1file_2。 假设这些文件在一个或多个提交中一起修改(更改不能通过提交分离),并且假设这些文件没有以任何方式相互引用。

过一段时间后,我想将branch_1合并到master,但决定仅准备将file_1合并。 我以后可能会合并file_2,因此我将其放在一个新分支上。

所以我在branch_1上创建了一个branch_2。 现在,branch_2现在包含对file_1file_2的更改。 这没关系,因为无论如何branch_2都将在branch_1之后合并。

现在,我如何优雅地还原branch_1以删除对file_2的更改?

如果我只是在branch_1上进行git checkout master file_2,它可以工作,但是:当我将branch_1合并到master,然后将master合并到branch_2时,它将删除file_2。 这根本不是我想要的!

基本上,我希望就像file_2branch_1上从未存在过一样。

3个回答

27

一种更方便选择特定文件的方法:

  • master创建branch_2
  • 使用--no-commit和--squash将branch_1合并到branch_2
  • 撤销您想要从新分支中排除的特定文件(*)
  • 提交在branch_2中剩余的文件

现在,您可以再次使用相反的文件选择重复该过程,立即完全拆分这两个分支,或者等待将branch_2合并到master中,然后将master合并回branch_1中,从而“快进”选定的文件并将其从原始branch_1中排除。

(*) 许多基于UI的git客户端提供批量还原工具,使该过程非常舒适

编辑:添加了--squash选项,否则来自branch_1的提交可能只在master中以其实际内容的子集存在


笨拙的后续:这会丢失历史记录,对吗?也就是说,如果我将30个文件从CommitA更改为CommitB,在CommitA上创建分支,使用--no-commit--squash将CommitB合并,然后在CommitC中提交其中的10个文件并丢弃其他文件,那么这些10个文件的历史记录就会丢失;在这些文件的日志中只有CommitC。如果我将CommitB分支合并到我的新分支中,我就可以“恢复”我在新分支中丢弃的20个文件的历史记录,但其他10个文件的历史记录仍然丢失。虽然不是世界末日,并且大多数情况下都是预期的,但如果有其它选择的话,这并不理想。 - ruffin

0

所以,我得出结论,git没有一个好的机制来实现这个,但使用PyCharm(和可能一些其他工具)很容易做到。

要使用pycharm,首先git checkout master,然后git checkout branch_3,然后在Pycharm的项目工具栏中右键单击项目的根文件夹,选择Git -> Compare with Branch,选择branch_1,然后将你想要合并的file_1branch_1复制到你当前的代码(branch_3)。现在你可以从branch_3master发起拉取请求。


-2

我不会从branch_1创建branch_2,而是从master分支创建branch_2并进行您要求的更改,将其合并到主分支,然后再将branch_2合并到branch_1

这基本上是git工作流程(这里有不错的阅读材料)


2
事后诸葛亮。问题通常是,直到更改完成后,您才意识到这两个更改应该在不同的分支上进行。我正在询问当这些更改已经完成时该怎么办。 - Peter
1
这有点棘手,除非你将它们分别提交并生成一个“补丁”来分离它们。 - webbyfox

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