【发布时间】:2011-05-16 12:09:28
【问题描述】:
我正在开发一个有两个分支的 svn 项目,让我们调用它们
trunk
branches/foo
我的想法是克隆整个 svn 存储库(告诉 git 哪个文件夹是主干、标签和分支),在 git 中进行合并,然后将我的合并复制到 svn 工作副本并提交来自 svn 的更改。
在这个工作流程中,我能否使用 git 合并功能,还是仅适用于使用 git 本身创建的分支?
【问题讨论】:
我正在开发一个有两个分支的 svn 项目,让我们调用它们
trunk
branches/foo
我的想法是克隆整个 svn 存储库(告诉 git 哪个文件夹是主干、标签和分支),在 git 中进行合并,然后将我的合并复制到 svn 工作副本并提交来自 svn 的更改。
在这个工作流程中,我能否使用 git 合并功能,还是仅适用于使用 git 本身创建的分支?
【问题讨论】:
为结帐命令创建别名:
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 rebase(请参阅答案中底部命令的第 5 个)然后那里应该没有任何问题。顺便说一句,答案中使用的命令git svn rebase 和git svn dcommit 直接与svn 存储库一起工作;你不需要单独的 svn checkout。
git svn clone -s 命令创建的,该命令需要整个 svn 历史记录(这就是为什么这个命令比单纯的 @987654328 慢得多@)。尽管克隆命令不适用于某些颠覆性存储库。
有一种方法可以与 git 进行合并,但使用 Subversion 提交(上游),这种方法设置起来很复杂,但在实践中却很强大(而且比与 Subversion 合并容易得多!)。首先,阅读 Derick Bailey 的 git+svn overview,因为您需要按照他的指示设置 git 和 SVN 忽略文件。
请注意,这个不使用标准的 git-svn 包,而是手动复制了很多功能。如果您已经在使用 git-svn,请不要使用此方法。此外,仅当您将反复从分支合并到主干时才值得使用此方法(尤其是从主干到分支的樱桃采摘),因为这在执行其他合并时会利用 git 的历史记录。
那么,基本步骤如下:
/trunk/ 到工作副本文件夹;我假设它是C:\trunk。git init 该文件夹中的 git 存储库;设置.gitignore; git add -A; git commit(见上文git+svn)。git clone C:\trunk foo。我假设这个克隆位于C:\foo。C:\foo 中除.git 子文件夹之外的所有内容,然后删除C:\foo 中的SVN Checkout /branches/foo。git add -A; git commit 将分支上的更改保存到 git 存储库。这将创建与 C:\trunk 中的历史不同的初始 git 历史。我们现在有两个文件夹,它们都是 git 存储库和 Subversion 工作副本;此外,git 认为这些文件夹是同一存储库的克隆。
在C:\trunk 和C:\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 执行合并。
【讨论】:
branches/foo代码的git分支,可以利用git的历史知识进行多次合并(从分支到主干)并避免在这种情况下通常由 Subversion 合并产生的冲突。此外,git 必须知道一个共同的祖先——你不能只告诉它合并两个文件夹。
我建议您将SmartGit 用于您的 SVN 项目。它对cherry-picking合并和完全合并都有很好的支持,正确修改svn:mergeinfo。
【讨论】: