I need to merge two Git repositories into a brand new, third repository. I've found many descriptions of how to do this using a subtree merge (for example Jakub Narębski's answer on How do you merge two Git repositories?) and following those instructions mostly works, except that when I commit the subtree merge all of the files from the old repositories are recorded as new added files. I can see the commit history from the old repositories when I do git log, but if I do git log <file> it shows only one commit for that file - the subtree merge. Judging from the comments on the above answer, I'm not alone in seeing this problem but I've found no published solutions for it.
有没有办法合并存储库,并保持单个文件历史完整?
该函数将远程回购克隆到本地回购目录:
function git-add-repo
{
repo="$1"
dir="$(echo "$2" | sed 's/\/$//')"
path="$(pwd)"
tmp="$(mktemp -d)"
remote="$(echo "$tmp" | sed 's/\///g'| sed 's/\./_/g')"
git clone "$repo" "$tmp"
cd "$tmp"
git filter-branch --index-filter '
git ls-files -s |
sed "s,\t,&'"$dir"'/," |
GIT_INDEX_FILE="$GIT_INDEX_FILE.new" git update-index --index-info &&
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"
' HEAD
cd "$path"
git remote add -f "$remote" "file://$tmp/.git"
git pull "$remote/master"
git merge --allow-unrelated-histories -m "Merge repo $repo into master" --edit "$remote/master"
git remote remove "$remote"
rm -rf "$tmp"
}
使用方法:
cd current/package
git-add-repo https://github.com/example/example dir/to/save
通知。这个脚本可以重写提交,但会保存所有作者和日期,这意味着新的提交将有另一个哈希值,如果你试图将更改推到远程服务器,它只能用强制键,也会重写服务器上的提交。所以请在启动前进行备份。
利润!
假设你想要合并存储库a到b(我假设它们位于彼此旁边):
cd b
git remote add a ../a
git fetch a
git merge --allow-unrelated-histories a/master
git remote remove a
如果你想把a放到子目录中,在上面的命令之前执行以下命令:
cd a
git filter-repo --to-subdirectory-filter a
cd ..
为此你需要安装git-filter-repo(不建议使用filter-branch)。
一个合并两个大型存储库的示例,将其中一个存储库放入子目录:https://gist.github.com/x-yuri/9890ab1079cf4357d6f269d073fd9731
这里有更多。
按照以下步骤,将一个repo嵌入到另一个repo中,通过合并两个git历史,从而拥有一个git历史。
克隆你想合并的两个回购。
Git克隆git@github.com:user/parent-repo.git
Git克隆git@github.com:user/child-repo.git
转到child repo
cd child-repo /
运行以下命令,将路径my/new/subdir(3次出现)替换为您想要拥有子repo的目录结构。
Git filter-branch - pruneempty -tree filter '
如果[!-e my/new/subdir];然后
Mkdir -p my/new/subdir
git ls-tree——name-only $GIT_COMMIT | xargs -I files mv files my/new/subdir
fi '
去父回购
cd . . / parent-repo /
为父repo添加一个远程,指向子repo的路径
Git远程添加child-remote ../child-repo/
取回子repo
Git获取子远程
合并历史
Git merge -allow-unrelated- history - child-remote/master
如果你现在检查父repo中的git日志,它应该已经合并了子repo提交。您还可以看到来自提交源的标记。
下面的文章帮助我将一个回购嵌入到另一个回购中,通过合并两个git历史,拥有一个单一的git历史。
http://ericlathrop.com/2014/01/combining-git-repositories/
希望这能有所帮助。
编码快乐!