我该如何恢复 git 历史重写?

6
我正在使用 git filter-branch --tree-filter 重写一个相当大的存储库的历史记录,这需要几个小时。我看到 git 正在使用一个临时目录来存储它的中间工作。这是否意味着如果重写被中断,可以恢复它?如果可以,如何操作? 编辑 我正在进行的操作是移动一些目录。这些目录当前位于子目录中,但现在我需要它们位于根目录下。
例如:
dir1
- dir2
- dir3
- dir4

变成

dir1
- dir2
dir3
dir4

当然,我的目录结构比那复杂得多,但这就是我试图做的要点。


1
出于好奇(并非您问题的核心),您能描述一下您使用 --tree-filter 进行的操作吗?是删除还是修改文件? - Roberto Tyley
2个回答

14

git filter-branch本身不支持挂起/恢复模式的使用——虽然它会将临时数据写入.git-rewrite文件夹中,但实际上没有根据该目录的内容支持恢复。如果在先前已中止filter-branch操作的存储库上运行git filter-branch,它要么会要求您删除该临时文件夹,要么使用--force选项自行删除

潜在问题是,git-filter-branch在大型存储库上运行缓慢——如果该过程更快,就没有尝试恢复的动机了。因此,您有几个选择:

使git-filter-branch更快一些...

  • 使用RAM-disk - git-filter-branch 非常依赖于IO,如果将存储库放在RAM中,则可以更快地运行。
  • 使用--index-filter 而不是 --tree-filter - 它类似于tree filter,但不会检出文件树,这使它更快,但需要您使用git索引命令来重写文件修改。
  • 使用cloud computing 并租用具有快速RAM和高时钟速度的计算机(除非您自己的命令是多线程的,否则不要费心多个核心,因为git-filter-branch本身是单线程的)

...或者使用BFG (速度更快)

BFG Repo-Cleaner 是一个比 git-filter-branch 更简单、更快速的替代方案 - 对于大型仓库,它可以提高50-150倍 的速度。这将把需要几个小时才能完成的工作转化为只需要几分钟。

完整披露:我是 BFG Repo-Cleaner 的作者。


非常高兴加快了事情的进展。顺便说一下,移动/删除目录是我正在考虑添加到BFG的功能 - 完成后我会添加评论。感谢您提供使用示例! - Roberto Tyley
@alnorth29 抱歉,进一步的问题 - 子目录移动的理由是什么?为什么有必要这样做? - Roberto Tyley
这是为了解决微软命令行构建工具的限制而进行的。Visual Studio可以编译嵌套在另一个网站中的ASP.NET网站,但命令行构建工具不能。我们正在设置一个持续集成服务器,并需要一个可行的命令行构建解决方案。感谢您的帮助,重写已完成,一切似乎都很好。 - alnorth29
1
不仅如此,我们还有8个分支需要合并。在每个分支上单独进行重新排列,然后尝试从一个分支合并到另一个分支将是一场噩梦。 - alnorth29
1
再次感谢BFG在这里。使用git-filter-branch(带有天真的--tree-filter)花费了将近3周的时间才完成我们过度庞大的repo的97%,然后Linux VM遭受文件系统损坏并失败了!使用BFG进行相同的操作只需不到20分钟,并且可以跨所有分支工作! - Dave Knight
显示剩余3条评论

7

Roberto在他的答案中提到了这一点,但我想给出一个基准:如果您的git filter-branch操作花费的时间太长,请考虑使用AWS高内存实例。

我曾经不得不filter-branch并合并35个不同的存储库,每个存储库都有两年的每天数十次提交历史记录。我的脚本在我的笔记本电脑上无法在25小时内完成。在Amazon的m2.4xlarge实例上完成45分钟。

总成本呢?

$1.64-少于我花在20盎司苏打水上的钱。

BFG听起来是一个很棒的工具,我鼓励那些经常重写历史的人尝试一下。但是,如果您只需要一些可以工作并且可以轻松访问AWS的东西,那么filter-branch就非常简单。

在2016年,这甚至更便宜。只需移步Spot Advisor,找到“以$0.30 /小时为价格的群集计算”之类的东西即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接