【问题标题】:git remove oldest revisions of a filegit 删除文件的最旧版本
【发布时间】:2011-02-16 23:39:15
【问题描述】:

我有一个 33 MB 的大文件,我想永久删除该文件的最旧版本,因此我只保留最新的 X 版本。怎么做?

我的裸存储库因此变得庞大。

我尝试了以下..但它完全删除了文件

git filter-branch --index-filter 'git rm --cached --ignore-unmatch big_manual.txt' HEAD

为了识别存储库中的大文件,我使用git-large-blob by Aristotle Pagaltzis

【问题讨论】:

  • 我认为如果您提供有关此文件以及您正在尝试做什么的更多信息会有所帮助。这将是一次性事件还是您打算定期清除文件并重写存储库历史记录?如果您不需要保留其历史记录,为什么要在 git 中跟踪文件?您的裸存储库有多大,如果它很大,真的有问题吗?
  • 这是我的程序手册,我使用 Apple Pages(文字处理器)编写,其中包含大量图像。我主要将它存储在 GIT 中,以便我可以在我的固定计算机和我的笔记本电脑之间共享它,所以我会在出现问题时撤消它。存储库当前为 450 MB。我对使用该文件犹豫不决,因为我知道存储库大小会增加。我认为最好摆脱最旧的修订版,而不是重新考虑我的备份解决方案。我每天拍摄存储库的完整快照并上传,但磁盘配额为 3 GB。
  • 是的,我希望可以不时这样做。
  • 假设您的存储库的其余部分是“正常”代码,那么我认为您应该重新考虑跟踪此文件以及我们的其余代码。它会导致您的存储库的大小增加,如果这会导致您拒绝更改它或迫使您一直重新定位最近的分支,那么它可能会迫使您进入一个非常痛苦的工作流程。
  • 它不仅仅是这个文件,我还跟踪了一些属于项目的网站的图像,这些会很好地擦除一些历史。我的项目有 1000 多个文件(h/cpp/mm、png、xml、rb、php),并且将所有内容放在一个地方会很好。我已经将它分成了 4 个存储库,但是它们都通过版本号相互引用。进一步拆分它并为我不感兴趣的未跟踪文件制定备份解决方案。

标签: git


【解决方案1】:

我认为您尝试使用 git filter-branch 命令时走在正确的轨道上。问题是您没有告诉它在任何提交中保留该文件,因此它已从所有提交中删除。现在,我认为没有办法直接告诉git-filter-branch 跳过任何提交。但是,由于命令是在 shell 上下文中运行的,因此使用 shell 删除除最后 X 个修订之外的所有修订应该不会太困难。像这样的:

KEEP=10 I=0 NUM_COMMITS=$(git rev-list master | wc -l) \
git filter-branch --index-filter \
'if [[ ${I} -lt $((NUM_COMMITS - KEEP)) ]]; then
     git rm --cached --ignore-unmatch big_manual.txt;
 fi;
 I=$((I + 1))'

这将使big_manual.txt 保留在最后 10 次提交中。

话虽如此,就像 Charles 提到的那样,我不确定这是不是最好的方法,因为您实际上是通过删除旧版本来撤消 VCS 的全部意义。

您是否已经尝试使用 git-gc 和/或 git-repack 优化 git 存储库?如果没有,这些可能值得一试。

【讨论】:

  • 这就是解决方案!它遍历了所有 312 个修订并丢弃了最旧的修订,完美。这很有教育意义。对于循环,rev-list.. 并在没有任何提交 id 的情况下调用 filter-branch,这似乎不直观(必须研究这种魔法是如何工作的),但它确实有效。谢谢你。有时我使用 git-gc 和 fsck,但我还没有自动化。我们先不谈我对 VCS 的看法 :-)
  • >>我们不要谈论我对 VCS 的看法 :-) 很公平 :) 我很高兴这对你有用。至于不指定修订的神奇之处,git-filter-branch 内部调用 git-rev-list 来获取要重写的提交列表。如果您未指定,它将把“HEAD”作为默认引用传递给 git-rev-list。因此,不指定任何内容与指定“HEAD”相同(就像您在示例中所做的那样)。
  • 感谢脚本。我把它做成了一个bash脚本文件,发现我需要稍微调整一下`#! /bin/bash KEEP=10 I=0 NUM_COMMITS=$(git rev-list master | wc -l) \ git filter-branch --index-filter \ 'if [ ${I} -lt $((NUM_COMMITS - KEEP ))];然后 git rm --cached --ignore-unmatch file-to-delete.tar;菲; I=$((I + 1))' `
【解决方案2】:

注意: 这个答案是关于缩短整个项目的历史,而不是从旧的历史中删除 单个文件 问题是关于什么的!


使用git filter-branch 缩短整个项目的历史 的最简单方法是使用grafts 机制(请参阅repository layout 文档)来缩短历史:

$ echo "$commit_id" >> .git/info/grafts

其中$commit_id 是您希望成为新存储库的根(第一次提交)的提交。使用“git log”或图形历史查看器(例如 gitk)检查历史看起来像您想要的那样,然后运行“git filter-branch --all”; git-filter-branch 文档中描述了移植物的使用。

或者您可以通过使用git clone--depth <depth> 选项来使用浅克隆



您可以使用 grafts 删除单个文件的部分历史记录(最初请求的内容),具体步骤如下所述。此解决方案比solution proposed by Dan Moulding 包含更多步骤,但每个步骤都更简单,您可以使用“git log”或图形历史查看器检查中间步骤。

  1. 首先,选择要删除文件的点,并通过在这些点创建分支来标记这些提交。例如,如果您希望文件在提交f020285b 中首次出现并在其所有祖先中删除,请使用

    标记它的祖先(假设这是普通的非合并提交)
    $ git branch cleanup f020285b^
    
  2. 其次,使用 git-filter-branch 从历史记录中删除以cleanup 开头的文件(即f020285b^),如git-filter-branch 手册页的“示例”部分所示:

    $ git filter-branch --index-filter 'git rm --cached --ignore-unmatch big_manual.txt' cleanup
    

    如果您还想删除所有仅更改为已删除文件的提交,您可以另外使用 git-filter-branch 的 --prune-empty 选项。

  3. 接下来,使用移植机制将重写的部分历史与其余历史连接起来:

    $ echo $(git-rev-parse f020285b) $(git rev-parse cleanup) >> .git/info/grafts
    

    然后您可以检查历史以检查它是否正确连接。

  4. 最后,使用 git-filter-branch 使移植物永久化(这将使所有移植物永久化,但在这里假设您不使用移植物),

    $ git filter-branch cleanup..HEAD
    

    并移除移植物(因为不再需要它们)和cleanup 分支

    $ rm .git/info/grafts
    $ git branch -d cleanup
    

最后说明:如果您删除了某个文件的部分历史记录,您最好确保没有该文件的项目是有意义的(例如正确编译)。

【讨论】:

  • 是的,移植机制似乎确实是这样做的预期方式。谢谢你让我意识到这一点。不幸的是,我今天没有时间试验它。
  • 嫁接方法在某些情况下会起作用,但它会删除所有文件的历史记录。在这种情况下,neoneye 只想删除 一些 文件的历史记录。所以我不确定移植是否是一个合适的解决方案。浅层克隆是不可能的,因为浅层存储库已经瘫痪(有关其局限性的描述,请参阅 git-clone 文档)。
  • 丹,是的,好点,一个只删除单个文件历史的解决方案。好的,所以我不会对移植物进行任何实验。
【解决方案3】:

您可能需要考虑使用git submodules。这样,您可以将图像和其他大文件保存在另一个 git 存储库中,并且具有源代码的存储库可以引用该其他存储库的特定修订。

这将帮助您使存储库修订保持同步,因为父存储库包含指向特定子存储库修订的链接。它还允许您在子存储库中删除/重新调整旧修订,而不影响您的源代码所在的父存储库 - 删除子存储库中的旧修订不会弄乱父存储库的历史记录,因为您只是更新父存储库中的子存储库链接指向的修订版。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-12
    • 2018-01-24
    • 2011-09-15
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多