12

我将一个大的源代码树分成两个独立的组件和一个共享的子模块。为了准备这次拆分,我首先将共享的内容移动到一个“公共”目录中,更新了所有引用,并进行了提交。到目前为止,一切都很好。现在我想将该目录提取到一个子模块中。

通常我会这样做

git filter-branch --subdirectory-filter

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

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

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

4

2 回答 2

4

并不真地。--subdirectory-filter是一种特殊情况,因为它实际上会显着修改树的内容(因为它会将事物向上移动一个或多个目录嵌套级别)。

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

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

于 2011-03-09T08:24:01.610 回答
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

到目前为止,这似乎工作正常,除了不删除点文件(例如.git,好和.gitignore坏),但显然我的 Git 版本(1.6.0.4)没有git filter-branch --prune-empty. 所以现在我克隆新的、更小的 repo(以便更快地通过网络复制它)并将 repo 复制到另一台装有 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

希望这可以帮助!

于 2011-12-29T00:04:00.417 回答