与 SVN 上游同步工作

13

我正在处理一个项目,其中使用了来自一个开源项目的代码。其中一个要求是尽可能将代码推回上游。

远程项目正在使用Subversion(不太好用)。

我的当前设置如下:

[Remote SVN] (git svn fetch)-> [My public Git] <-(push/pull)-> [My dev. Git]
                                    VV
                                  (pull)
                                    VV
                               [Testing grid]

编辑于11.7- 重新阐述问题。

我的问题是本地公共存储库和svn上游的共存。

我必须提供3个公共分支:

  • 保守稳定版
  • 实验稳定版
  • 开发版

这些分支现在是线性的(开发变成实验稳定版,实验变成保守),但目标是使用合并的标准三头方法。由于它们是公共的,所以我不能将这些分支rebase。

现在与此完全不相关,我正在尝试以某种方式使发送补丁到上游更容易。从我的分支中挖掘出来很慢,也容易出错。

我的典型当前工作流程如下:

  • 在开发分支之上实现一些功能
  • 测试和修复功能
  • 测试和修复其他受新功能影响的功能(实际上经常发生)
  • 确定是否可以接受上游或不接受上游的内容(30:60是:否)
  • 采取行动(我通常只写一个新的TODO)

上游的另一个问题是他们将补丁接受到不同的分支中(我的公共分支基于他们的稳定分支)。一旦补丁到达稳定分支,我就可以简单地忘记它们的存在,但在此之前,我仍然需要将它们保留在本地。


1
你的任务看起来类似于这个链接:http://hgbook.red-bean.com/read/advanced-uses-of-mercurial-queues.html。可以通过“Mercurial Queues”管理补丁栈来解决。不知道Git是否有类似的工具。 - Alsk
@Alsk 这确实看起来很相似。谢谢你的提示。 - Šimon Tóth
4个回答

30

git svn文档建议在处理Subversion分支时使用以下工作流程:

# 克隆仓库(如git clone):
git svn clone http://svn.example.com/project -T trunk -b branches -t tags
# 将svn:ignore设置附加到默认的git排除文件中: git svn show-ignore >> .git/info/exclude # 查看您已克隆的所有分支和标签: git branch -r # 在SVN中创建一个新分支 git svn branch waldo
# 将主干重置为waldo: git reset --hard remotes/waldo
# 本地更改 git add ... git commit ...
# 获取当前分支上的更改 git svn rebase # 将更改发送到Subversion git svn dcommit
# 检查新分支 git svn fetch

以上工作流程适用于在单个Subversion分支上进行不间断更改,您有提交权限,但是在处理多个活动的Subversion和git分支时会有一些麻烦。

要跟踪Subversion存储库的waldo分支,请从以下命令开始

git checkout -b waldo-svn remotes/waldo

-svn后缀避免了如下警告:

warning: refname 'waldo' is ambiguous.

还提醒您此git分支用于跟踪Subversion分支。始终使这些分支的更改线性!

要更新waldo-svn,请运行

git svn rebase
这将从Subversion获取更改,并在其之上重新应用任何本地更改。它还足够聪明,能够识别一个已被上游完全接受的本地更改:它将被Subversion提交替换,并在其提交消息中有以git-svn-id: ...开头的行。
当上游维护者修改您的补丁的内容和结构(例如修改代码、将一个补丁拆分为多个Subversion提交或将多个补丁合并为单个提交)时,就会变得有趣,需要解决冲突并尝试梳理混乱。
为了实现完全通用性,请保持-git分支在git中干净(没有更改),并从-git分支创建问题分支。要发送补丁,请使用
git diff waldo-svn waldo-fix-frobnicator 然后,当您使用git svn rebase与Subversion repo保持同步时,您需要查看日志,并决定问题分支的各自处理方式,这有点像Git的GTD

3
+1 表示支持“保持你的svn分支干净整洁”。这些分支本质上不是你的svn分支,而是上游分支,因此它们必须在你的本地Git仓库中作为单独的分支存在。如果这样做了,你就可以像处理Git上游分支一样来处理它们了。 - P Shved
1
感谢您如此详细的回答,gbacon。但那不是我遇到困难的部分。我已经重新表述了问题,希望现在更清楚了。 - Šimon Tóth
2
一个更简单的 -T trunk -b branches -t tags 的同义词是 -s - l0b0

1

我并不确定我是否理解了你的问题,但我认为你可能正在寻找git stash


谢谢,这会有所帮助,但并不是整个问题的解决方案。 - Šimon Tóth

1

我不确定你的功能与上游代码有多高度耦合,但你可能可以分支出一个“核心”上游代码,将其与你的功能添加分开维护。这只有在你能够对代码库进行分区的情况下才能真正起作用。


好的,我会对代码进行分区。我将代码的一部分与基础代码完全隔离,因为针对这部分代码的大量补丁使得上游bug修复变得无关紧要。问题在于其余的代码。 - Šimon Tóth

0

你并没有很清楚地表达出你想要做什么。关于你说的“(为每个功能维护单独的分支因此不是微不足道的)”这句话,我只能想知道你为什么认为它应该是微不足道的。互相依存的两个补丁应该是一个单一的补丁,或者至少在一个单一的分支上。一个依赖于 A 的补丁 B(但反之不然)应该在与 A 相同的分支上,或者在一个拥有 A 分支上父提交的分支上。

现在,如果你想要维护一个“清晰的概览”,记录你的所有补丁在上游都在哪里,这将归结为保留所有上游分支的本地副本。我不明白问题出在哪里。如果你想得到更精确的答案,你就需要更加精确地阐述问题。


好的,现在这个问题更容易解决了。

你有两个问题。

(1)是将永远不会上游的分叉提交从主开发分支中移出,并将其放入分叉分支中,一旦你意识到它们永远不会被发送回去。

创建一个分叉分支。一旦你意识到一个功能不会回去,就从保存分叉功能的分支中拉取。然后使用git revert来应用一个撤消本地-*中该功能的补丁。根据需要重复此操作。

(2)是你担心补丁在上游的情况。

你真的不应该跟踪他们是否已经将你的补丁应用到远程稳定版本(以下简称r-stable)。如果你从r-stable拉取并且他们还没有应用补丁,那么在L-stable中你不会失去任何补丁。唯一可能的问题是代码合并时会出现冲突,但你无法避免这种情况。一旦他们应用了补丁,它要么看起来与你解决合并冲突的方式完全相同(在这种情况下,当你从R-stable拉取补丁时,你将得到没有差异的结果),要么他们会以不同的方式进行合并,然后你将遇到合并冲突,并有机会决定保留他们的方式还是你的方式。只需记住,如果你想保留自己的方式,你将从r-stable分叉。其中一个选项是将“你的方式”移动到分支上,并在本地-*上保留他们的方式。


我再次重新表述了问题,希望现在更加清晰明了。 - Šimon Tóth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接