我将一个大型项目的上游合并到了我的本地git仓库。在合并之前,我的历史记录很少,很容易查看,但是在合并之后,我的仓库中出现了大量历史记录。我不需要来自上游仓库的所有历史提交。
在这个上游合并之后,已经有了其他提交,我想保留它们。如何将合并自上游的所有历史压缩成一个提交,同时保留在上游合并之后所做的提交?
我能够使用这里找到的策略,在从主分支进行多次合并后,压缩了几个提交记录:https://dev59.com/WG025IYBdhLWcg3wCxVN#17141512
git checkout my-branch # The branch you want to squash
git branch -m my-branch-old # Change the name to something old
git checkout master # Checkout the master branch
git checkout -b my-branch # Create a new branch
git merge --squash my-branch-old # Get all the changes from your old branch
git commit # Create one new commit
如果您需要将已经压缩的分支推送到之前已推送过的远程代码库上,您需要强制更新,例如:git push origin my-branch -f
我最终采用的解决方案是手动重新创建历史记录。我这样做主要是因为我不想花太多时间寻找一个优雅的解决方案,而且历史记录并不是很多(大约有30个提交需要手动合并)。
因此,在我合并巨大的上游之前,我创建了一个分支:
git checkout -b remove-history-fix <commit ID before merge>
然后使用--squash
选项重新合并上游。
git merge --squash <upstream tag>
然后手动从旧分支(具有大量上游历史记录的分支)合并后挑选提交内容。
git cherry-pick <commit ID>
在所有这些提交合并到我的remove-history-fix分支之后,我将带有上游历史记录的分支删除了。git branch -D <upstream-history-branch>
以下是几个选项:
这不完全是你所要求的,但可能是一个好的替代方案,而且更加容易。这允许您像平常一样使用git,但隐藏了所有您不想看到的东西(假设问题是历史记录杂乱无章,而不是原始存储空间。如果您在第一次获取upstream时就为合并操作获取了upstream,则在分支中压缩合并不会阻止git包括来自upstream的所有提交)。
在这种情况下,您将执行普通合并,但在记录日志时,您将向命令添加--first-parent
。
例如,如果没有此选项,我可能会有以下提交记录(假设“sample more”1到3实际上是更多的提交记录):
$ git log --oneline
0e151bf Merge remote-tracking branch 'origin/master' into nosquash
f578cbb sample more 3
7bc88cf sample more 2
682b412 sample more 1
fc6e1b3 Merge remote-tracking branch 'origin/master'
29ed293 More stuff
9577f30 my local change
018cb03 Another commit
a5166b1 Initial
但是,如果我添加--first-parent
,它会变得更加简洁:
$ git log --oneline --first-parent
0e151bf Merge remote-tracking branch 'origin/master'
fc6e1b3 Merge remote-tracking branch 'origin/master'
9577f30 my local change
018cb03 Another commit
a5166b1 Initial
注意,我分支后主分支的所有提交(“我的本地更改”是我分叉提交)都消失了。只有我做过的提交显示出来,包括合并时的提交。如果我在合并时使用更好的提交消息,我甚至可能知道这批更改是什么。
这是你所要求的内容。
从https://git-scm.com/book/en/v2/Git-Tools-Replace中获取灵感。
我们将在此处压缩远程历史记录,用我们的压缩版本替换他们的历史记录,并合并压缩版本。
在我的示例存储库中,上游添加但我尚未合并的修订版为682b412“sample more 1”到origin/master(f578cbb“sample more 3”)(虽然对于此示例不那么长,请假装之间有50个提交或其他)。
我想要的第一件事是远程侧的本地分支:
git checkout -b squashing origin/master
接下来,我想快速压缩它
git reset --soft 682b412~
git commit -m "Squashed upstream"
~
。这会导致我们的分支位于我们要合并的第一个提交的父级,并且因为我们指定了--soft
,所以我们的索引仍然位于我们要合并的最后一个提交处。提交行结果是一个包含我们从第一个到最后一个提交的单个提交。git log
我可以看到新的"Squashed upstream"提交是1f0bc14,所以我们执行:git replace f578cbb 1f0bc14
从这里开始,你的Git将使用“压缩上游”提交。
回到我们原来的分支(如果它是“master”)
git checkout master
git merge f578cbb
这似乎是将源主分支(f578cbb)合并,实际上获取了1f0bc14的内容,但将其记录为具有父SHA1为f578cbb
我们不再需要压缩分支,所以可以摆脱它。
现在,假设上游添加了更多功能。 在此简单示例中,在上游的存储库上,日志可能显示如下:
84f5044 new feature
f578cbb sample more 3
7bc88cf sample more 2
682b412 sample more 1
29ed293 More stuff
018cb03 Another commit
a5166b1 Initia
在我们拉取上游代码后,如果从我们的代码库查看其日志,我们会看到以下内容:
84f5044 new feature
f578cbb squashed upstream
29ed293 More stuff
018cb03 Another commit
a5166b1 Initial
git merge origin/master
4a9b5b7 Merge remote-tracking branch 'origin/master' for new feature
46843b5 Merge remote-tracking branch 'origin/master'
84f5044 new feature
f578cbb squashed upstream
fc6e1b3 Merge remote-tracking branch 'origin/master'
29ed293 More stuff
9577f30 my local change
018cb03 Another commit
a5166b1 Initial
git fetch
获取最新的提交历史。在主分支和特性分支上都执行此操作。无法这样做,因为您将无法将更改推回或合并到该远程存储库或该项目的任何其他存储库中。当压缩时,您正在更改历史记录,导致您的存储库和远程存储库之间的sha1哈希不同。
您必须接受大量历史记录。