我们的Git存储库最初是一个大型SVN存储库的一部分,其中每个项目都有自己的树,如下所示:
project1/branches
/tags
/trunk
project2/branches
/tags
/trunk
显然,使用svn mv将文件从一个文件移动到另一个文件非常容易。但是在Git中,每个项目都在它自己的存储库中,今天我被要求将一个子目录从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
但这似乎相当复杂。有没有更好的方法来做这类事情呢?还是我采取了正确的方法?
注意,这涉及到将历史合并到现有的存储库中,而不是简单地从另一个存储库的一部分创建一个新的独立存储库(如前面的问题中所述)。
在我的例子中,我不需要保存我正在迁移的回购,也不需要保存任何以前的历史记录。我用不同的遥控器,截取了同一根树枝的补丁
#Source directory
git remote rm origin
#Target directory
git remote add branch-name-from-old-repo ../source_directory
在这两个步骤中,我能够让另一个回购的分支出现在同一个回购中。
最后,我设置这个分支(我从另一个回购导入)遵循目标回购的主线(所以我可以准确地区分它们)
git br --set-upstream-to=origin/mainline
现在它的行为就好像它只是我在同一次回购中推的另一个分支。
如果你的历史记录是正常的,你可以将提交作为补丁取出,并将它们应用到新的存储库中:
cd repository
git log --pretty=email --patch-with-stat --reverse --full-index --binary -m --first-parent -- path/to/file_or_folder > patch
cd ../another_repository
git am --committer-date-is-author-date < ../repository/patch
或者在一行里
git log --pretty=email --patch-with-stat --reverse --full-index --binary -m --first-parent -- path/to/file_or_folder | (cd /path/to/new_repository && git am --committer-date-is-author-date)
提示:如果源项目子目录中的提交应该被提取到一个新的存储库根目录,git am可以被赋予-p2这样的参数来从补丁中删除额外的目录。
(摘自Exherbo的文件)
试试这个
cd repo1
这将删除除上述目录之外的所有目录,仅为这些目录保留历史记录
git filter-branch --index-filter 'git rm --ignore-unmatch --cached -qr -- . && git reset -q $GIT_COMMIT -- dir1/ dir2/ dir3/ ' --prune-empty -- --all
现在,您可以在git远程中添加新的repo并将其推到该位置
git remote remove origin <old-repo>
git remote add origin <new-repo>
git push origin <current-branch>
添加-f来覆盖