【问题标题】:Merge multiple git repositories into one, keeping branches history将多个 git 存储库合并为一个,保留分支历史记录
【发布时间】:2014-12-17 15:19:15
【问题描述】:

我有四个独立的项目。他们有自己的 git 存储库。以及所有项目的相同分支名称。

 /project/
 /project/projA/
 /project/projA/.git/
 /project/projB/
 /project/projB/.git/
 /project/projC/
 /project/projC/.git/
 /project/projD/
 /project/projD/.git/

所有 git 存储库都有相同名称的分支,当然还有自己的 master 分支。

问题

我想像这样将所有项目合并为一个:

  /Project/.git/
  /project/projA/
  /project/projB/
  /project/projC/
  /project/projD/

但是

我想保留所有分支的历史记录。

ps -> 我对所有 repo 都有相同的分支名称。 例如:用于所有四个项目的分支名称:V6-004

详情

我尝试了 submodulesubtree 但两者都没有解决问题。

我也试过这个。

  $ mkdir new_parent_project
  $ cd new_parent_project
  $ git init
  # Now we need to create the initial commit. This is essential.
  $ touch README.md
  $ git add README.md
  $ git commit -am "initial commit"

之后

  # merge project ProjA into subdirectory ProjA
  $ git remote add -f ProjA http://GitUrl
  $ git merge -s ours --no-commit ProjA/V6-006
  $ git read-tree --prefix=ProjA/ -u ProjA/V6-006
  $ git commit -m "merging ProjA into subdir: ProjA"

之后

  # merge project ProjB into subdirectory ProjB 
  $ git remote add -f ProjB http://GitUrl
  $ git merge -s ours --no-commit ProjB/V6-006
  $ git read-tree --prefix=ProjB/ -u ProjB/V6-006
  $ git commit -m "merging ProjB into subdir: ProjB"

但是

项目已合并,但我只有 V6-006 的历史记录。但我没有其他分支的历史记录。

【问题讨论】:

  • “我尝试了子模块和子树,但两者都没有解决问题。”......太糟糕了:在这种情况下,子模块是一个简单的解决方案。
  • 是的,但是。当您想在项目中包含仅偶尔需要更新的第三方库时,此模型效果很好。另一方面,如果您将子模块用于紧密耦合的库,您将经常对其进行更改,你会发现子模块不是答案。
  • 每个子仓库是否只有一个分支 (master) 可以进入您的仓库?或者这些子回购是否有自己的多个分支? (除了他们的master
  • 是的,这些子存储库有自己的多个分支。
  • 您只需要单个分支和子目录中的所有现有历史记录,然后在最后合并一个巨大的章鱼将所有内容组合在一起吗?

标签: git github merge git-branch git-subtree


【解决方案1】:

该解决方案与您尝试的方案相去甚远。 这仅在您的不同项目没有公共文件时才有效(否则可能难以解决冲突)

# create a new repo:
git init all_projects
cd all_project
# to make it more easy to understand, let's create a new branch
git checkout -b main

# import 1st project
git remote add projectA http://projectA
git fetch --all --tags
git checkout masterA projectA/master
git rebase masterA main
# move the main branch to the current state
git branch main -f
# Now your branch main is at the same state as your A project

# import 2st project
git remote add projectB http://projectB
git fetch --all --tags
git checkout masterB projectB/master
git rebase masterB main
# move the main branch to the current state
git branch main -f
# Now your branch main contains all commits from projectA and projectB

# etc..

结果将是一个存储库,其中首先包含来自项目 A 的所有提交,然后是来自项目 B 的所有提交,即使项目 B 有一些提交日期在项目 A 的最后一次提交之前,但这应该不是问题(并且历史树会更容易阅读)

编辑:对不起,我只是注意到这并不能解决您获取所有远程分支的问题。也许你可以找到基于that question 的解决方案,类似这样:

for i in $(git branch -r |grep projectA|awk -F'/' '{print $2}'); do
  git checkout $i projectA/$i
  git rebase $i main
done

但这会使你的树更复杂,因为所有分支都将从main 提交开始..

【讨论】:

  • 我无法让它工作,它在步骤git checkout masterA projectA/master 上给出了一个错误,说error: pathspec "masterA" did not match any files known to git。我应该在“masterA”中添加什么?
  • 如果 git 将masterA 视为一个文件,这可能意味着该分支在本地不存在(我想也不存在远程)。或者git fetch 不见了
  • @Asenar 你知道如何处理两个 共享公共文件的存储库,即一个是另一个没有历史记录的分支吗?我是trying to figure this out here
  • @przemo_li 远程仓库的 url 可以从 httpuser@server/path/to/loca/dir 开始,所以我不明白为什么这不起作用。但您可以查看git help clone 以查看一些有趣的选项(--no-hardlinks、--shared、...)
  • 我认为这行不通,因为 masterA 需要在子目录中结束;现在合并和变基只将文件添加到主目录。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-26
  • 1970-01-01
相关资源
最近更新 更多