我知道可以使用以下命令提取指定分支的给定文件夹在 git
中的历史记录:
git filter-branch --subdirectory-filter "a sub directory" -- myBranch
不幸的是,这个子目录在历史上被重命名了,从a subdirectory
到aSubdirectory
。不幸的是,filter-branch
在重命名处停止。
有没有办法解决这个问题?
我知道可以使用以下命令提取指定分支的给定文件夹在 git
中的历史记录:
git filter-branch --subdirectory-filter "a sub directory" -- myBranch
不幸的是,这个子目录在历史上被重命名了,从a subdirectory
到aSubdirectory
。不幸的是,filter-branch
在重命名处停止。
有没有办法解决这个问题?
git filter-branch --prune-empty --index-filter '
git ls-files -z |
egrep --invert-match --null-data "^(a subdirectory|aSubdirectory)/" |
xargs -0 --no-run-if-empty git rm --cached -q
git ls-files -s | sed -re "s-\t(a subdirectory|aSubdirectory)/-\t-" |
git update-index --index-info
git ls-files -z |
egrep --null-data "^(a subdirectory|aSubdirectory)/" |
xargs -0 git rm --cached -q
' -- myBranch
$ git lola --name-status的翻译:
* da6c7ae (HEAD, myBranch) file2 | A file2 * d94110a file1 A file1 * 27c7275 (refs/original/refs/heads/myBranch) file2 | A aSubdirectory/file2 * 39d7e75 mv | D a subdirectory/file1 | A aSubdirectory/file1 * c710654 file1 A a subdirectory/file1列出了Git日志并显示工作目录中当前分支中的更改情况,以及这些更改的文件名和状态。
* da6c7ae (HEAD, myBranch) file2
表示提交ID、分支名称和修改的文件名。而| A file2
表示该文件是添加的。refs/original/refs/heads/myBranch
是一个备份,用于验证结果后可以通过git update-ref -d refs/original/refs/heads/myBranch
来丢弃。最终的输出只包括提交ID和文件名的列表。
--prune-empty
,重命名目录的提交已经消失了。git lol
和 git lola
是非标准的但是非常有用的别名。我发现这个很有用,但是因为xargs和egrep缺少一些功能,所以在我的OSX上,@Greg Bacon的解决方案出现了一些问题。最终我写了一个Perl脚本,并确保它在$PATH中。
git filter-branch --prune-empty --tag-name-filter cat --index-filter 'git_prune_non_proxy_dirs.pl' -- --all
这个 Perl 脚本的样子是这样的(我猜你可以修改它来执行所有三个步骤,但这只执行了“第一部分”,请确保在这种情况下使用 system 而不是 exec 来调用 Git)
#!/usr/bin/perl
open(LS,"git ls-files|") || die "Failed to git ls-files: $!\n";
my %to_remove=();
while ( <LS> ) {
chomp;
if( $_ =~ m#(^adserver-proxy(|-api)/)#) {
}else{
my @components = split('/',$_, 2);
my $path_to_delete = $components[0];
$to_remove{$path_to_delete}=1;
}
}
if (%to_remove) {
my @cmd=(
"git","rm","-rfq","--cached","--", keys %to_remove);
exec(@cmd) || die "Failed to invoke git rm"
}