同一个svn仓库的不同git-svn克隆是否可以在使用git svn dcommit时共享更改?

35

我已经阅读了很多关于“从svn转向git”和其他“git-svn工作流程”的文章,并且我认为它们通常处理过于简单的情况。它们通常面向那些只想使用git并本地hack,而不使用全部git功能(如在多个使用git-svn克隆了svn存储库的开发人员之间进行pull、fetch、merge等操作),然后仍然希望能随时将其更改推送到(正式的)svn存储库,并回到使用git和共享他们的东西等。

每当这些文章承认您无法完成纯git中可以完成的所有操作时,其可能造成的后果和可能的失败都没有得到清晰的解释(或者也许只是我?)。即使是git-svn手册也提到了注意事项,但并没有详细说明。

根据我所读的内容,我觉得在以这种特定方式使用git-svn时可能会出现问题,我会在下面描述。有人能告诉我我是否正确吗?

以下是“期望”的工作方式:

  1. 我们在svn存储库中有一个项目
  2. 开发人员A使用git-svn-clone克隆svn仓库。他开始在本地修改内容
  3. 开发人员B使用相同的git-svn-clone克隆svn仓库。他开始进行自己的修改。
  4. 在这样做一段时间后,可能添加了开发人员C/D/...,并有其他“标准”的svn提交到原始仓库的开发人员,git用户将想分享他们的代码并做所有种类的git操作。
  5. 任何一个这些git用户都希望能够将现在合并的更改推送到svn(dcommit?)
我的问题是:我在做梦吗?我有一段时间前读了一本git书,其中提到git-svn-clone可以创建git存储库,这些存储库当然是svn存储库的"镜像",但是使用不同开发人员创建的以这种方式创建的git存储库将具有不同的"id"和提交将具有不同的哈希值。因此,我理解这些git存储库不会共享任何公共git祖先,因此无法使用所有需要共享、合并等命令。这是真的吗?我们将面临这种工作流程的问题吗?

有时候我看到这可以通过至少使用一个"官方"裸git存储库来完成,该存储库将是唯一一个被git-svn克隆的存储库,所有git用户都必须从这个存储库开始。然后您需要有人负责这个中央git存储库,并收集git开发者之间的更改,然后将所有内容dcommit到svn存储库。这将是让git用户“不知道”原始git存储库来自svn的唯一方法,并让他们随意使用所有git命令的方式。唯一需要精通git和svn(并了解git-svn注意事项)的人是“合并管理器”(或他被称为什么)。

我是不是完全误解了git-svn注意事项?有没有更简单的方法来做到这一点?


7个回答

23

我最近一直在进行这方面的实验,我想我成功地设计出了一种有些可行的设置。是的,它是一个严格的rebasing-only制度,是的,它很复杂,但你可以使用Git在本地工作(速度、历史记录、stash、索引等)。

如果你与团队中的其他Git用户协作,你可以在幕后使用分支,但我个人对此并没有进行过太多的实验。只要你在dcommit之前线性化日志,它就应该可以工作。

以下是简短版本(大部分已经重复了之前所说的内容):

  1. 将Subversion repo克隆到位于中央服务器上的“获取”repo中
  2. 在同一台服务器上初始化一个“裸”(bare) repo
  3. 从获取repo推送到裸repo
  4. 开发人员克隆裸repo,然后
    1. git svn init svnurl 来配置git-svn远程,并且
    2. git update-ref refs/remotes/git-svn refs/remotes/origin/master 以便git-svn指向一个修订版本
  5. 自动(提交钩子)使“获取”repo svn rebase,并推送到裸repo
  6. 开发人员使用 git pull --rebase从裸repo拉取
  7. 运行git svn dcommit的开发人员首先必须重复上述update-ref以防止来自SVN的较新修订。

这个页面有一个流程图(我需要更多的声望才能内联图像)。更新:在这里:


2
这个回答的关键点在于第 6 步: git update-ref refs/remotes/git-svn refs/remotes/origin/master。这是让开发者将他们的克隆链接到 svn 的方法。这就是让分享 origin/master 成为可能,并且 同时 将其用于推送至 svn 的方法。如果没有第 6 步,开发者必须在 origin/mastergit-svn 分支之间来回切换。获取存储库和提交挂钩并非绝对必要:开发者可以在 dcommit 到 svn 后立即将其推送到裸存储库的 master - Oleg
另外一个问题上,我有一个详细的答案,展示了第6步。远程名称很容易弄错,最好能让git svn rebase真正起作用。 - undefined

19

问题在于第四步。dcommit 试图将你的本地历史记录回放到服务器上。dcommit 假装你是一个 SVN 客户端。现在,如果你提交的代码不仅仅来自于你,这就是很难提交到 SVN 的东西。

以下是专家在此问题上的观点:

  • 为了简单起见并与 SVN 互操作,建议所有 git-svn 用户直接从 SVN 服务器(即远程 SVN 存储库)克隆、提取和提交,并避免所有 git-clone/pull/merge/push 操作,这些操作涉及通过 git svn 克隆检索的 git 存储库和分支,同时也用于将更改集推回远程 SVN 存储库。
  • 交换 git 分支和用户之间的代码的推荐方法是使用 git format-patch 和 git am,或者只是使用 git svn dcommit 提交到 SVN 存储库。
  • 由于 git svn dcommit 在内部使用 git svn rebase,因此我们在它们上面进行 git 推送之前 git 推送到的任何 git 分支都需要强制覆盖远程存储库上的现有引用。这通常被认为是不好的做法,请参阅 git-push 文档以获取详细信息。
  • 不建议在我们计划从中 git svn dcommit 的分支上运行 git merge 或 git pull。SVN 不以任何合理或有用的方式表示合并,因此使用 SVN 的用户无法看到我们进行的任何合并。此外,如果从是 SVN 分支的镜像的 git 分支进行 git merge 或 git pull,则 git svn dcommit 可能会提交到错误的分支。
  • git 克隆不克隆 refs/remotes/ 分层结构下的分支、任何 git-svn 元数据或配置。因此,使用 git 克隆创建和管理的存储库和分支不能与 SVN 互操作。
使用git-svn应该使用rsync进行克隆,如果确实需要克隆的话。 我们不应该在已经dcommitted的更改上使用git commit的--amend选项。这被认为是一种不良做法,因为对于已经推送到远程存储库供其他用户使用的提交,我们不应该使用--amend进行修改,并且与SVN一起使用dcommit类似。有关此问题的更多信息,请参见单个提交的修改和重写历史的问题

谢谢。我不知道“guru”。嗯,看来我们卡住了。没有合并/拉取,建议使用差异和补丁,这听起来不像Git的强大之处(除了本地和个人完成的小事情)。 - Ced-le-pingouin
1
大师确实提到通过邮件分发的补丁是可以的。 - nes1983
3
“不要合并/拉取(diff和patch)”,但是仅限于:“在我们计划从git svn dcommit的分支上”。这意味着,是的,你可以使用git合并/拉取/挑选更改并获得强大/魔力;只需在-另一个-分支上解决你的更改问题,然后再将其推送到svn中。这并不太难,变基或合并--压缩应该就可以了。 - inger

3

有一个工具可以解决与Subversion同步的Git版本库共享问题。

SubGit 是一个Git-SVN双向服务器镜像。

您可以将SubGit安装到Subversion存储库中,并自动将Git存储库与SVN同步:

$ subgit configure $SVN_REPOS
# Adjust $SVN_REPOS/conf/subgit.conf to specify branches, tags and other options;
# Adjust $SVN_REPOS/conf/authors.txt to specify git & svn authors mapping
$ subgit install $SVN_REPOS
...
$ INSTALLATION SUCCESSFUL

SubGit会在Subversion仓库中安装pre-commit和post-commit钩子,在Git仓库中安装pre-receive和post-receive钩子。因此,它可以立即将来自SVN和Git两个方面的修改进行翻译。在SubGit安装后,开发人员可以使用任何Git客户端来克隆并且使用Git存储库。
SubGit不依赖于git-svn,而是使用我们团队开发的翻译引擎。您可以在SubGit vs. git-svn比较页面上找到更多详细信息。有关SubGit的常规文档,请单击此处
SubGit 1.0版本需要本地访问Subversion存储库,即SVN和Git存储库必须位于同一主机上。但是,在2.0版本中,我们将引入Git代理模式,此时Subversion和Git存储库可以位于任何位置,只有Git存储库中安装了SubGit,即Subversion存储库保持不变。
SubGit是一款商业产品。它对于开源项目、学术项目以及最多有10个提交者的项目是免费的。
免责声明:我是SubGit开发人员之一。

3
我以前的做法是先创建一个git svn克隆,然后使用git共享.git文件夹给开发人员,这样我们就有了完全相同的参考。

在线性树中(即使用变基而不是合并的情况下),似乎能够正确地使用“特定的git功能”来进行git用户之间的交互。

2

2

我发现这篇博客文章建议为与Subversion存储库同步保留单独的分支,以便在主分支中仍然可以进行push/pull操作。


链接已经失效,而且答案对于博客内容提供的线索非常少。这就是仅仅链接到博客但没有提供更多细节的问题所在... - mutex

1

我认为git-svn存在的一个问题是它将git-svn-id存储在提交注释中;因为这会重写该提交,从而更改其SHA1,所以您无法将其推送到任何人都会共享的地方。

实际上,我更喜欢bzr-svn,因为它使用SVN修订属性功能将bzr revid存储在远程SVN修订版本中,这意味着没有本地修订重写。它还具有所需的属性,即同一SVN分支的两个独立拉取将导致相同且可互操作的bzr分支。


完全同意。使用git-svn无法共享继承自相同svn树的git分支非常痛苦。 - David Fraser

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