我有一个Git repo,它是来自另一个Git repo的克隆,它是来自巨型SVN repo的克隆。我们可以从SVN更新其他Git repo并从中提交给SVN,但是与另一个用户一起提交。
我想用我自己的用户直接将我的本地提交发布到SVN repo。
这就是我尝试过的:我手动创建了git-svn
分支,将其添加到.git/config
[branch "master"]
[svn-remote "svn"]
url = https://url/to/svn/trunk/repo_name
fetch = :refs/remotes/git-svn
然后git svn fetch
,下载了32k提交。
但我最终得到了两个不相关的历史:
674c35a
开始,表示原始克隆点处SVN仓库的状态。master
始终与SVN同步(通过其他Git仓库)。dev
有我们目前的发展,应该合并到master
(通常被压扁),然后提交回SVN回购。fb1b9c7
]克隆的提交(但只有前一次提交的diff,而不是整个repo作为开始提交)。git/origin/master
应该是共同的提交(100+)。如何告诉Git启动提交(674c35a
)实际上与SVN提交(fb1b9c7
)相同?那么Git可以以某种方式理解克隆之后master
中的提交实际上与git-svn
相同吗?
我已尝试使用--onto
进行变基,正如here所解释的那样,但这并不是我想要的(提交不在分支的顶部)。
答案 0 :(得分:1)
我相信我的博客文章Grafting History with Git中有一个适用于此的方法,为了遵守网站规则,我将在此总结:
现状:
目标状态:
git log --reverse --format="%T %H"
获取每个分支上的tree-id和commit-id列表,并将其保存到文件git read-tree -um $TREEID
git commit --reuse-message $ORIGINAL_COMMIT
或者......将您的tree-id + commit-id列表添加到此脚本中。
#!/bin/bash # graft script while read TREE COMMIT do git read-tree -um $TREE git commit --reuse-message $COMMIT done
答案 1 :(得分:0)
你的历史可能看起来像这样:
*--*--*--fb1b9c7--*--*--* [git-svn] (version of master from SVN)
674c35a--*--*--* [master] (version of master from Git)
\
*--*--*--* [dev]
看起来您有两个问题:您的Git历史记录不包含完整SVN历史记录中的30k +提交,dev
基于(不完整的)Git历史记录而不是SVN版本。
自fb1b9c7
== 674c35a
以来,您应该可以:
git rebase --onto git-svn master dev
我的实验表明git rebase
并不关心目标分支(git-svn
)与基本分支(master
)的历史记录不同。 SVN只存储差异也无关紧要,因为git-svn会在获取过程中将这些差异转换为真正的Git提交。
由于历史记录包含相同的内容,您甚至可以这样做:
git checkout dev
git rebase git-svn
之后,您可以删除master
并让该树稍后进行垃圾回收。 (如果您仍需要单独的master
分支,请在删除原始git checkout -b master git-svn
后执行master
。
当你说:
(提交不在分支的顶部)
我假设您指的是提交fb1b9c7
和674c35a
。但是,这些提交被埋没在历史中并不重要,因为我们将选择一个(fb1b9c7
)使用,并让另一个进行垃圾收集,如上所述。
答案 2 :(得分:0)
如果您想用另一个提交替换一个提交,只需使用git replace
,例如git replace 674c35a fb1b9c7
。
如果您想要永久保留,请使用git rebase
。