在保留历史记录WITH重命名的同时提取git子目录

时间:2011-03-09 08:13:01

标签: git git-filter-branch

我将一个大的源代码树分成两个独立的组件和一个共享的子模块。为了准备这个分裂,我首先将共享的东西移动到一个“公共”目录中,更新了所有引用,并进行了提交。到现在为止还挺好。现在我想将该目录解压缩到子模块中。

通常情况下,我会用

执行此操作
git filter-branch --subdirectory-filter

但在这种情况下,所有有趣的历史都发生在该子目录之外,因此历史丢失了。

我知道保留完整的历史记录是没有意义的,因为这根本不会过滤掉任何数据。但我真的不想回到过去和构建的能力,我只是希望能够查看每个文件所属的提交。

有没有办法在保留单个文件的历史记录的同时保持过滤器分支的行为?

2 个答案:

答案 0 :(得分:4)

不是真的。 --subdirectory-filter有点特殊,因为它实际上是在显着地修改树的内容(因为它正在向上移动一个或多个目录嵌套级别)。

因此,在文件之外的文件之间并没有很好的映射 你要过滤的子目录和可以作为结果中提交的一部分存储的树。

请记住,filter-branch完全重写了您的历史记录 - 输出是一组全新的提交,并且没有任何与旧提交的“链接”,因此任何额外的信息都必须表达为部分新的提交。

答案 1 :(得分:3)

以下是 解决类似问题的方法。我在一个准私有“misc”存储库中启动了一个项目,重命名了一些文件,然后我想在https://github.com/kragen/aikidraw将项目上传到GitHub。

$ git clone misc aikidraw
$ cat > aikidraw-wanted
aikidraw.js
aikidraw.html
caposketchra.html
caposketchra.js
jquery-1.2.6.js
^D
$ cd aikidraw
$ git filter-branch --tree-filter 'bash -c "comm -23 <(/bin/ls | sort) <(sort ~/devel/aikidraw-wanted) | xargs rm -rf"' HEAD

到目前为止,除了不删除dotfiles(例如.git,好,.gitignore,坏)之外似乎没有用,但显然我的Git版本(1.6.0.4)没有有git filter-branch --prune-empty。所以现在我克隆新的,较小的仓库(为了让它更快地通过网络复制它)并将仓库复制到另一台上有Git 1.7.2.5的机器上:

$ time git clone aikidraw aikidraw-smaller
$ du -sh aikidraw/.git aikidraw-smaller/.git
8.6M    aikidraw/.git
1.2M    aikidraw-smaller/.git

$ time rsync -Pav aikidraw-smaller panacea.canonical.org:devel/aikidraw/
real    1m23.251s

然后在panacea.canonical.org上:

$ cd ~/devel/aikidraw/aikidraw-smaller  # Oops. I hate rsync sometimes.
$ git checkout  # otherwise I get "Cannot rewrite branch(es) with a dirty working directory."
$ git filter-branch --prune-empty HEAD
$ cd ../..
$ mv aikidraw i-hate-rsync
$ mv i-hate-rsync/aikidraw-smaller/ aikidraw

然后回到我的上网本上:

$ mv aikidraw aikidraw-big
$ git clone panacea.canonical.org:devel/aikidraw
$ du -sh aikidraw/.git
268K    aikidraw/.git

现在,如果您使用两个目录而不是五个文件执行此操作,那么此时您可能希望使用git mv将剩余子目录中的所有内容重命名为存储库的根目录。在我的情况下,我已经完成了我的重命名。

$ git remote add github git@github.com:kragen/aikidraw.git
$ git push github master

希望这有帮助!