【问题标题】:git filter-branch led to a disconnected history: how to get rid of the old commits?git filter-branch 导致历史断开:如何摆脱旧的提交?
【发布时间】:2013-07-26 16:16:09
【问题描述】:

场景如下:

我有一个大型 CVS 存储库,我想将其转换为 14 个不同的 git 存储库。 该过程的cvs2git 部分很好,并导致一个大型存储库 repo.git。

对于 14 个 git 存储库中的每一个,我都克隆了主存储库并运行以下命令:

git filter-branch -d /tmp/rep --tag-name-filter cat --prune-empty --subdirectory-filter "sub/directory" -- --all

但是,在执行此命令之前,我必须为某些 git 存储库执行另一个 git filter-branch 命令,因为我必须重写提交才能将文件从一个目录移动到另一个目录。 --tree-filter 是我使用的选项。以下是执行的命令行示例:

script_tree_filter="if test -f rep/to/my/file && test -d another/rep ; then echo Moving my file ; mv rep/to/my/file another/rep; fi"
git filter-branch -d /tmp/rep --tag-name-filter cat --prune-empty --tree-filter '$script_tree_filter' -- --all

在过程结束时(14500 次提交:大约需要 1 小时!)我清理了 refs 并使用git gc

git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
git reflog expire --expire=now --all
git gc --prune=now

最后我得到了一个大小为 1.2Go 的存储库(这显然还是太大了),通过查看提交,我可以看到很多旧的仍然存在。它们涉及在--subdirectory-filter 命令之后不应再出现的文件和目录。

在提交的历史中,不想要的提交和好的提交之间存在不连续性,如 gitk --all 所示:

我很确定这些提交仍然存在,因为它们上有一些标签。如果是这种情况,是否可以在不删除良好提交的情况下删除这些标签?

如果标签不是原因,有什么想法吗?

更多信息,refs目录(在subdirectory-filter获取的git仓库中)的内容为空:

$ ls -R refs/
refs/:
heads  original  tags

refs/heads:

refs/original:
refs

refs/original/refs:
heads  tags

refs/original/refs/heads:

refs/original/refs/tags:

refs/tags:

我发现分支和标签都列在了git仓库的packed-refs文件中:

d0c675d8f198ce08bb68f368b6ca83b5fea70a2b refs/tags/v03-rev-04
95c3f91a4e92e9bd11573ff4bb8ed4b61448d8f7 refs/tags/v03-rev-05

文件中列出了817个标签和219个分支。

【问题讨论】:

  • git gc 会将标签引用打包到 .git/packed-refs 中,因此是空目录。我不确定为什么标签会指向旧的提交,因为每个过滤器分支操作都使用--tag-name-filter....
  • 你按照本帖的4条命令清理了吗? stackoverflow.com/a/7966852/11343
  • 除了reset hard,我执行了我的问题中提到的其他 3 个命令(rm -rf .git/refs/original/ 的编写方式不同,因为我有一个裸存储库)。我没有使用gc的--agressive选项,但我不能尝试(我认为它不会改变任何东西)。
  • 所以您问题中的ls 登录不是最新的,是吗?里面有refs/original 的东西。另外请在您的 cmets 中使用@user,否则我们不会收到通知
  • @CharlesB ls 日志是最新的:refs/original 中的所有目录都是空的(使用命令update-ref -d)。

标签: git tree git-filter-branch disconnected


【解决方案1】:

我设法通过改变我使用cvs2git 的方式解决了我的问题:我没有转换整个CVS 基础然后使用subdirectory-filter 命令,而是转换了我想要的每个子模块。就我而言,这导致启动了 18 个不同的cvs2git 命令:

之前

cvs2git --blobfile=blob --dump=dump /path/to/cvs/base
# Module 1
git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter "path/to/module1" -- --all
# Module 2
git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter "path/to/module2" -- --all

现在

# Module 1
cvs2git --blobfile=blob_module1 --dump=dump_module1 /path/to/cvs/base/path/to/module1
# Module 2
cvs2git --blobfile=blob_module2 --dump=dump_module2 /path/to/cvs/base/path/to/module2

现在每个存储库都有完美的历史记录。

为什么以前的方法不起作用?我的猜测是 cvs2git 与所有子模块混淆(其中一些在其历史期间更改了目录名称)。

@Michael @CharlesB 感谢您抽出宝贵时间回答并帮助我。

【讨论】:

  • 很高兴你解决了这个问题,我很好奇你为什么要从 cvs 本身做一个大的 repo - 太棒了你分享了解决方案 - 干杯。 +1 以及
【解决方案2】:

我打赌你会被这个打击:

  • CVS 和 git 分支/标签模型之间的区别:CVS 允许从多个源分支的源修订的任意组合创建分支或标签。它甚至允许将从未同时发生的文件修订添加到单个分支/标签中。另一方面,Git 只允许完整的源代码树,因为它在历史的某个时刻存在,被分支或标记为一个单元。此外,一个 git 版本的祖先会影响该版本的内容。这种差异意味着从根本上不可能 100% 忠实地表示 git 存储库中的任意 CVS 历史记录。 cvs2git 使用以下解决方法:

    • cvs2git 尝试从单个源创建一个分支,但如果它不知道如何创建,它会使用来自多个源分支的“合并”来创建分支。在病态情况下,分支的合并源数量可以任意大。由此产生的历史表明,每当将任何文件添加到分支时,整个源分支都会合并到目标分支中,这显然是不正确的。 (另一种选择是省略合并,将丢弃某些内容从一个分支移动到另一个分支的信息。)

    • 如果 cvs2git 无法确定可以从单个修订版创建 CVS 标记,则它会创建一个名为 TAG.FIXUP 的标记修复分支,然后标记该分支。 (这是一个必要的解决方法,因为 git 只允许标记现有的修订。) TAG.FIXUP 分支是作为包含在标记中包含的文件修订的所有分支之间的合并创建的,这涉及到所描述的相同权衡上面的分支。 TAG.FIXUP 分支在转换结束时被清除,但(由于 git 快速导入文件格式的技术限制)没有被删除。在某些情况下,可以从单个修订创建标签,但 cvs2git 没有意识到它并创建了一个多余的标签修复分支。通过在生成的 git 存储库中运行 contrib/git-move-refs.py 脚本,可以在转换后删除多余的标签修复分支。

  • 没有检查 CVS 分支和标签名称是合法的 git 名称。可能还有其他 git 约束也应该检查。 see cvs2git

您是在显示新目录的 refs 目录还是转换后的大型 repo 目录?您可以在过滤和拆分大型存储库之前删除单个大型导出存储库中的标签。

您可以通过删除目录中的文件来删除大型 repo 中的标签 - 它只是对 SHA 的引用。

【讨论】:

  • refs 目录是新目录之一(在子目录过滤器之后)。删除所有标签不是一种选择:我想保留那些与我保留的目录有关的标签。
  • 我不是说删除所有标签,只是删除不重要的标签 = 你是说一些不必要的标签导致了问题。
  • 诀窍是我不知道如何区分“好”标签和“坏”标签。我目前正在调查删除带有标签的空提交。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-07
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 2014-11-01
  • 1970-01-01
相关资源
最近更新 更多