网上搜索了很久也没有找到一个满足目标实现的方案,想在此请教一下大家。
问题的来源是这样的:部门内部原来的项目通过 svn 管理,有一个项目在某年开始在新的 svn 仓库进行了重构开发,结果导致并行存在着两个项目仓库。今年公司内部代码管理迁移到了 gitlab 托管,我将原来两个 svn 项目迁移到了同一个 git 仓库的两个“分支”。当时的参考资料没有留存,再搜索一次找到一篇文章:Git-合并两个不同的仓库,大概就是这样的流程。 其中的问题在于,如果我简单采用类似 git merge B --allow-unrelated-histories
这样的操作,分支将在现有的所有提交之后进行合并。这不是我想要的结果。
由于历史原因导致了现在同一个 git 仓库内的两个“分支”没有共同的祖先来源,本着保留提交历史记录的原因需要同时保留两个“分支”。这两个孤立的“分支”其中一条分支 A 基本不再开发,另一条分支 B 持续开发,B 分支起源时间处于第一条分支 A 的某两次提交 a1 、a2 时间节点之间。
我想:将 B 分支的起点连接在 A 分支 a1 的提交之后,达到在分支图上看 A 分支在 a1 提交之后开了新的分支 B 。具体的细节可以是 B 的源点上游直接是 A 分支的 a1 ,中间也可以增加必要的节点。相当于伪造一下项目的提交流程记录?(因为 B 分支的第一次提交内容就是项目文件的加入,可以在 A 分支上的 a1 提交后增加一个分支节点将文件全部删除提交,再续借上 B 分支(我想的))
有办法实现吗?具体命令是怎样的呢?
附:
现在的分支图:
大概想要实现的分支图:
1
xbcslzy 2023-04-03 10:28:36 +08:00
从 a1 切个新分支 C, 将 B 合并至 C, 删除 B 重命名 C?
|
4
cubecube 2023-04-03 10:36:28 +08:00
以前也幻想过这么整。。最后强行 copy 的。丢了部分历史信息
|
5
lechain 2023-04-03 10:37:13 +08:00 via Android
在 a1 处 merge 分支 b ,然后基于这个 merge 产生的节点 rebase 原本分支 a 的 a1 到最新的所有改动,当然了,rebase 操作也可以换成 cherry-pick
|
6
nothingistrue 2023-04-03 10:59:12 +08:00
有一个项目在某年开始在新的 svn 仓库进行了〖〖〖重构〗〗〗开发,想想为啥当时不是拉 SVN 分支,而是重建仓库。
如果当时不是重构,那么可以这么操作: git checkout -b branch-temp a1 git checkout B git rebase branch-temp rebase 那里可能要加 --force 。因为是重构,所以这里会产生近乎 100%的冲突。 但是实际上来说,你们原始的 A 和 B 就是两个仓库,git 虽然能把它勉强合起来,但是卵用都没有。 |
7
ruanimal 2023-04-03 15:18:37 +08:00
用 git-svn 试试?
|
8
Nile20 2023-04-03 23:36:30 +08:00
在公司实现过类似的需求,当时是合并三个仓并且要保留对应的 commit 记录。像这样的需求不是很常见,没有找到简单的命令或者脚本来处理,最后是自己写的 python 脚本来实现的。
大致思路如下: 从 B 仓库的 root commit 开始,按照如下过程遍历 B 仓库内的所有 commit: 1. 清空 A 仓内 working directory 中的所有文件(保留.git 文件夹) 2. 将 B 仓 checkout 到当前待处理的 commit 3. 将 B 仓内的文件全部复制到 A 仓,然后 git add 4. 获取 B 仓当前待处理的 commit 的 meta data ( author, author date, committer, commit date ),然后使用这些信息在 A 仓的 B 分支上创建一个 commit 上述过程中,如果你能确保 A 、B 仓的起点具有完全一致的文件状态,那也可以把 1-3 改为 cherry-pick 。 获取 meta data 的过程,如果是 python 的话,建议使用 GitPython 。但是如果要创建 commit ,建议直接使用命令行,GitPython 不擅长这个。 步骤 4 将 meta data 传递给特定的环境变量,然后再运行 git 命令即可获得与原 commit 相同的提交时间、作者信息等的 commit 。但是 commit 的 id 必然会变化。如果原 commit 有签名,签名也是无法保留的(或者用你的私钥来签名?不过不太有必要) |
9
SoloCompany 2023-04-04 01:27:17 +08:00
如果你能准确找出 a' 以及对应的 b' 并且经过对比 a'^{tree} 和 b'^{tree} (用 show --pretty=raw 查看 tree object hash, 或直接 diff 命令很简单就能得到结论) 完全相同, 那么事情就非常简单, 把 b'...B^{head} 之间的所有 commit 都 cherry-pick 到 a' 就能得到想要的 B' (或者说 from B rebase a' -i 然后选择 drop 掉 a' 之前所有 commit)
|