我如何将一个我没有写权限的Google Code Subversion仓库fork并保持同步到GitHub仓库?
我想在我的Git仓库中开发自己的功能,但我也希望与Google Code Subversion仓库保持同步,以从Google Code项目方面获取修复。
我知道git-svn并曾经使用它来上下游到我完全控制的Subversion仓库。但我不知道如何与Google Code Subversion仓库保持同步。
从git-svn的远程分支来看,它基本上与常规的Git远程分支相同。因此,在本地仓库中可以有你的git-svn克隆,并将更改推送到GitHub。Git并不在意。如果你创建了一个git-svn克隆并将完全相同的更改推送到GitHub,那么你就会拥有Google Code存储库的非官方镜像。其余都是普通的Git。
git svn clone http://example.googlecode.com/svn -s
git remote add origin git@github.com:example/example.git
git push origin master
现在您已经拥有了这个,偶尔需要将Subversion存储库与Git同步。它会看起来像这样:
git svn rebase
git push
在gitk或类似工具中,它看起来像这样:o [master][remotes/trunk][remotes/origin/master]
|
o
|
o
当你运行 git svn rebase
时,会出现以下情况:
o [master][remotes/trunk]
|
o
|
o [remotes/origin/master]
|
o
|
o
现在运行git push
命令将提交推送到GitHub,其中包括那些在那里的[remotes/origin/master]分支。然后您将回到第一个ASCII示意图中的情况。
问题是,如何将您的更改加入到混合中?想法是,您不要在正在进行git-svn-rebase和git-push的同一分支上提交。您需要为自己的更改创建一个单独的分支。否则,您的更改将被重新基于Subversion的更改,这可能会使克隆您的Git存储库的任何人感到不适。明白了吗?好的,所以您创建一个名为“features”的分支。您进行提交并将其推送到GitHub的“features”分支。您的gitk看起来应该像这样:
o [features][remotes/origin/features]
|
o
|
o [master][remotes/trunk][remotes/origin/master]
|
o
你现在有一个特性分支,它比Google Code分支多了几个提交。那么当你想要将新的内容从Google Code合并进来时会发生什么?你需要首先运行git svn rebase
,然后得到这样的结果:
o [features][remotes/origin/features]
[master][remotes/trunk] o |
| o
o /
|/
o[remotes/origin/master]
|
o
如果你git push
master out,你可以想象[remotes/origin/master]与主分支相同。但是你的特性分支没有这些更改。现在你有两种选择,要么将主分支合并到特性分支,要么将特性分支重新设置基础。合并将会是这样:
git checkout features
git merge master
o [features]
/|
/ o [remotes/origin/features]
[master] o |
| o
o /
|/
o
|
o
然后你将功能推送到GitHub。我省略了主分支的远程引用,以节省空间,它们应该与 [master] 处于同一点。
变基方法略微更加恶劣 - 你需要使用 --force 参数进行推送,因为你的推送不会是快进合并(你会从已经克隆过的某人那里拉取功能分支)。虽然这样做并不被认为是正确的,但如果你决心这样做,没有人能阻止你。它也使一些事情变得更容易,例如当补丁以稍微修改的形式被上游接受时。这将避免处理冲突,只需通过 rebase --skip 命令跳过上游补丁即可。无论如何,一个变基会像这样:
git rebase master features
o [features]
|
o
| o [remotes/origin/features]
[master] o |
| o
o /
|/
o
|
o
然后你需要用git push --force
来强制推送。你可以看到为什么需要强制,因为历史记录从[remotes/origin/features]到新的当前后置基础上存在着一个很大的分裂。
所有这些都有效,但需要付出很多努力。如果你要成为一名常规贡献者,最好的方法是像这样工作一段时间,将一些补丁发送到上游,并尝试获得对Subversion的提交访问权限。如果失败了,也许不要将您的更改推送到GitHub上。保持本地并尝试在上游获得它们的接受。
http://svn2github.com/ 网站提供了一项服务,可以将任何公开访问的 SVN 仓库复制到 Github 上(在 https://github.com/svn2github/projectname)。我尝试了它;点击“Make a mirror”按钮后,它似乎没做任何事情,显示“error”消息,但实际上它确实起作用了。新仓库已被创建,其中包含 SVN 仓库中的代码。
然后,您可以 fork 它创建的仓库并在自己的 fork 上工作。您可以使用他们的 bugtracker 将更改提交给上游项目。
查看服务的 Github 用户下的现有存储库(例如“svn2github pushed to master at svn2github/haxe 5 hours ago”),它似乎定期从 SVN 仓库中拉取更改。网站上没有关于谁运行该服务的信息,因此我不确定它是否会无限期运行,但它现在是可用的(如果它停止运行,您仍然可以手动更新您的 fork)。
如果你不想使用 Git 和 Github,则另一个选择是使用 Launchpad.net。 Launchpad 可以自动将 SVN(还有 CVS)仓库导入到个人的 bzr 分支中。为此,请创建一个 Launchpad 项目,然后转到新的导入页面,选择 Subversion 并输入 URL(例如 http://projectname.googlecode.com/svn/trunk/
)。根据项目大小,初始导入可能需要几个小时。随后的导入将定期运行。
有关更多文档,请参阅Launchpad 帮助上的 VCS Imports。
一份将代码从Google Code同步到GitHub的指南可在fnokd.com找到。作者使用一台始终开启的远程服务器和定时任务来自动化同步,并将SVN主干保留在名为“vendor”的GitHub分支中。
GitHub现在支持直接导入Subversion项目(参见http://help.github.com/import-from-subversion/)。只需创建一个新的repo,然后在“下一步”屏幕上点击“从Subversion导入”。但是它不支持进一步同步 :/。
git svn clone https://foo.googlecode.com/svn/ git-foo
cd git-foo
git remote add git-foo git@github.com:username/foo.git
git push git-foo master
cd /path/to/git-foo
git svn fetch
git svn rebase
git push git-foo master
我不太确定你想要什么,但是当然可以从一个子版本库中拉取并将其推送到Git存储库的同一工作副本中。您还可以使用git svn dcommit
将其提交回子版本库。但是,您无法使GitHub存储库与子版本库同步。此外,如果您的工作副本中有尚未在子版本库中的提交,则需要对其进行变基,如果子版本库已更新,则需要强制执行git push --force
将“新”提交推送到GitHub。
git push origin --mirror
。 - mpontillogit svn clone
命令的-s
选项时,这对我无效,但是如果不用该选项,则其余部分完全可以正常工作。 - user1027169