Git:合并来自分支的部分更改

zaqlnxep  于 2023-04-28  发布在  Git
关注(0)|答案(4)|浏览(291)

一段时间以来,我们一直在研究一个工作分支,打算在某个时候将其带回我的主要分支。
与此同时,该工作分支通过与主要分支的频繁合并而保持最新。
现在,我们只想将工作分支的一些更改,而不是全部更改带到主分支。
这里的困难在于,这些更改根本没有被提交或文件很好地分隔开,因为从来没有人期望必须这样做。相反,单独的提交会带来我们想要在我的主分支上的更改,以及我们不想要在我的主分支上的更改。可以在任何给定的单个文件中看到这两种更改的示例。
现在,仍然有一种可能性,最终,我们将希望按照最初的计划,将该工作分支最终合并回主分支。因此,我需要保持这种可能性,它需要提供一个很好的保证,一切确实已按计划合并-或至少是一个很好的方式来检查。
正因为如此,我觉得git cherry-pick(假设它可以下降到文件中的单个块的级别)不是我想要的选项,因为这样一来,一方面来自工作分支的所有原始提交,另一方面来自主分支的樱桃采摘生成的提交都将是愚蠢的冲突,看起来两个分支都带来了相同的变化。此外,日志将看起来完全丑陋的重复日志评论。
我宁愿有一个单一的提交说:“把所有与X和Y相关的更改,而不是Z从工作分支。然后过了一段时间,如果我们愿意的话,另一个提交说:“从工作分支带来剩余的更改,主要是关于Z的。”“我想最后一个最好有两个父母,但我不知道第一个最理想的是什么:它是否应该在工作分支中有一些提交作为其父分支?所以是merge而不是cherry-pick
同时,如果我决定使用一个实际的merge来创建第一次提交,我将不得不手动删除主分支上的代码中的内容,以忽略通过这个merge来自工作分支的关于Z的更改。然而,由于第一次提交将工作分支的顶端作为其父分支之一(这是一个实际的merge),因此在git看来,第一次提交包含了来自工作分支的所有更改-但这不是真的。
可能是我把自己置于一个git无法干净或原生地解决的情况下,如果是这样的话,我想知道,我会没事的。我仍然会对其他降级的解决方案感兴趣,这将打破我的一些要求。

f3temu5u

f3temu5u1#

您的最佳选择IMO是:

  • 在特性分支上进行一次提交,撤消不需要的更改。
  • 将结果合并到main。
  • 恢复功能分支上较早的提交以恢复不需要的更改。

恢复的更改现在可以在特性分支上存在,直到决定合并它们,或者如果它们仍然不需要,则可以放弃它们。

baubqpgj

baubqpgj2#

方法1

  • 将当前main合并到feature
  • 基于当前main创建并 checkout 新分支partially-merge-feature-into-main
  • partially-merge-feature-into-main上,使用git checkout -p feature -- .有选择地选择要保留/编辑并提交更改的文件更改块。
  • partially-merge-feature-into-main合并到feature中,并在发生冲突时始终采用“--ours”i。feature版本。

因此,合并应该不会改变任何东西。
(But它将允许你以后合并feature到分支而不会再次发生这些冲突)

  • 合并partially-merge-feature-into-main(最好是与--no-ff合并,这样人们就知道那里发生了什么)
    方法2
  • feature上创建一个提交,删除main上不需要的所有内容

(完全手动或首先合并main,然后在提交之前使用git checkout -p main -- .选择性地丢弃不需要的更改/块)

  • feature合并到main
  • 在特性上,恢复第一步的提交,以重新包含删除的更改。
svdrlsy4

svdrlsy43#

这里有一个完全不同的方法。既然你的提交历史已经是一团糟了,那就放弃它并清理它:

  • 将分支重定基准到主管上。
  • 将分支重置(混合)回主分支。
  • 使用git add,可能与补丁,交互式等。,以形成一个“好”提交的索引基础,该提交由您现在想要合并的内容组成。做出承诺。
  • 隐藏,以便git status报告干净。
  • 切换到main,合并特性分支,并丢弃这个特性分支。

你可以在这一点上停止,与stash保存的东西,你可能会或可能不会合并后。但是如果你打算进一步开发这些材料,那么,仍然在main上,创建一个新的分支并切换到它,弹出隐藏并添加所有内容并提交。现在有一个特性分支在等待,它只包含以后可能会合并到main中的内容。

jdzmm42g

jdzmm42g4#

一些备选方案:

Rebase

交互式地将特性分支重新定位到main上,检查和修改每个提交。
将交互式变基中的每个提交都设置为“编辑”,除了那些你知道你会完全丢弃的提交(将这些设置为“跳过”)。在每次提交时,rebase暂停,让您有机会查看更改(git show),并可能修改它(git reset HEAD~可能很方便,使所有更改在diff中可见),然后提交它(git commit --amend),然后继续使用rebase --continue
但是如果你的分支历史是一团乱,你可能无论如何都想把它抛在身后。如果你认为有更多的变化要放弃,而不是带来的变化。

丢弃历史,使用补丁文件

保存git diff main...feature > feature-changes.patch保存功能分支中发生的全部内容(注意!3个点!)。
查看此文件的内容。确保所有更改都在那里。如果您已经将main合并回feature,则可能需要手动查找main的提交(feature最初基于该提交),然后运行git diff <that commit> feature > feature-changes.patch
现在,您将在修补程序文件中对特征分支进行的所有更改。
修改补丁文件,只留下您想要的块,然后将其应用于maingit checkout main然后git apply feature-changes.patch)。

通过文件系统获取更改

checkout 分支,将其重置为main,进行新的提交。
git checkout feature更新文件系统。
git checkout -b migrate-to-main允许您在新分支上工作,而不会有丢失feature的风险。
git reset main将当前 checkout 的分支(记住分支只是指向提交的标签)移动到main,但保持文件系统上的内容不变。
您现在位于新分支migrate-to-main上,它指向与main相同的提交,并且您的文件系统具有与feature相同的内容。
您现在可以查看diff,决定要包含哪些内容,不包含哪些内容,还可以解决其中可能存在的冲突。您可以手动执行此操作,或使用git-gui等工具选择要包含或不包含的内容。
当你完成了,剩下的就是承诺。

相关问题