使用git-svn(或类似)*just*来帮助svn合并?

ing*_*ger 27 svn merge svk git-svn hgsubversion

我的项目中出现了一些复杂的颠覆合并:长期分离的大分支.Svn给出了太多的冲突 - 其中一些似乎是虚假的.


鉴于git对于优秀的合并体验而言,为了使合并更易于管理,使用git-svn 它是否有益?


你能推荐其他的替代品(如svk,hgsvn),以减轻疼痛合并?

有些冲突很容易解决(例如java导入,空格) - 所以我也想知道是否有任何自动解决方案.

将来可能会完全切换到DVCS(我们中的一些人会喜欢),但现在不行.(更新:这不再是真的 - 团队最近完全切换并对此感到高兴).

提前致谢.

PS:有些帖子似乎是相关的(例如git-svn合并2个svn分支),但他们没有完全回答这个问题.

更新:看完我的-novice-回答后再往下走(这个道路).

ing*_*ger 34

试图回答我的问题:使用git进行svn合并似乎很有希望.

更新:它不仅仅是有希望的,它取得了巨大的成功.简而言之,Linus是对的.

刚刚完成了2个svn分支的巨大合并,这些分支已经分开了1.5年; 3k文件被更改,在svn中有大量冲突(我认为~800).

我发现git&git-svn是一个救生员:

  • 自动冲突解决方案:首先,它提供了更少的冲突文件(我认为〜一半)
  • 令人难以置信的表现
  • 出色的repo /分支模型,灵活的工作流程:使用各种方法轻松实验,例如chunk-by-chunk(及时)合并,始终进行健全性检查(编译等); 每当遇到麻烦时:只需回溯.您可以随时在需要时退后一步.
  • 可用性,出色的工具:
    • git-log(以及基础git-rev-parse选项),没有什么能比这更强大.它也很方便:-p一次性给你差异; 在svn中你得到一个日志,然后找到"revision-1:revision"的差异,或使用笨拙的UI.查找何时将字符串添加/删除到repo中,同时搜索多个分支
    • gitk:对于可视化分支历史非常有用,并具有出色的搜索功能.在其他工具中没有看到这样的东西,特别是没有这么快.没关系它在Tk,它很棒
    • git gui:即使不是最性感也能正常工作 - 对于新手发现事物有很大的帮助
    • blame: 奇迹.是的,它会检测原始片段的来源(复制和粘贴等)
    • mergetool:比开始大的更好的体验svn merge,然后每次停止(即每5分钟)它会遇到冲突,按'(p)ostpone',而不是以后手动搜索冲突的文件.首选的是它的味道git gui(需要一个小补丁).发现集成外部差异工具比可以更好地配置svn.
    • 可插拔的合并驱动程序和对它们的细粒度控制
    • rebase 允许过滤掉svn历史的混乱部分
  • 分配:在此工作时无需上台,可以在火车/飞机上一步一步地暂停和进步.
    • Unison的USB驱动器同步工作< - >家里一块蛋糕
    • 如果没有git的疯狂压缩,这是不可能的(5年的项目有26k提交,大量的分支和二进制文件,trunk svn checkout:1.9Gb =>所有这些在完整的git repo中:1.4Gb!)

所以,这真的可以改变从噩梦到欢乐的区别 - 特别是如果你喜欢学习(在这种情况下需要付出一些努力 - 我想在骑自行车后学习摩托车).

即使我不能强迫公司里的每个人立即切换 - 我真的不打算这样做.再一次,git-svn通过"先蘸脚趾"的方法来拯救我们.但是看到同事们的反应,切换可能会在任何人预期之前发生:)

我会说 - 即使我们忘记了合并和提交,这些东西已经很好用作查询,可视化,备份等的只读前端.

警告:

"请不要将Git合并提交到Subversion存储库.Subversion不会像Git一样处理合并,这会导致问题.这意味着你应该保持你的Git开发历史是线性的(即不与其他分支合并,只是变基.)" (http://learn.github.com/p/git-svn.html的最后一段)

另一个很好的来源是Pro Git书,"切换活动分支"部分基本上说合并确实有效,但dcommit只会存储合并的内容,但历史记录会受到损害(打破后续的合并),所以你应该放弃合并后的工作分支.无论如何它毕竟是有道理的,在实践中很容易避免陷阱在这里...在svn中,我发现人们通常不会重新合并,所以这只能被视为后退如果你来自第一个git世界地点.

无论如何,dcommit只对我有用.我把它放在我自己的svn workbranch上,我只保留这个,所以避免任何额外的冲突.但是,我决定从这个workbranch到svn中的svn trunk进行最后的合并(在git中同步所有内容之后); --ignore-ancestry在那里给出了最好的结果.

更新:正如我后来发现的那样,上面的最后几个步骤(额外的svn分支和合并 - ignore-ancestry)很容易通过保持你从线性分支的分支来避免.正如Gabe在下面所说, merge --squash只是创建了一个简单的svn友好提交.就在我在当地分支机构准备好大量合并时(可能需要数天/周),我现在只是:

git checkout -b dcommit_helper_for_svnbranch  svnbranch
git merge --squash huge_merge_work_with_messy_nonlinear_history
git commit 'nice merge summary' # single parent, straight from the fresh svnbranch
git dcommit
Run Code Online (Sandbox Code Playgroud)

我知道合并跟踪在svn端不会很好,直到我们完全切换.我等不及了.


更新:@Kevin要求关于合并svn分支的整个过程的更多细节..有很多文章,帖子在那里,但作为一个新手我发现一些令人困惑/误导/过时..无论如何,我的方式这些天做的(当然,在合并之后坚持使用git-svn;就像一些新感染的同事一样)..

git svn clone -s http://svn/path/to/just-above-trunk  # the slowest part, but needed only once ever..you can every single branch from the svn repo since revision #1. 2) 
git svn fetch          # later, anytime: keep it up to date, talking to svn server to grab new revisions. Again: all branches - and yet it's usually a faster for me than a simple 'svn up' on the trunk:)    
# Take a look, sniff around - some optional but handy commands:
git gui   &    # I usually keep this running, press F5 to refresh
gitk --all     # graph showing all branches
gitk my-svn-target-branch svn-branch-to-merge    # look at only the branches in question
git checkout -b my-merge-fun my-svn-target-branch  # this creates a local branch based on the svn one and switches to it..before you notice :)
# Some handy config, giving more context for conflicts
git config merge.conflictstyle diff3
# The actual merge.. 
git merge  svn-branch-to-merge    # the normal case, with managable amount of conflicts
# For the monster merge, this was actually a loop for me: due to the sheer size, I split up the 2 year period into reasonable chunks, eg. ~1 months, tagged those versions ma1..ma25 and mb1..mb25 on each branch using gitk, and then repeated these for all of them
git merge ma1   # through ma25
git merge mb1   # through mb25
# When running into conflicts, just resolve them.. low tech way: keep the wanted parts, then "git add file" but you can
git mergetool   # loops through each conflicted file, open your GUI mergetool of choice..when successful, add the file automatically.
git mergetool  my-interesting-path # limit scope to that path
Run Code Online (Sandbox Code Playgroud)

实际上我更喜欢使用'git gui的内置mergetool集成(右键单击文件冲突).虽然这略有限制,所以请看上面我的小补丁,它允许你插入一个shell脚本,你可以在其中调用你喜欢的任何合并工具(我尝试了各种有时并行,因为它们引起了惊人的悲痛......但通常我被困在kdiff3 ..

当合并步骤正常(没有冲突)时,合并提交会自动完成; 否则,你解决冲突

git commit  # am usually doing this in the git gui as well.. again, lightning fast.
Run Code Online (Sandbox Code Playgroud)

最后阶段..请注意,到目前为止,我们只有本地提交,而不是与svn服务器交谈.除非您使用了--squash或其他技巧,否则您现在最终会得到一个图表,其中您的合并提交有2个父项:svn-mirror分支的提示.现在这是常见的问题:svn只能采用线性历史..所以'git-svn'通过删除第二个父(在上面的情况下为svn-branch-to-merge)简化了它.所以真正的合并跟踪是在svn方面走了......但是在这种情况下它很好.

如果你想要一种更安全/更清洁的方式,这就是我早期代码片段的用武之地:只需用--squash进行最后的合并.将之前的一个改编为此流程:

git checkout -b dcommit_helper_for_svnbranch my-svn-target-branch  # another local workbranch.. basically needed as svn branches (as any other remote branch) are read-only
git merge --squash my-merge-fun  
git commit 'nice merge summary' # single parent, straight from the fresh svn branch
git dcommit  # this will result in a 'svn commit' on the my-svn-target-branch
Run Code Online (Sandbox Code Playgroud)

哎呀,这已经太久了,太晚之前停下来..祝你好运.

  • +1为您的完整审查和自我回答 (2认同)