我有两个分支,develop和master。我想挑选一些关于一个特定功能的提交,从开发到主功能。但是从dev到master的cherry-pick提交数量大约为106,这意味着我必须遍历所有这些提交才能过滤掉相关的提交。为了避免不得不经历每次提交的更改,然后挑选单个或一系列的更改,我想走捷径:D。我将development合并到master中,在合并提交中大约有115个文件更改。
我浏览了每个文件,并删除了那些与该功能无关的更改。对于某些文件,我完全删除了它们,对于一些文件,我只进行了部分更改,并删除了不必要的更改。在浏览了所有115个文件后,剩下大约55个经过过滤的文件,这些文件与我在合并提交中提交的功能相关。
现在,当我查看master的git日志时,日志显示好像所有106个提交都被合并到了master中,并且在顶部显示了我的名为"merged-development-to-master"的合并提交。现在我想将development合并到master中,以便真正合并我之前从合并提交中删除的剩余文件,git说没有什么可以合并的,尽管两个分支之间都有更改,但由于我从合并提交删除了这些更改,我现在无法将这些更改移到master中。我需要从主文件中删除合并提交吗?或者有任何方法可以强制完全合并差异吗?为了避免未来出现任何问题,应该采取什么正确的方法?
不幸的是,您的快捷方式误用了"merge"。当你试图合并两个分支,获取冲突,手动解决它们,然后提交合并时,你告诉Git,合并这两个分支(以及所有在这两个分枝上进行的提交)的"正确"方式是你选择手动解决提交的方式。如果你从develop
"重新合并",Git不会否决你的手动冲突解决方案,因为你已经告诉Git什么是正确的合并,它也不会试图反驳你(好吧,除非它真的很困惑)。Git无法区分您为解决两个合并所做的更改与您希望"稍后保存"的更改。
您将必须重置错误的合并,但以下是如何相对自动地完成合并,而不需要太多麻烦。您提到自合并后您在master
上又进行了一次提交。如果根本没有,你可以跳过几个步骤,但我在下面给出了更通用的解决方案,如果你在master
和develop
上都添加了额外的提交,它也会起作用。
我假设如下。
- 当您进行"错误合并"时,您将
develop
合并到master
中(即,您在master
上运行git merge develop
,而不是相反) - 在这一点上,您不太关心历史记录的外观,您只想从"坏合并"之前的
develop
中获得"丢失"的更改(加上此后的其他更改,如果您有)成功合并到master
中 - 您尚未在任何地方发布
master
或develop
,因此没有其他发布依赖于它们的历史记录 - 您当前已在干净的树中签出了
master
与任何混乱的Git操作一样,在这里对存储库进行完整备份(cp -a
或git clone mirror
)不是一个坏主意。
首先,让我们命名糟糕的合并。在你的日志中找到它的散列,并为它创建一个标签。(在你的情况下,它是master^
,但更常见的是,你可能必须搜索它。)
git tag bad_merge 8354cbeb
git log bad_merge # !! double check that this points to the bad merge !!
现在,我们将查看一个新的fix_merge
分支。我们将从bad_merge
:开始
git checkout -b fix_merge bad_merge
然后,我们将把分支回滚到"坏合并"之前的master
状态,但保持工作目录不变(因此它包含手动编辑以将第一个功能添加到master
):
git reset HEAD^
我们将重新推荐这些手动编辑:
git add -A
git commit -m 'fix_merge: add first feature to master'
现在,我们要做一个有点复杂的重新基准。(如果由于合并失败,在master
上没有任何提交,那么这是不必要的步骤。)
git checkout master
git branch master_backup # make a copy in case something goes wrong
git rebase --onto fix_merge bad_merge master
这将在master
分支上所做的更改从坏合并后的移植到其当前状态(即,从bad_merge
到master
的树的部分)ONTO我们修复的分支fix_merge
。再碱基后,master
将指向移植的分支。不应该有冲突,因为bad_merge
和fix_merge
中的树完全匹配;只是提交历史被重写了,因为一个有合并,另一个没有。
我们现在有以下情况:
master
的历史记录,而不是从develop
进行合并,现在只需提交一次手动编辑即可添加第一个功能,再加上自错误合并以来在master
上所做的额外工作。它缺少的是从develop
(糟糕地)合并而来的历史。develop
分支现在有第一个功能的(复杂)历史,加上您在错误合并之前开发的但希望"保存以备将来使用"的功能,再加上您此后所做的额外工作(在您的情况下没有,但此解决方案也适用于这些功能)。
如果你从develop
中精心挑选了第一个功能,这或多或少就是你的处境,只是它都是在一次提交而不是多次提交中精心挑选的。现在,如果将develop
合并为master
:
git checkout master # probably already there, but make sure
git merge develop
并解决任何冲突——可能会有很多冲突,因为Git试图将develop
分支中第一个功能的所有单独提交与master
中的大型单片提交相匹配,所以这可能是一个丑陋的合并——然后你可以提交合并:
git commit
并且您最终应该成功地将master
与来自develop
的所有更改合并,无论是在错误提交之前还是之后。
此时,您可能需要考虑将master
合并回develop
,或者完全放弃develop
并从master
重新分支它。
我认为这里需要做的是添加一个小的更改来开发分支(让它成为一个额外的空间),然后切换到mastergitmergedevelop将添加更改,包括您之前删除的已删除更改然后git-push为了避免未来的问题,我认为每个功能都应该在一个分支上,一旦完成,就会合并到主