这个问题听起来与这里提出的许多问题相似,但却是惊人的不同。
我有一个git存储库,它曾经是一个svn存储库(曾经是一个cvs存储库)。这些数据可以追溯到1999年左右。
现在是将这个存储库分成几个不同的存储库的时候了,保存了所有这些丰富的历史。但是,存储库的结构经常发生变化。目前所有的项目都来自一个基础项目,这个基础项目发展为几个项目,缩小到两个项目,然后再增长。代码已经被移来移去,但从来没有被复制过;现在,它已经在几个成熟的项目中找到了一个最后的休息点。
如果我想保存历史的话,这使得拆分存储库变得非常困难。使用git-filter分支似乎是正确的方法,但所有这些似乎都破坏了存储库的一部分,并用它们截断历史。
编辑添加了来澄清,这里有一个小例子,假装我在存储库的根中。假设存储库如下所示:
foo/
bar/
file.txt
baz/现在,假设我编辑file.txt的内容。然后我将它重命名为newfile.txt。然后我再次编辑内容。然后,我将该文件移出bar/并进入baz/。我的存储库现在如下所示:
foo/
bar/
baz/
newfile.txt好的,现在假设我想将baz/拆分到它自己的存储库中。使用git过滤器分支或使用git子树拆分将丢失newfile.txt的所有提交消息和历史记录,当它位于bar/内部和命名为file.txt时。
我理解,签出一个历史修订版可能是疯狂的;它可能引用一些名为../bar/的内容,或者它可能引用了一个无效目录,该目录并不存在,而且异常失败。只要我能在任何特定的版本中查看文件内容,我就不在乎。
端编辑
我想要做的事情似乎有两条路:
中没有出现的文件或从文件中降下来的文件。
是否有可能找到所有没有出现在头部的文件,并删除与它们相关的任何历史记录?我不关心已经被删除的文件的复活,这似乎是我问题的症结所在。
另一种解决办法也将受到赞赏。我对git还比较陌生,所以我可能遗漏了一些显而易见的东西。
发布于 2012-04-23 21:47:36
最后,我不得不在几个阶段中完成这个任务。
首先,我得到了存储库中找到的所有文件路径的列表:
git log --pretty=format: --name-only --diff-filter=A | sort -u使用它,我能够确定我想要保存的文件在某个点或另一个点的位置。在我的例子中,他们在整个生命周期都居住在存储库中的四个单独的目录中。我使用这些信息手动创建正则表达式,如(?:^foo|^bar/baz|^qux/(?:moo|woof))。这与我想保存的目录相匹配。
然后,我创建了一个perl脚本来保存这些路径名和包含它们的任何父路径名。
use Path::Class;
if(scalar(@ARGV) < 1) { die "no regex"; }
my $regex = qr/$ARGV[0]/;
my @want; my @remove; my $last = undef; my $lastrm = undef;
while(<STDIN>) {
chomp;
my $d = $_;
if( $d =~ $regex ) {
if( ! defined($last) || ! dir($last)->subsumes(dir($d)) ) {
$last = $d;
push @want, $d;
}
} else {
if( ! defined($last) || ! dir($last)->subsumes(dir($d)) ) {
push @remove, $d;
}
}
}
foreach $rm (@remove) {
my $no_rm = 0;
if( defined($lastrm) && dir($lastrm)->subsumes($rm) ) {
$no_rm++;
} else {
foreach $keep (@want) {
if( dir($rm)->subsumes(dir($keep)) ) {
$no_rm++;
}
}
}
if( $no_rm == 0 ) {
print "$rm\n";
$lastrm = $rm;
}
}最后,我使用git过滤器分支来使用我的新过滤器和正则表达式来保留我想要的路径。
git filter-branch --prune-empty --index filter '
git ls-tree -d -r -t --name-only --full-tree $GIT_COMMIT
| sort | /path/to/filter.pl "(?:regex|of|paths)"
| xargs -n 50 git rm -rf --cached --ignore-unmatch' -- --all排序是必要的,因为它确保perl脚本获得正确层次结构中的目录。
我希望这能帮助到一些人,因为我花了很多很多小时才想出这个主意。:)
发布于 2012-04-21 13:25:15
您应该考虑安装和使用git子树https://github.com/apenwarr/git-subtree,它处理拆分的repos并很好地保存历史记录。
https://stackoverflow.com/questions/10258054
复制相似问题