以下场景:我有一个历史悠久的回购(从2006年开始使用的SVN迁移),并希望将较新的历史记录推送到外部服务器。
我有一个标记,比如说mytag
,并希望删除之前发生的所有提交该标记,但希望保留自此标记以来发生的历史记录
我尝试在Rebase many commits to one in Git. What am I doing wrong?的接受答案中这样做,但这会导致无休止的冲突解决。
我只想抛弃历史,同时能够将我的本地仓库(仍然拥有大量历史记录)合并到远程仓库(历史较短)。
我如何实现这一目标?
答案 0 :(得分:3)
更新:请注意,在下面我假设mytag
只有一个父提交,否则它会更复杂。
首先,让我们假设您只有一个root提交,而且它是f414f31
。 (如果您需要查找所有root提交,可以使用the first command in this answer执行此操作。)
为了安全起见,我们为此操作创建一个新分支,因此您的分支master
保持不变,以防结果不是您想要的。< / p>
git checkout -b new-master
将此分支重置为根提交:
git reset --hard f414f31
现在将工作树和索引更改为mytag
之前的提交相同:
git merge --squash mytag^
然后从索引创建一个提交 - 如果你想重写root提交,你可以用git commit --amend
来做,但是我希望在你的旧历史和新历史之间保持一个共同的提交,所以我和#39; d只做:
git commit
现在您需要做的是在该提交之后重播您的所有工作(包括)mytag
。这是git rebase
的用途,但默认情况下,它会线性化您尝试重播的所有历史记录。如果您在mytag
之后的历史记录中有许多合并提交,那么这可能是您看到许多冲突的原因。
所以,如果你不介意历史被线性化,你可以解决冲突(可能在git rerere
的帮助下),你可以这样做:
git rebase --onto new-master mytag^ master
但是,如果该历史记录中有合并,并且您希望保留它们,则可以尝试添加-p
(--preserve-merges
)选项,该选项将尝试重新创建它们:
git rebase -p --onto new-master mytag^ master
您在下面的评论中提出了另一个问题,即您有两个root提交的情况。在这种情况下,您可以选择其中一个,并在压缩合并后使用git commit --amend
为重写的历史记录创建一个全新的根提交。
答案 1 :(得分:2)
如果您想重写/删除历史记录,那么您正在寻找git filter-branch。这是一个很好的thread ,讨论了如何删除提交。 $ drop变量将是mytag之前的提交。