关于git:筛选分支以删除额外目录

filter-branch to remove extra directory

我正在将几个Subversion存储库迁移到Git,但它们设置得有点奇怪:标准的主干/分支/标记结构位于存储库的几个子目录中。/分支和/标记都是空的,因此git svn导入最终只使用主干目录。

1
2
3
4
5
6
7
svn/
  proj1/
    trunk/
      src/
  proj2/
    trunk/
      src/

我想使用git filter-branch删除额外的主干文件夹,但保留其余部分:

1
2
3
4
5
svn/
  proj1/
    src/
  proj2/
    src/

基于文档中的最后一个示例,这是迄今为止我所拥有的:

1
2
3
4
5
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正在做它的工作,作为这一输入:

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

生成此输出:

1
100644 fa3dcf79717e9aca85ad745078a2fb2a2ce2b900 0       proj1/src/file1.txt

但是,当我运行整个命令时,会得到以下错误:

1
2
3
4
5
6
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不存在):

1
2
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

同样的解决方法最终也起了作用。


根据这里的一条评论来解决这个问题。GitSvn如何表示"空"(仅目录)提交似乎是个问题。如果我从一个正常的提交开始,它会很好地工作:

1
2
3
4
5
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


嗯,我看不出你运行的有什么问题,在示例存储库中它对我来说很好:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ git init
Initialized empty Git repository in /Users/bcampbel/tmp/git-subdir/.git/
$ mkdir -p proj1/trunk
$ echo"hello"> proj1/trunk/test.txt
$ git add .
$ git commit -m"initial commit"
[master (root-commit) cd431f3] initial commit
 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] add a file
 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
Rewrite 84139f26c7921721190b3c5dd57e2b49a41034aa (2/2)
Ref 'refs/heads/master' was rewritten
$ ls proj1/
another.txt test.txt

似乎由于某种原因,index.new文件没有在您的系统中写入,或者无法由mv命令读取。我不知道为什么会这样,但我想知道这可能是因为您在Windows上使用msysgit。你有一个Linux设备或Mac电脑可以在上面试用吗?