【问题标题】:How to extract a subset of history from Git?如何从 Git 中提取历史的子集?
【发布时间】:2010-09-08 17:20:59
【问题描述】:

更新:我试图简化此处的真实示例,以便清楚地解释我的选项,但这并没有真正奏效。到目前为止,下面的链接示例过于笼统,甚至无法使这个简单的示例正常工作。

我一直都能用 SVN 做这类事情,并且非常熟练。现在我发现它在 Git 中非常困难,并且开始相信我的历史基本上是混在一起的,无法将其分开。

现实世界的问题:我已经移动和重命名了大约十几个文件。他们的历史与我想要完全删除历史的数百个其他文件的历史混合在一起。

在 SVN 中,我可以使用一系列转储/包含过滤器/排除过滤器/加载来精简存储库,并且很少需要在加载之前在转储文件本身中手动重命名路径。

像这样的事情,我早就完成了:

SET Includes=trunk/src/Foo.aaa trunk/src/Foo.bbb trunk/src/Foo trunk/src/Bar
SET Excludes=trunk/src/Bar/Blah.aaa trunk/src/Foo/Blah.aaa

svnadmin dump FooSrc > Full.dump 2> Dump.log
svndumpfilter include %Includes% --skip-missing-merge-sources --renumber-revs --drop-empty-revs < Full.dump > Filter_1.dump 2> Filter_1.log
svndumpfilter exclude %Excludes% --skip-missing-merge-sources --renumber-revs --drop-empty-revs < Filter_1.dump > Filter_2.dump 2> Filter_2.log
svnadmin create FooDest
svnadmin load FooDest --ignore-uuid < Filter_2.dump > Load.log 2> Load_Errors.log

有没有人有一个很好的例子,不仅仅是简单地删除单个文件或导出单个子目录?

定义文件集的最简单方法是使用包含 7 个目录路径的列表。这些目录中的所有内容都需要保留,外部的所有内容都需要从历史记录中删除。


简化问题:

我有一个 Git 存储库,其中包含一些我想提取到它自己的存储库中的文件。问题是这些文件是在整个原始存储库的历史中创建和修改的,所以我无法弄清楚如何干净地提取它们。

这里是我的历史的概要(只有更多的提交和更多需要忽略的内容)。如您所见,我显然不打算稍后将这些文件从历史中挑选出来:

commit 4a09d3f977a8595d9e3f61766a5fd743e4265a56

M    src/Foo/Bar/FileToExtract2.foo
A    src/Foo/Bar/FileToExtract3.bar
D    src/Foo/AnotherFileToIgnore.txt

commit 05d26f23518083270cc45bf037ced29bec45e064

M    src/Foo/Blah/IgnoreThisOneToo.foo
M    src/Foo/AnotherFileToIgnore.txt

commit 343187228f4bd8e4427395453034c34ebd9a95f3

M    src/Foo/Bar/FileToExtract1.txt
M    src/Foo/AnotherFileToIgnore.txt

commit 46a0129104ac31291462f657292aab43f8883d8d

A    src/Foo/Bar/FileToExtract1.txt
A    src/Foo/Bar/FileToExtract2.foo
M    src/Foo/FileToIgnore.txt

commit 3fe6af56f0d8dc42fcb5b0bafee41bff534ba2cc

A    src/ReadMe.txt
A    src/IgnoreMe.foo
A    src/Foo/FileToIgnore.txt
A    src/Foo/Blah/IgnoreThisOneToo.foo
A    src/Foo/AnotherFileToIgnore.txt

最后,我想要的是一个干净的存储库,其中包含src/Foo/Bar/ 中文件的完整历史记录。其余的可以忽略。我也可以将这个存储库保持原样(即不重写历史记录)并为整个目录提交删除。

在 SVN 中,我会使用 svnadmin dumpsvndumpfiltersvnadmin load。如果我小心的话,我什至可以手动编辑转储文件以清理路径等。

我一直在查看 Git 命令,但找不到执行此操作的方法。任何帮助将不胜感激。

【问题讨论】:

    标签: git version-control history


    【解决方案1】:

    您可以使用git filter-branch 并将目录 Foo 分离到它自己的目录中。
    见:

    【讨论】:

    • 优秀。我想这正是我想要的。我今晚试试。谢谢!
    • 看起来这是我需要的,但是如果我想在新的修剪后的存储库中包含多个子目录怎么办?看来git filter-branch --subdirectory-filter &lt;directory&gt; 只取一个值?
    • @McKAMEY: stackoverflow.com/questions/1425892/… 是一个好的开始:子模块或子树合并。
    • 啊,我想我看到了,所以为每个子目录生成一个存储库,然后将它们重新合并成一个?历史是交错的,还是一个接一个的叠加?
    • @McKAMEY:它们是独立的(两个根,即无父提交)。
    【解决方案2】:

    相当于 SVN 的 svnadmin dumpsvndumpfiltersvnadmin load 将是 git fast-export、一个自己的脚本(参见 examples)和 git fast-import >.

    【讨论】:

    • @VonC:感谢您提供链接。
    • 我有 7 个目录,其中包含我需要提取的所有文件列表。我在导出和导入之间指定什么来过滤除这 7 个目录之外的所有内容?我需要相当于svndumpfilter include
    • “查看示例”链接仅提供了一个用于过滤器脚本的sed "s|refs/heads/master|refs/heads/other|" 示例。我将如何告诉 Git 删除作为我的 7 个子目录之一不存在的所有文件?
    猜你喜欢
    • 2014-11-01
    • 2015-09-02
    • 2014-06-27
    • 1970-01-01
    • 1970-01-01
    • 2013-01-23
    • 2013-08-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多