考虑以下场景:

我在自己的Git repo中开发了一个小型实验项目a。它现在已经成熟,我希望A成为更大的项目B的一部分,该项目有自己的大仓库。现在我想将A添加为B的子目录。

我如何将A合并为B,而不丢失任何方面的历史?


当前回答

要在B中合并a:

1) 在项目A中

git fast-export --all --date-order > /tmp/ProjectAExport

2) 在项目B中

git checkout -b projectA
git fast-import --force < /tmp/ProjectAExport

在这个分支中,执行所有需要执行的操作并提交它们。

C) 然后回到主节点,两个分支之间进行经典合并:

git checkout master
git merge projectA

其他回答

如果您想单独维护项目,子模块方法是很好的。然而,如果您真的想将两个项目合并到同一个存储库中,那么您还有更多的工作要做。

第一件事是使用gitfilter分支将第二个存储库中所有内容的名称重写到您希望它们结束的子目录中。因此,您将使用projb/foo.c和projb/bar.html代替foo.c和bar.html。

然后,您应该能够执行以下操作:

git remote add projb [wherever]
git pull projb

git pull将执行git fetch,然后执行git merge。如果您要拉到的存储库还没有projb/目录,那么应该不会有冲突。

进一步搜索表明,在将gitk合并为git时也做了类似的操作。Junio C Hamano在这里写道:http://www.mail-archive.com/git@vger.kernel.org/msg03395.html

我在使用merge时不断丢失历史记录,所以我最终使用了rebase,因为在我的情况下,两个存储库的不同程度足以避免每次提交时合并:

git clone git@gitorious/projA.git projA
git clone git@gitorious/projB.git projB

cd projB
git remote add projA ../projA/
git fetch projA 
git rebase projA/master HEAD

=>解决冲突,然后根据需要继续。。。

git rebase --continue

这样做会导致一个项目具有来自projA的所有提交,然后是来自projB的提交

如果要将项目a合并到项目b中:

cd path/to/project-b
git remote add project-a /path/to/project-a
git fetch project-a --tags
git merge --allow-unrelated-histories project-a/master # or whichever branch you want to merge
git remote remove project-a

摘自:git合并不同的存储库?

这种方法对我来说效果很好,它更短,在我看来更干净。

如果您想将project-a放到子目录中,可以使用gitfilter repo(不建议使用过滤器分支)。在上述命令之前运行以下命令:

cd path/to/project-a
git filter-repo --to-subdirectory-filter project-a

合并两个大型存储库,将其中一个放在子目录中的示例:https://gist.github.com/x-yuri/9890ab1079cf4357d6f269d073fd9731

注意:--allow非相关历史参数仅在git>=2.9之后存在。请参阅Git-Git merge文档/-允许不相关的历史记录

更新:按照@jstadler的建议添加了--tags,以便保留标签。

几天来我一直在尝试做同样的事情,我使用的是git2.7.2。子树不会保留历史。

如果不再使用旧项目,可以使用此方法。

我建议你先在B分支机构工作,然后在该分支机构工作。

以下是没有分支的步骤:

cd B

# You are going to merge A into B, so first move all of B's files into a sub dir
mkdir B

# Move all files to B, till there is nothing in the dir but .git and B
git mv <files> B

git add .

git commit -m "Moving content of project B in preparation for merge from A"


# Now merge A into B
git remote add -f A <A repo url>

git merge A/<branch>

mkdir A

# move all the files into subdir A, excluding .git
git mv <files> A

git commit -m "Moved A into subdir"


# Move B's files back to root    
git mv B/* ./

rm -rf B

git commit -m "Reset B to original state"

git push

如果您现在在分区A中记录任何文件,您将获得完整的历史记录

git log --follow A/<file>

这是帮助我做到这一点的帖子:

http://saintgimp.org/2013/01/22/merging-two-git-repositories-into-one-repository-without-losing-file-history/

给定命令是我建议的最佳解决方案。

git subtree add --prefix=MY_PROJECT git://github.com/project/my_project.git master