代码之家  ›  专栏  ›  技术社区  ›  Gareth

正在折叠Git存储库的历史记录

  •  79
  • Gareth  · 技术社区  · 16 年前

    我们有一个历史悠久的Git项目。

    具体来说,在项目早期,项目中有很多二进制资源文件,这些文件现在已经被删除,因为它们实际上是外部资源。

    但是,由于以前提交了这些文件,我们的存储库的大小为>200MB(当前的总签出量为~20MB)。

    我们要做的是“折叠”历史记录,以便存储库看起来是从比原来更高的修订版创建的。例如

    1-----2-----3-----4-----+---+---+
                       \       /
                        +-----+---+---+
    
    1. 已创建存储库
    2. 添加了大量二进制文件集
    3. 删除了大量二进制文件集
    4. 存储库的新预期“开始”

    所以实际上,我们希望在某一点之前丢失项目历史。此时只有一个分支,因此尝试处理多个起始点等并不复杂。但是,我们不希望丢失所有历史记录并使用当前版本启动新的存储库。

    这是可能的,还是我们注定要永远拥有一个膨胀的仓库?

    4 回复  |  直到 8 年前
        1
  •  88
  •   Paul    16 年前

    您可以删除二进制膨胀并保留其余的历史记录。Git允许您重新排序并“挤压”之前的提交,因此您可以组合添加和删除大型二进制文件的提交。如果添加操作都是在一次提交中完成的,而删除操作都是在另一次提交中完成的,那么这将比处理每个文件容易得多。

    $ git log --stat       # list all commits and commit messages 
    

    搜索添加和删除二进制文件的提交并注意它们的sha1,比如 2bcdef 3cdef3 .

    然后,要编辑回购历史记录,请使用 rebase -i 命令及其交互选项,从添加二进制文件的提交的父级开始。它将启动$editor,您将看到从 2BCDEF :

    $ git rebase -i 2bcdef^    # generate a pick list of all commits starting with 2bcdef
    # Rebasing zzzzzz onto yyyyyyy 
    # 
    # Commands: 
    #  pick = use commit 
    #  edit = use commit, but stop for amending 
    #  squash = use commit, but meld into previous commit 
    # 
    # If you remove a line here THAT COMMIT WILL BE LOST.
    #
    pick 2bcdef   Add binary files and other edits
    pick xxxxxx   Another change
      .
      .
    pick 3cdef3   Remove binary files; link to them as external resources
      .
      .
    

    插入 squash 3cdef3 作为第二行,并删除其中的行 pick 3cdef3 从列表中。现在,您有一个交互式操作列表 rebase 它将把添加和删除二进制文件的提交合并到一个提交中,这个提交的diff就是这些提交中的任何其他更改。然后,当您要求它完成以下操作时,它将按顺序重新应用所有后续提交:

    $ git rebase --continue
    

    这需要一两分钟。
    现在您有了一个不再有二进制文件来或去的回购。但它们仍然会占用空间,因为在默认情况下,Git会在垃圾收集之前将更改保留30天,这样您就可以改变主意了。 如果现在要删除它们:

    $ git reflog expire --expire=1.minute refs/heads/master
          #all deletions up to 1 minute  ago available to be garbage-collected
    $ git fsck --unreachable      # lists all the blobs(files) that will be garbage-collected
    $ git prune
    $ git gc                      
    

    现在你已经移除了膨胀,但保留了你的其他历史。

        2
  •  26
  •   Alfe    8 年前

    你可以使用 git filter-branch 用嫁接使commit 4成为分支的新根commit。只需创建文件 .git/info/grafts 其中只有一行包含提交号4的sha1。

    如果你现在做了 git log gitk 您将看到这些命令将显示commit 4作为分支的根。但实际上在您的存储库中不会发生任何更改。你可以删除 .git/info/移植物 以及 GIT日志 吉特克 会像以前一样。要使commit 4成为新的根目录,必须运行 Git过滤器分支 ,没有参数。

        3
  •  21
  •   JesperE    16 年前

    多亏了杰斯佩尔的职位 git-filter-branch --这可能正是你想要的。看起来您也可以保留以前的提交,除非它们在删除大文件后会被修改。从 git-filter-branch man page :

    假设您要从所有提交中删除一个文件(包含机密信息或侵犯版权):

    git filter branch—树过滤器“rm filename”头

    一定要阅读那个手册…显然,您希望在存储库的备用克隆上执行此操作,以确保它按预期工作。

        4
  •  6
  •   JesperE    16 年前

    git-fast-export 你在找什么?

    NAME
       git-fast-export - Git data exporter
    
    SYNOPSIS
       git-fast-export [options] | git-fast-import
    
    DESCRIPTION
       This program dumps the given revisions in a form suitable to be piped into git-fast-
       import(1).
    
       You can use it as a human readable bundle replacement (see git-bundle(1)), or as a kind
       of an interactive git-filter-branch(1).