我已经开始在我的项目中使用Git,其中前两个提交只是一些初始设置(.gitignore和.gitattributes),第三个提交M2添加了SVN主干的内容:
I1 -- I2 -- M2 -- N -- .. -- Z
Run Code Online (Sandbox Code Playgroud)
我已经在名为svn的分支中导入了SVN历史记录,其中M1是SVN中继(内容与M2相同,除了.gitignore和.gitattributes):
A -- B -- ... -- K -- L -- M1
Run Code Online (Sandbox Code Playgroud)
问:合并两个分支的最佳方法是什么?
我可以将M1和M2合并到M3中,然后重新绑定,但我不知道如何删除I1和I2提交,如果我可以安全地删除M3提交(我已经找到一些建议来保留合并提交,但是这种情况M3不再需要了).
A -- B -- ... -- K -- L -- M1
\
M3 -- N' -- .. -- Z'
/
I1 -- I2 -- M2 -- N -- .. -- Z
Run Code Online (Sandbox Code Playgroud)
另一种方法是樱桃挑选N .. Z手工提交到svn分支,但我想避免这种方法.
最优雅的解决方案是重新定义N .. Z在svn分支之上提交的更改,但是我没有找到没有共同祖先的两个分支所需的语法.
jan*_*nko 26
免责声明:我自己只在玩具库中使用过"贪污点".但这是一个你可能没有听说过的晦涩难懂的特征,而且可能对你的情况有所帮助.
您可以使用"嫁接点"伪造祖先信息.参见,例如,什么是.git/info/grafts?或立即进入嫁接点的git wiki条目.
从本质上讲,你会创建一个文件.git/info/grafts,欺骗git认为提交M1是提交M2的祖先:
$ cat .git/info/grafts
<your M2 commit hash> <your M1 commit hash>
Run Code Online (Sandbox Code Playgroud)
随后,看起来M2是一个空提交,只是将I2和M1合并到一个公共树中.
主要缺点:贪污点没有承诺; 因此,它没有签出,但需要手动添加到存储库的每个本地工作副本.
更新: 改为使用git replace --graft.
如上所述,移植点已被取代.跑
git replace --graft <your M2 commit hash> <your M1 commit hash>
Run Code Online (Sandbox Code Playgroud)
创造移植物.这存储在.git/refs/replace/.虽然git默认不提取或推送这些引用,但是可以使用以下命令在存储库之间同步它们:
git push origin 'refs/replace/*'
git fetch origin 'refs/replace/*:refs/replace/*'
Run Code Online (Sandbox Code Playgroud)
(StackOverflow:如何推送'refs/replace'而不在git中推送任何其他引用?)
我会做以下事情:
git checkout M1
git cherry-pick I1
git cherry-pick I2
Run Code Online (Sandbox Code Playgroud)
这会将 .gitignore 和 .gitattributes 添加到包含更好历史记录的分支中。
然后将新的提交设置在该提交之上:
git filter-branch --parent-filter 'if $GIT_COMMIT = $hash_of_N; then printf -- '-p
$hash_of_cherrypicked_I2\n'; else cat; fi'
Run Code Online (Sandbox Code Playgroud)
这样做的缺点是你重写了历史。
因此,另一种方法是创建一个类似于Linux 内核的脚本 并将其放入您的存储库中。
| 归档时间: |
|
| 查看次数: |
16246 次 |
| 最近记录: |