我将一个大项目的上游与我当地的git repo合并。在合并之前,我有一些易于阅读的历史,但在合并之后,我的回购中有大量的历史记录。我不需要上游回购的所有历史记录提交。
我希望保留此上游合并之后的其他提交。如何在上游合并后保留提交的同时,将从上游合并的所有历史记录压缩到一个提交中?
答案 0 :(得分:10)
我最终使用的解决方案是手动重新创建历史记录。我这样做主要是因为我不想花太多时间寻找一个优雅的解决方案而且没有那么多的历史(大约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>
答案 1 :(得分:2)
为您提供几种选择:
不完全是你要求的,但可能是一个很好的选择,而且更容易。这允许你像平常一样使用git,但是隐藏了你不想看到的所有内容(假设问题是历史混乱你的日志而不是原始存储空间。我认为压缩你的分支中的合并赢了&如果您首先获取合并操作的上游,则阻止git包含来自上游的所有提交。)。
在这种情况下,您将进行正常合并,但在记录时,您会将--first-parent
添加到命令中。
例如,没有我可能有的选项(假设&#34;样本更多&#34; 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
注意我分支后所有来自主服务器的提交(&#34;我的本地更改&#34;是我的不同提交)都没了。只有我提交的提交,包括合并时。如果我在合并期间使用了更好的提交消息,我甚至可能知道这批更改是什么。
这是你提出的问题。
从https://git-scm.com/book/en/v2/Git-Tools-Replace
中汲取灵感我们在这里所做的就是压制遥控器的历史,用我们的视角用我们压扁的版本替换他们的历史,然后合并压缩的版本。
在我的示例存储库中,我没有合并的上游添加的修订版本是682b412&#34;示例更多1&#34; to origin / master(f578cbb&#34;示例更多3&#34;)(虽然这个例子的时间不长,假装有50个提交或介于两者之间)。
我想要的第一件事是远程方的本地分支:
git checkout -b squashing origin/master
接下来,我想快速压缩它
git reset --soft 682b412~
git commit -m "Squashed upstream"
请注意代字号~
字符。这导致我们的分支位于我们想要压缩范围内的第一个提交的父级,并且因为我们指定了--soft
,所以我们的索引仍然是我们想要压缩范围内的最后一次提交。提交行会产生一个提交,其中包含我们的第一个到最后一个包含的内容。
此时,原始/主人和挤压分支具有相同的树内容但历史不同。
现在,我们告诉git当它看到对origin / master的原始提交的引用时,使用我们的压缩提交。使用git log
我可以看到新的&#34; Squashed upstream&#34; commit是1f0bc14,所以我们这样做:
git replace f578cbb 1f0bc14
从这里开始,你的git将使用&#34;压扁的上游&#34;提交。
回到原来的分支(如果是#34; master&#34;)
git checkout master
git merge f578cbb
这似乎合并了原始主文件(f578cbb),实际上获得了1f0bc14的内容,但是将其记录为具有f578cbb的父SHA1
我们不再需要挤压分支,所以你可以摆脱它。
现在,让我们说上游添加了更多功能。在这个简单的例子中,在上游的repo中,日志可能会显示:
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
请注意它似乎也给我们带来了压扁的历史,更重要的是,压扁的上游SHA1显示了上游历史中使用的那个(对于他们来说,它实际上是&#34;样本更多3& #34;承诺)。
因此,合并继续像正常一样工作
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
如果&#34;新功能&#34;在上游提交同样是大量的提交,我们可以重复这个过程来压缩它。
答案 2 :(得分:2)
我可以使用以下https://stackoverflow.com/a/17141512/1388104
策略从master分支中压缩多个提交。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
答案 3 :(得分:0)
无法执行此操作,因为您将无法再次向后推送或与该远程存储库或任何其他同一项目合并。压缩时,您正在更改历史记录,从而导致存储库与远程存储库之间出现不同的sha1-hash。
你将不得不忍受大历史。