使用filter-branch命令删除额外目录

10

我正在将几个Subversion存储库迁移到Git,但它们的设置有点奇怪:标准的trunk/branches/tags结构位于存储库的几个子目录中。 / branches和/ tags都为空,因此git-svn导入最终只包含trunk目录。

svn/
  proj1/
    trunk/
      src/
  proj2/
    trunk/
      src/

我希望使用git filter-branch命令删除额外的主干文件夹,但保留其余部分完整:

svn/
  proj1/
    src/
  proj2/
    src/

根据文档中的最后一个示例,我已经做到了这一点:

git filter-branch --index-filter \
    'git ls-files -s | sed "s-/trunk/-/-" |
        GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
            git update-index --index-info &&
     mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD

我认为sed正在发挥作用,因为这是输入:

100644 fa3dcf79717e9aca85ad745078a2fb2a2ce2b900 0       proj1/trunk/src/file1.txt

生成以下输出:
100644 fa3dcf79717e9aca85ad745078a2fb2a2ce2b900 0       proj1/src/file1.txt

然而,当我运行整个命令时,出现以下错误:
Rewrite e00c119cfb755f741dc0e17c36d36bc2ddd27562 (1/42)mv: cannot stat `/c/dev/R
epo/.git-rewrite/t/../index.new': No such file or directory
index filter failed: git ls-files -s | sed "s-/trunk/-/-" |
            GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
                git update-index --index-info &&
         mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"

你有什么想法吗?我在Windows上使用git版本1.7.3.1.msysgit.0。

更新:现在使用的是git版本1.9.0.msysgit.0,类似的情况会产生不同的错误(注意在执行命令之前不存在.git-rewrite):

rm: cannot remove `c:/Path/to/svn/.git-rewrite/revs': Permission denied
rm: cannot remove directory `c:/Path/to/svn/.git-rewrite': Directory not empty

同样的修复方法最终起作用了。
2个回答

9
根据这里的评论,我理解了其中的问题。似乎是由于git-svn在表示“空”(仅限目录)提交时出现了问题。如果我从普通提交开始,它就能正常工作。
git filter-branch --index-filter \
    'git ls-files -s | sed "s-/trunk/-/-" |
        GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
            git update-index --index-info &&
     mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' 83df928c..HEAD

啊,有趣。知道这点很好。我猜git update-index如果从git ls-files得不到任何东西,实际上并不会创建索引文件;它似乎无法从空输入中生成空索引。 - Brian Campbell
1
对我没有任何作用。正在寻找更通用的解决方案。 - Ryan
1
如果有人遇到了和我类似的情况,但稍有不同,我的git存储库中最初的提交是空的(例如使用'git commit --allow-empty'提交)。从空提交后的提交到HEAD运行filter-branch可以解决该问题:例如FIRST_COMMIT..HEAD。没有引起任何问题的空提交不是最初的提交。 - vman
我有完全相同的问题,但是我对git很陌生,我想知道83df928c..HEAD是否是您为此问题提出的命令的一部分,还是它是与您的问题非常特定相关的东西? - user4964330
1
@BenjaminPeter 尝试执行 rm -rf .git-rewrite 命令,该命令会删除 filter-branch 存储东西的临时文件夹。 - dahlbyk
显示剩余3条评论

1

嗯,我看不出你运行的有什么问题,在一个示例存储库中它可以正常工作:

$ git init
在 /Users/bcampbel/tmp/git-subdir/.git/ 中初始化了一个空的 Git 仓库。
$ mkdir -p proj1/trunk
$ echo "hello" > proj1/trunk/test.txt
$ git add .
$ git commit -m "initial commit"
[master (root-commit) cd431f3] 初始提交
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 proj1/trunk/test.txt
$ echo "foo" > proj1/trunk/another.txt
$ git add .
$ git commit -m "add a file"
[master 84139f2] 添加文件
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 proj1/trunk/another.txt
$ git filter-branch --index-filter \
>     'git ls-files -s | sed "s-/trunk/-/-" |
>         GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
>             git update-index --index-info &&
>      mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
重写 84139f26c7921721190b3c5dd57e2b49a41034aa (2/2)
引用 'refs/heads/master' 已被重写
$ ls proj1/
another.txt test.txt

看起来由于某种原因,在您的系统上没有写出index.new文件,或者mv命令无法读取该文件。我不确定为什么会这样,但我想知道是否可能是因为您在Windows上使用msysgit。您是否有Linux或Mac可以尝试一下?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接