【问题标题】:Git SVN and merging branchesGit SVN 和合并分支
【发布时间】:2011-05-16 12:09:28
【问题描述】:

我正在开发一个有两个分支的 svn 项目,让我们调用它们

trunk
branches/foo

我的想法是克隆整个 svn 存储库(告诉 git 哪个文件夹是主干、标签和分支),在 git 中进行合并,然后将我的合并复制到 svn 工作副本并提交来自 svn 的更改。

在这个工作流程中,我能否使用 git 合并功能,还是仅适用于使用 git 本身创建的分支?

【问题讨论】:

标签: svn git git-svn


【解决方案1】:

为结帐命令创建别名:

git config alias.co checkout

确保您的本地分支机构是最新的:

git co master    # checkout branch that tracks subversion's trunk
git svn rebase 
git co local/foo # checkout branch that tracks subversion's branches/foo
                 # It assumes that  the branch is created with the command:
                 # `git co -b local/foo remotes/foo`
                 # And the repo was created with:
                 # `git svn clone --stdlayout SVN_REPO_URL`
git svn rebase 

合并分支:

# create new local branch based on `master`
git co master
git co -b merging_branch_foo 
# merge, resolve conflicts, etc (pure git)
git merge local/foo  

# rebase `merging_branch_foo` to linearize history for subversion
git rebase master # or `rebase -i`

# merge `merging_branch_foo` into `master`
git co master
git merge merging_branch_foo # --squash to create single commit

# commit changes to svn
git svn dcommit

# (optionally) delete `merging_branch_foo`
git branch -D merging_branch_foo

【讨论】:

  • 感谢您的回答,但它并没有真正回答我的问题。我知道如何使用 git 合并和提交,但我也读过将合并提交到 svn 会导致问题。这就是为什么我想将它合并到 git 中,然后将合并复制到我的 svn checkout 并使用 svn 提交合并,但我的第一个问题也是,即使 git 没有进行分支,git 是否会理解如何合并分支是由 svn 之前制作的。感谢您花时间展示如何进行正常合并
  • @unkown:如果本地 git 分支是最新的(请参阅我的答案中的前 4 个命令)并且您执行了 git rebase(请参阅答案中底部命令的第 5 个)然后那里应该没有任何问题。顺便说一句,答案中使用的命令git svn rebasegit svn dcommit 直接与svn 存储库一起工作;你不需要单独的 svn checkout。
  • Sebastian,您如何看待 Bardleys 在评论中关于 Git 需要了解历史并且它不会知道的回答?根据他的理解,我理解它的方式是,按照你建议的方式,Git 不会知道历史,因此我不会获得任何尝试使用 Git 进行合并的东西。关于您对 dcommit 的评论,我认为您实际上是正确的,它与将其复制到并工作 svn copy and commit 相同。所以感谢您澄清那部分。
  • @unkown:正如我在答案中所指出的,假设 git repo 是使用 git svn clone -s 命令创建的,该命令需要整个 svn 历史记录(这就是为什么这个命令比单纯的 @987654328 慢得多@)。尽管克隆命令不适用于某些颠覆性存储库。
  • 这个别名真的有必要吗?我觉得这会使答案复杂化。
【解决方案2】:

有一种方法可以与 git 进行合并,但使用 Subversion 提交(上游),这种方法设置起来很复杂,但在实践中却很强大(而且比与 Subversion 合并容易得多!)。首先,阅读 Derick Bailey 的 git+svn overview,因为您需要按照他的指示设置 git 和 SVN 忽略文件。

请注意,这个使用标准的 git-svn 包,而是手动复制了很多功能。如果您已经在使用 git-svn,请不要使用此方法。此外,仅当您将反复从分支合并到主干时才值得使用此方法(尤其是从主干到分支的樱桃采摘),因为这在执行其他合并时会利用 git 的历史记录。

那么,基本步骤如下:

  1. SVN Checkout /trunk/ 到工作副本文件夹;我假设它是C:\trunk
  2. git init 该文件夹中的 git 存储库;设置.gitignoregit add -A; git commit(见上文git+svn)。
  3. 创建存储库的 git 克隆(在不同的文件夹中):git clone C:\trunk foo。我假设这个克隆位于C:\foo
  4. 删除C:\foo 中除.git 子文件夹之外的所有内容,然后删除C:\foo 中的SVN Checkout /branches/foo
  5. 在 C:\foo 中,运行 git add -A; git commit 将分支上的更改保存到 git 存储库。这将创建与 C:\trunk 中的历史不同的初始 git 历史。

我们现在有两个文件夹,它们都是 git 存储库和 Subversion 工作副本;此外,git 认为这些文件夹是同一存储库的克隆。

C:\trunkC:\foo 文件夹中执行工作(或只是svn update 以获取其他人的工作)。定期运行 git add -A; git commit 以将更改保存到您的 git 存储库。

现在您想将 foo 分支合并回主干。在 C:\trunk 中,运行 git pull C:\foo。这会拉入并合并来自C:\foo 文件夹的所有更改,这是您跟踪/branches/foo Subversion 分支的git 存储库。如有必要,解决任何冲突并完成 git 提交。

您现在可以将 C:\trunk 中的更改提交到 Subversion,而无需使用 Subversion 执行合并。

【讨论】:

  • 谢谢,这似乎是我要找的。这与使用 git 合并远程 svn 主干和 foo 然后将它们复制到我的 svn 工作副本并通过 svn 提交它会有所不同吗?
  • @unkown:这种方式的不同之处在于,通过创建一个包含branches/foo代码的git分支,可以利用git的历史知识进行多次合并(从分支到主干)并避免在这种情况下通常由 Subversion 合并产生的冲突。此外,git 必须知道一个共同的祖先——你不能只告诉它合并两个文件夹。
  • 布拉德利,我对您的答案投了赞成票,并且可能很快就会成为正确答案。我会再等一会儿,看看其他人是否也有一些建议。您如何看待 Sebastians 关于合并而不是 dcommit 的回答?在那种情况下,git不会对历史有任何了解吗?我想你已经说过不会了,但我只是想 100% 确定这一点。再次感谢您的回答。
  • 我对 git-svn 不是很熟悉(我使用“git+svn”方法的原因之一是(就像 Derick Bailey)我无法让 git-svn 导入我的上游 Subversion 存储库没有崩溃)所以我不能说他的回答是否解决了你的问题。他的回答确实假设您使用的是 git-svn;如果你是,你可能会按照他说的去做;如果你不是,我的方法可能更适合你。
【解决方案3】:

我建议您将SmartGit 用于您的 SVN 项目。它对cherry-picking合并和完全合并都有很好的支持,正确修改svn:mergeinfo。

【讨论】:

    猜你喜欢
    • 2013-04-11
    • 1970-01-01
    • 2017-10-11
    • 1970-01-01
    • 1970-01-01
    • 2013-05-28
    • 1970-01-01
    • 1970-01-01
    • 2013-11-29
    相关资源
    最近更新 更多