合并后的Git压缩历史

b09cbbtk  于 2023-06-28  发布在  Git
关注(0)|答案(5)|浏览(131)

我将一个大型项目的上游与我的本地git repo合并。在合并之前,我有少量的历史记录,很容易阅读,但在合并之后,大量的历史记录现在在我的仓库中。我不需要上游repo的所有历史提交。
在这次上游合并之后,还有其他提交,我想保留。我如何压缩所有从上游合并到一个提交中的历史,同时保留上游合并后的提交?

vc6uscn9

vc6uscn91#

给你几个选择:

限制日志记录

不完全是你所要求的,但可能是一个很好的选择,而且容易得多。这允许你像平常一样使用git,但是隐藏了所有你不想看到的东西(假设问题是历史记录弄乱了你的日志,而不是原始存储空间。我认为在你的分支中压缩合并并不会阻止git包含所有来自上游的提交,如果你在一开始就为合并操作获取了上游。)
在本例中,您将执行普通的合并,但在记录日志时,您将向命令添加--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

请注意,在我分支之后,来自master的所有提交(“我的本地更改”是我的发散提交)都消失了。只显示我提交的内容,包括我合并的时候。如果我在合并期间使用了更好的提交消息,我甚至可能知道这批更改是什么。

替换历史

这是你要的钱
灵感来自https://git-scm.com/book/en/v2/Git-Tools-Replace
我们在这里要做的是压缩遥控器的历史,用我们的压缩版本替换它们的历史,并合并压缩版本。
在我的示例仓库中,上游添加的我还没有合并的修订是682 b412“sample more 1”到origin/master(f578 cbb“sample more 3”)(尽管对于这个示例来说没有那么长,假设中间有50次提交或其他)。
我想要的第一件事是远程端的本地分支:

git checkout -b squashing origin/master

接下来,我想快速地把它压扁

git reset --soft 682b412~
git commit -m "Squashed upstream"

请注意波浪号~字符。这导致我们的分支位于我们想要压缩的范围内的第一个提交的父节点,并且因为我们指定了--soft,所以我们的索引仍然位于我们想要压缩的范围内的最后一个提交。提交行导致一个单一的提交,它由我们的第一个到最后一个提交组成。
此时,origin/master和squashing分支具有相同的树内容,但具有不同的历史。
现在,我们告诉git,当它看到origin/master的原始提交时,使用我们的压缩提交。使用git log,我可以看到新的“Squashed upstream”提交是1f 0 bc 14,所以我们这样做:

git replace f578cbb 1f0bc14

从这里开始,你的git将使用“squashed upstream”提交。
回到我们原来的分支(如果是“master”)

git checkout master
git merge f578cbb

这似乎合并了原始主机(f578 cbb),实际上获取了1f 0 bc 14的内容,但将其记录为具有f578 cbb的父SHA1
我们不再需要压分支,所以你可以摆脱它。
现在,让我们说上游增加了更多的功能。在这个简单的例子中,在upstream的repo上,日志可能会显示:

84f5044 new feature
f578cbb sample more 3
7bc88cf sample more 2
682b412 sample more 1
29ed293 More stuff
018cb03 Another commit
a5166b1 Initia

在我们获取上游数据之后,如果我们从repo中查看它的日志,我们会看到这样的结果:

84f5044 new feature
f578cbb squashed upstream
29ed293 More stuff
018cb03 Another commit
a5166b1 Initial

请注意,它似乎也压缩了我们的历史,更重要的是,压缩的上游SHA1显示了上游历史中使用的SHA1(对他们来说,这实际上是“sample more 3”提交)。
因此,合并继续正常工作

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

如果上游的“新特性”提交同样是大量的提交,我们可以重复这个过程来压缩它。

6vl6ewon

6vl6ewon2#

没有办法做到这一点,因为你将无法推回或合并再次与远程存储库或任何其他相同的项目。当压缩时,您正在更改历史,导致您的存储库和远程存储库之间的sha1散列不同。
你得接受这段历史。

nimxete2

nimxete23#

我也遇到过类似的问题。当您在没有最新提交历史记录的情况下解决合并冲突时,就会发生这种情况。如果您有旧PR,并且自创建旧PR以来已将许多更改合并到主PR,则可以重新创建该问题。我是这样解决的:

  • 使用git命令git fetch获取最新的提交历史。在主分支和特色分支上都这样做
  • 然后解决合并冲突。
iq3niunx

iq3niunx4#

我能够使用这里找到的策略在master分支的多次合并后压缩几个提交:https://stackoverflow.com/a/17141512/1388104

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

n9vozmp4

n9vozmp45#

我最终使用的解决方案是手动重新创建历史。我这样做主要是因为我不想花太多时间寻找一个优雅的解决方案,而且没有那么多的历史(大约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>

相关问题