如何在git中压缩一定范围的历史?(专家)

如何在git中压缩一定范围的历史?(专家),git,Git,几个小时来一直在试图解决这个问题,但似乎找不到解决办法 因此,假设我有一个这样的存储库:a-B-C-D-E-F-G(master)(存储库有许多合并和数千次提交,因此这只是为了简化) 我希望它变成这样:A*-F-G(master) 其中A*是A、B、C、D和E提交的压缩提交(大约前2000次提交) 我曾尝试使用交互式重新基址压缩提交,但由于某些原因,我遇到了一些奇怪的错误,例如行已被#注释掉,以及“不应用”错误,即使我没有做任何更改。此外,我在交互式重基中得到的提交比我在git log中得到的提

几个小时来一直在试图解决这个问题,但似乎找不到解决办法

因此,假设我有一个这样的存储库:a-B-C-D-E-F-G(master)(存储库有许多合并和数千次提交,因此这只是为了简化)

我希望它变成这样:A*-F-G(master)

其中A*是A、B、C、D和E提交的压缩提交(大约前2000次提交)

我曾尝试使用交互式重新基址压缩提交,但由于某些原因,我遇到了一些奇怪的错误,例如行已被#注释掉,以及“不应用”错误,即使我没有做任何更改。此外,我在交互式重基中得到的提交比我在git log中得到的提交要少?为什么会这样

不管怎样,我现在正在这样做:

git branch new-branch

git reset --hard E

git reset --soft A

git commit --amend
在这一点上,我在一个*-存储库中进行一次提交


如何从这里开始添加-F-G提交,这些提交存在于A*上的新分支上?

Git是一组工具

你需要哪些工具来建造书架或书柜?也许一把台锯、锤子和钉子就可以了,尤其是如果你有一些护墙板头可以用来做漂亮的细木工。或者你可以使用其他类型的锯,一个用于制作细木工制品的刨子(燕尾榫!),一个用于钻孔的钻头,螺丝和螺丝刀。这样会更好吗

如果你想在家具的正面画些精美的卷轴怎么办?你想要带锯、跳汰锯、锉刀、锉刀吗?也许是凿子?你能用螺丝刀当凿子吗

Git是一个相当完整的工具集。你可以使用任何你喜欢的,只要你得到你想要的最终结果。哪一个最简单。。。这取决于你觉得什么容易。如果要处理的提交很少,则可以使用各种手动工具,例如
git-rebase-i--root
git-checkout--orphant
,然后执行特定操作。您的示例方法也很好:只需选择最后两个提交,使用旧的分支名称查找它们,如果您不再需要旧的分支名称,则丢弃它

记住也要更新您想要更新的任何标记。通常情况下,更新标记是个坏主意,但你基本上是在告诉所有拥有原始存储库克隆的人扔掉他们的整个克隆,而代之以你正在构建的新克隆,提交散列ID根本不匹配;新历史与原始历史完全无关


该方法也是一种简单的方法:使用git replace在要截断历史的位置插入根嫁接;然后在没有过滤器的情况下运行
git filter branch
(但使用
--all--tag name filter cat
),将移植物永久固定到位。这就是电动工具方法。

有一种方法可以截断书中描述的历史。它允许您在以后重新组装历史,如果您需要它来进行责备或平分,并在新历史的根中留下如何重新组装的说明

E处截断历史记录
  • F
    推至历史记录回购

  • G*F
    git cherry-pick
    git-rebase
    不起作用,cherry-pick在合并提交时非常不确定,我有一公吨的提交。您可以使用-m来控制cherry pick的合并,但是我想使用cherry pick A..B范围选项,如果您提供了-m标志,或者当您在范围内有合并时也没有提供-m标志,则f会失败。当他们没有完全相似的亲子关系时,我将如何对其进行重基?“当他们没有完全相似的亲子关系时,我将如何对其进行重基”
    git-rebase——在问题标题中的master branch~2 branch
    上,“专家”是什么意思?顺便说一句,在接下来的“无论如何,我现在正在做这个”中,你所做的是好的。@phd不就是在A*上重新应用B C D E,并显示在历史记录中吗?当使用过滤器分支时,截断是在有平行分支的点上,随后的合并将拉动旧的历史记录。嗨,谢谢你的评论。我运行了
    git replace--graft
    ,然后运行
    git log--reverse
    确实显示了repo的初始提交,然后第二次提交类似于repo的第1000次提交。那就完成了吗?我如何使用git过滤器分支来“固定嫁接”?@torek running
    git过滤器分支——tag name filter cat——all
    什么都不做,它只告诉我如何使用过滤器分支,什么都不做。(编辑:我忘了用
    git filter branch添加空过滤器--tag name filter cat--all
    现在它可以工作了。让我们看看它做了什么。完成了!非常感谢您的指导,git有这么多不同的工具和命令我需要学习…使用
    git replace
    的问题是这会向gr添加一个替换对象aph,保留原始图形。克隆存储库将克隆除替换对象以外的所有对象,以便新克隆可以看到旧的历史记录,而不是嫁接的历史记录。运行筛选器分支会根据嫁接的历史记录将所有内容复制到新图形,以便不再有嫁接。新的历史记录(新的提交集)现在将正确克隆,旧的历史将完全不可见。
    $ echo 'Instructions to get the history...' | git commit-tree E^{tree}
    new root sha (R)
    
    git rebase --onto R E
    
    G <- master     rebase     G* <- master
    |              -------->   |
    F <- history               F*
    |                          |
    E                          R instructions
    |
    D
    |
    .
    .
    
    git replace F* F
    
    G* <- master
     \_____________
                   \
         replace    \
    F* ------------> F <- history
    |                |
    R instructions   E
                     |
                     D
                     |
                     .
                     .