考虑以下场景:

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

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


当前回答

我今天必须按如下方式解决:项目A在bitbucket中,项目B在代码提交中。。这两个项目都是相同的,但必须将A到B的更改合并。(诀窍是在项目A中创建同名分支,与在项目B中相同)

git签出项目Agit远程删除原点git远程添加源项目Bgit结帐分行git加法*gitcommit-m“我们已经移动了代码”数字推送

其他回答

git子树很好,但它可能不是您想要的。

例如,如果projectA是在B中创建的目录,在git子树之后,

git log projectA

仅列出一个提交:合并。合并项目的提交针对不同的路径,因此不会显示。

格雷格·休吉尔(Greg Hewgill)的答案最接近,但实际上并没有说明如何重写路径。


解决方案出奇地简单。

(1) 在A中,

PREFIX=projectA #adjust this

git filter-branch --index-filter '
    git ls-files -s |
    sed "s,\t,&'"$PREFIX"'/," |
    GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info &&
    mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE
' HEAD

注意:这将重写历史;你可能想先备份a。

注意Bene:如果在文件名或路径中使用非ascii字符(或白色字符),则必须修改sed命令中的替代脚本。在这种情况下,“ls files-s”生成的记录中的文件位置以引号开头。

(2) 然后在B中,运行

git pull path/to/A

瞧!在B中有一个projectA目录。如果运行git-log-projectA,您将看到a中的所有提交。


在我的例子中,我需要两个子目录,projectA和projectB。在这种情况下,我也执行了步骤(1)到B。

除了使用远程add->fetch->merge策略的所有答案之外:如果您想保留其他存储库中的标记,但不想将它们全部泄漏到一个公共命名空间中(可能会发生冲突),您可能需要稍微更改fetch命令:

git fetch --no-tags other_repo
git fetch --no-tags other_repo 'refs/tags/*:refs/tags/other_repo/*'

第一个命令像往常一样获取所有分支,但省略了附加到提交的标记,第二个命令也省略了通常的标记获取机制(git help fetch了解更多信息),并使用git的refspec功能获取将它们从X映射到other_repo/X的所有标记。

引用(分支、标记)只是git中的文件,您可以使用目录来命名。上面的两个命令将保留第一个存储库中的标记,而另一个存储库的标记将以other_repo作为前缀/

操作完成后,最好移除另一个遥控器,这样您就不会意外地以正常方式获取标签并造成混乱。

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

第一件事是使用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

合并2个回购

git clone ssh://<project-repo> project1
cd project1
git remote add -f project2 project2
git merge --allow-unrelated-histories project2/master
git remote rm project2

delete the ref to avoid errors
git update-ref -d refs/remotes/project2/master

要在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