简单的解决方案:合并后删除“工作”分支
简短的答案:可以随意使用git(请参见下面的简单工作流),包括合并。只要确保在每个“ git merge work ”之后加上“ git branch -d work ”以删除临时工作分支即可。
背景说明:
merge / dcommit问题是,每当您“ git svn dcommit”一个分支时,该分支的合并历史记录就会被“展平”:git忘记了进入该分支的所有合并操作:仅保留文件内容,但是该内容(部分)来自其他特定分支的事实却丢失了。请参阅:为什么git svn dcommit会丢失本地分支的合并提交的历史记录?
(注意:git-svn对此无能为力:svn根本无法理解更强大的git合并。因此,在svn存储库中,此合并信息无法以任何方式表示。)
但这是整个问题。如果您在合并到“主分支”之后删除“工作”分支,则您的git存储库是100%干净的,看起来与svn存储库完全一样。
我的工作流程:
当然,我首先将远程svn存储库克隆到本地git存储库中(这可能需要一些时间):
$> git svn clone <svn-repository-url> <local-directory>
然后,所有工作都在“本地目录”中进行。每当我需要从服务器获取更新(例如“ svn更新”)时,我都会:
$> git checkout master
$> git svn rebase
我在一个单独的分支“工作”中完成所有开发工作,如下所示:
$> git checkout -b work
当然,您可以根据需要为自己的工作创建任意数量的分支,并根据需要在它们之间进行合并和重新设置基础(只需在完成后删除它们---如下所述)。在正常工作中,我经常承诺:
$> git commit -am '-- finished a little piece of work'
下一步(git rebase -i)是可选的---它只是在将历史记录保存在svn上之前清理历史记录:一旦我想与他人共享稳定的里程碑,就重写此“工作”的历史记录分支并清理提交消息(其他开发人员无需查看我在路上所做的所有小步骤和错误-只是结果)。为此,我愿意
$> git log
并复制svn信息库中最新提交的sha-1哈希(如git-svn-id所示)。然后我打电话
$> git rebase -i 74e4068360e34b2ccf0c5869703af458cde0cdcb
只需粘贴我们的上一个svn commit的sha-1哈希而不是我的。您可能需要阅读带有'git help rebase'的文档以了解详细信息。简而言之:此命令首先打开一个显示您的提交的编辑器,只需将您要与以前的提交一起压缩的所有提交的“ pick”更改为“ squash”。当然,第一行应保留为“选择”。这样,您可以将许多小的提交压缩为一个或多个有意义的单元。保存并退出编辑器。您将获得另一个编辑器,要求您重写提交日志消息。
简而言之:完成“代码黑客”工作后,我对“工作”分支进行按摩,直到它看起来像如何向其他程序员展示(或者我希望在几周的时间内浏览历史记录时看到它) 。
为了将更改推送到svn存储库,我这样做:
$> git checkout master
$> git svn rebase
现在,我们回到了旧的“ master”分支,该分支更新了同时在svn存储库中发生的所有更改(您的新更改隐藏在“ work”分支中)。
如果有可能与您的新“工作”更改冲突的更改,则必须在本地解决它们,然后才能推送您的新工作(请参见下面的详细信息)。然后,我们可以将更改推送到svn:
$> git checkout master
$> git merge work # (1) merge your 'work' into 'master'
$> git branch -d work # (2) remove the work branch immediately after merging
$> git svn dcommit # (3) push your changes to the svn repository
注意1:命令“ git branch -d work”非常安全:它仅允许您删除不再需要的分支(因为它们已经合并到当前分支中)。如果在将工作与“ master”分支合并之前错误地执行了此命令,则会收到错误消息。
注意2:请确保在合并和dcommit 之间使用'git branch -d work' 删除分支:如果尝试在dcommit之后删除分支,则会收到错误消息:当您执行'git svn dcommit'时,git会忘记您的分支已与“ master”合并。您必须使用“ git branch -D work”将其删除,这不会进行安全检查。
现在,我立即创建一个新的“工作”分支,以避免意外地侵入“主”分支:
$> git checkout -b work
$> git branch # show my branches:
master
* work
将您的“工作”与svn上的更改集成在一起:
这是当“ git svn rebase”显示我在“工作”分支上工作时其他人更改了svn存储库时的操作:
$> git checkout master
$> git svn rebase # 'svn pull' changes
$> git checkout work # go to my work
$> git checkout -b integration # make a copy of the branch
$> git merge master # integrate my changes with theirs
$> ... check/fix/debug ...
$> ... rewrite history with rebase -i if needed
$> git checkout master # try again to push my changes
$> git svn rebase # hopefully no further changes to merge
$> git merge integration # (1) merge your work with theirs
$> git branch -d work # (2) remove branches that are merged
$> git branch -d integration # (2) remove branches that are merged
$> git svn dcommit # (3) push your changes to the svn repository
存在更强大的解决方案:
呈现的工作流很简单:它仅在每轮“ update / hack / dcommit”中使用git的功能---却使长期项目历史与svn存储库一样线性。如果您只想在旧版svn项目的第一步中开始使用git merge,就可以了。
当您对git合并更加熟悉时,请随时探索其他工作流程:如果您知道自己在做什么,则可以将git合并与svn合并混合(使用git-svn(或类似工具)只是为了帮助svn合并?)