我们的 Git 存储库最初是单个怪物 SVN 存储库的一部分,其中各个项目都有自己的树,如下所示:
project1/branches /tags /trunk project2/branches /tags /trunk
显然,使用svn mv. 但是在 Git 中,每个项目都在自己的存储库中,今天我被要求将子目录project2从project1. 我做了这样的事情:
svn mv
project2
project1
$ git clone project2 $ cd project2 $ git filter-branch --subdirectory-filter deeply/buried/java/source/directory/A -- --all $ git remote rm origin # so I don't accidentally overwrite the repo ;-) $ mkdir -p deeply/buried/different/java/source/directory/B $ for f in *.java; do > git mv $f deeply/buried/different/java/source/directory/B > done $ git commit -m "moved files to new subdirectory" $ cd .. $ $ git clone project1 $ cd project1 $ git remote add p2 ../project2 $ git fetch p2 $ git branch p2 remotes/p2/master $ git merge p2 # --allow-unrelated-histories for git 2.9+ $ git remote rm p2 $ git push
但这似乎很令人费解。一般来说,有没有更好的方法来做这种事情?还是我采用了正确的方法?
请注意,这涉及将历史合并到现有存储库中,而不是简单地从另一个存储库的一部分创建新的独立存储库
是的,命中--subdirectory-filter是filter-branch关键。您使用它的事实基本上证明了没有更简单的方法 - 您别无选择,只能重写历史记录,因为您希望最终只得到文件的(重命名)子集,并且根据定义,这会更改哈希值。由于没有任何标准命令(例如pull)重写历史记录,因此您无法使用它们来完成此操作。
--subdirectory-filter
filter-branch
pull
当然,您可以改进细节 - 您的一些克隆和分支并不是绝对必要的 - 但整体方法很好!很遗憾它很复杂,但当然,git 的目的并不是让重写历史变得容易。