简体   繁体   English

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

[英]Using git-svn (or similar) *just* to help out with an svn merge?

Some complex subversion merges are coming up in my project: big branches that have been apart for a long time. 我的项目中出现了一些复杂的颠覆合并:长期分离的大分支。 Svn gives too many conflicts - and some of them seem spurious. Svn给出了太多的冲突 - 其中一些似乎是虚假的。


Given that git is praised for a superiour merge experience, Would it be any good to use git-svn just for the benefit of making the merge more manageable? 鉴于git被称赞为优秀的合并体验,使用git-svn 只是为了使合并更易于管理是否有用?


Can you recommend other alternatives (eg. svk , hgsvn ) to lessen the merge pain? 你能推荐其他替代品(例如svkhgsvn )来减轻合并疼痛吗?

Some conflicts are easy enough to resolve (eg java imports, whitespaces) - so I'm also wondering if there is any automated solutions for those. 一些冲突很容易解决(例如java导入,空格) - 所以我也想知道是否有任何自动解决方案。

A full switch to DVCS might happen in the future (some of us would love that), but not right now. 未来可能会发生完全切换到DVCS(我们中的一些人会喜欢),但现在不行。 (UPDATE: this isn't true any longer - the team switched fully recently and are happy about it). (更新:这不再是真的 - 团队最近完全切换并对此感到高兴)。

Thanks in advance. 提前致谢。

PS: there are posts that seem to be related (eg. git-svn merge 2 svn branches ) but they don't fully answer this question. PS:有些帖子似乎是相关的(例如git-svn合并2个svn分支 ),但他们没有完全回答这个问题。

Update: see my -novice- answer after going down (and up:) this road. 更新:看完我的-novice-回答后(和向上:)这条路。

Trying to answer my question: using git for svn merges seems promising. 试图回答我的问题:使用git进行svn合并似乎很有希望。

Update: it's not just promising, it's a great success. 更新:它不仅仅是有希望的,它取得了巨大的成功。 In short, Linus was right . 简而言之, Linus是对的

Just completed a huge merge of 2 svn branches that have been apart for 1.5 years; 刚刚完成了2个svn分支的巨大合并,这些分支已经分开了1。5年; 3k files were changed, got tons of conflicts in svn (~800 I think). 3k文件被更改,在svn中有大量冲突(我认为~800)。

I found git & git-svn a life saver: 我发现git&git-svn是一个救生员:

  • auto-conflict resolution: for a start, it gave a lot less conflicted files (~half I think) 自动冲突解决方案:首先,它提供了更少的冲突文件(我认为〜一半)
  • unbelievable performance 令人难以置信的表现
  • excellent repo/branching model , flexible workflows: easy experimentation with various approaches, such as chunk-by-chunk(in time) merge, always doing sanity checks(compile,etc); 出色的repo /分支模型 ,灵活的工作流程:使用各种方法轻松实验,例如chunk-by-chunk(及时)合并,始终进行健全性检查(编译等); whenever trouble hits: just backtrack. 每当遇到麻烦时:只需回溯。 You can always just take a step back when needed. 您可以随时在需要时退后一步。
  • usability, great tooling: 可用性,出色的工具:
    • git-log (and the underlying git-rev-parse options), nothing can be more powerful than this. git-log (以及底层的git-rev-parse选项),没有什么能比这更强大。 It's handy as well: -p gives you diffs in one go; 它的方便,以及: -p让你一次过的比较; in svn you get a log, then find the diff for that "revision-1:revision", or use clumsy UIs. 在svn中你得到一个日志,然后找到“revision-1:revision”的差异,或使用笨拙的UI。 Find when a string was added/removed into the repo, search multiple branches simultaneously 查找何时将字符串添加/删除到repo中,同时搜索多个分支
    • gitk : hugely useful for visualising branch histories, combined with great search capabilities. gitk :非常有用于可视化分支历史,并具有出色的搜索功能。 Haven't seen anything like this in other tools, especially not as fast as this. 在其他工具中没有看到这样的东西,特别是没有这么快。 Nevermind it's in Tk, it's just brilliant 没关系它在Tk,它很棒
    • git gui : works fine even if not the sexiest - great help for the novice to discover things git gui :即使不是最性感也能正常工作 - 对新手发现事物有很大的帮助
    • blame : a miracle. blame :一个奇迹。 Yes, it detects where the original segment comes from (copy&paste etc) 是的,它会检测原始片段的来源(复制和粘贴等)
    • mergetool : much more pleasant experience than kicking off the big svn merge which then stops everytime (ie. every 5 minutes) it runs into a conflict, press '(p)ostpone', than manually hunt for conflicted files later. mergetool :比开始大svn merge更令人愉快的经历,然后每次停止(即每5分钟)它会遇到冲突,按'(p)ostpone',而不是以后手动搜索冲突的文件。 Preferred a flavour of this integrated in git gui (needed a tiny patch for that). 优选的是一种集成在git gui的味道(需要一个小补丁 )。 Found integrating external diff tools better configurable than in svn . 发现集成外部差异工具比在svn更好地配置。
    • pluggable merge drivers and fine grained control of them 可插拔的合并驱动程序和对它们的细粒度控制
    • rebase allowed to filter out messier parts of the svn history rebase允许过滤掉svn历史的混乱部分
  • distribution: no need to come to the office when working on this, could pause & progress step-by-step on train/plane, etc.. 分配:在此工作时无需上台,可以在火车/飞机上一步一步地暂停和进步。
    • a USB drive with Unison made syncing work<->home a piece of cake Unison的USB驱动器同步工作< - >家里一块蛋糕
    • this wouldn't have been possible without git's crazy compression (5 years old project with 26k commits, tons of branches and binary files, trunk svn checkout: 1.9Gb => all of these in the full git repo: 1.4Gb!) 如果没有git的疯狂压缩,这是不可能的(5年的项目有26k提交,大量的分支和二进制文件,trunk svn checkout:1.9Gb =>所有这些在完整的git repo中:1.4Gb!)

So, this really can make the difference from a nightmare to joy - especially if you enjoy learning (which does take some effort in this case - I guess like learning a motorbike after a bicycle). 所以,这真的可以改变从噩梦到欢乐的区别 - 特别是如果你喜欢学习(在这种情况下需要付出一些努力 - 我想在骑自行车后学习摩托车)。

Even though I can't force everyone in the company to switch immediately - I really didn't intend to actually. 即使我不能强迫公司里的每个人立即切换 - 我真的不打算这样做。 Again, git-svn saves us by 'dipping the toe first' approach.. But seeing colleagues' reactions the switch might happen much before anyone expected:) 再一次, git-svn通过“先踩脚趾”的方法来拯救我们。但是看到同事的反应,切换可能会在任何人预期之前发生:)

I'd say- even if we forget about merges & commits, this stuff is already great as a read-only frontend for queries, visualisation, backups, etc.. 我会说 - 即使我们忘记了合并和提交,这些东西已经很好用作查询,可视化,备份等的只读前端。

Caveat: 警告:

"Do not dcommit Git merge commits to the Subversion repository. Subversion doesn't handle merges in the same way as Git, and this will cause problems. This means you should keep your Git development history linear (ie, no merging from other branches, just rebasing)." “不要将Git合并提交到Subversion存储库.Subversion不会像Git一样处理合并,这会导致问题。这意味着你应该保持你的Git开发历史是线性的(即,不要与其他分支合并,只是变基。)“ (last paragraph of http://learn.github.com/p/git-svn.html ) http://learn.github.com/p/git-svn.html的最后一段)

Another excellent source is the Pro Git book , section 'Switching Active Branches' basically says that the merge does work, but dcommit will only store the content of the merge, but the history will be compromised (which breaks subsequent merges), so you should drop the work branch after merge. 另一个很好的来源是Pro Git书 ,“切换活动分支”部分基本上说合并确实有效,但是dcommit只会存储合并的内容,但是历史会受到损害(这打破了后续的合并),所以你应该合并后删除工作分支。 Anyway it makes sense after all, and in practice it's easy to avoid traps here.. in svn, I found people do not usually re-merge anyway so this could only be seen as a step back if you come from git world in the first place. 无论如何它毕竟是有道理的,在实践中很容易避免陷阱在这里...在svn中,我发现人们通常不会重新合并,所以这只能被视为后退如果你来自第一个git世界地点。

Anyhow, the dcommit just worked for me. 无论如何,dcommit只对我有用。 I did it onto my own svn workbranch that I kept for this only, so avoided any extra conflicts that time. 我把它放在我自己的svn workbranch上,我只保留这个,所以避免任何额外的冲突。 However, I decided to do the final merge from this workbranch to the svn trunk in svn (after syncing up everything in git); 但是,我决定从这个workbranch到svn中的svn trunk进行最后的合并(在git中同步所有内容之后); --ignore-ancestry gave the best results there. --ignore-ancestry在那里取得了最好的成绩。

Update: as I found out later, the last few steps above (extra svn branch and merge--ignore-ancestry) is easily avoided by just keeping the branch you're dcomitting from linear. 更新:正如我后来发现的那样,上面的最后几个步骤(额外的svn分支和合并 - ignore-ancestry)很容易通过保持你从线性分支的分支来避免。 As Gabe says below, merge --squash just creates a simple stupid svn-friendly commit. 正如Gabe在下面所说, merge --squash只会创建一个简单的svn友好提交。 Just when ready with huge merge(s) on the my local branch (which might take days/weeks), I would now just: 就在我在当地分支机构准备好大量合并时(可能需要数天/周),我现在只是:

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

I know the merge tracking won't work great from the svn-side, until we switch fully. 我知道合并跟踪在svn端不会很好,直到我们完全切换。 I can't wait for that. 我等不及了。


UPDATE : @Kevin requested some more details on the whole process of merging svn branches.. There are lots articles, posts out there, but as a novice I found some of the confusing/misleading/out of date.. Anyhow, the way I do it these days (of course, stuck with git-svn after that merge affair; just as some newly infected colleagues).. 更新 :@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

Actually I preferred to use 'git gui's builtin mergetool integration (right click on file in conflict). 实际上我更喜欢使用'git gui的内置mergetool集成(右键单击文件冲突)。 That's slightly limited though,so see my little patch above, which allows you to plugin a shell script where you can invoke whatever mergetools you prefer (I tried a variety of them sometimes in parallel as they caused a surprising amount of grief.. but normally I'm stuck with kdiff3.. 虽然这略有限制,所以请看上面我的小补丁,它允许你插入一个shell脚本,你可以调用你喜欢的任何合并工具(我有时会尝试各种各样的并行,因为它们引起了惊人的悲痛......但通常我被困在kdiff3 ..

When a merge step goes fine (no conflict), a merge commit is done automatically; 当合并步骤正常(没有冲突)时,合并提交会自动完成; otherwise, you resolve conflicts then 否则,你解决冲突

git commit  # am usually doing this in the git gui as well.. again, lightning fast.

The last phase.. Note that so far we had only local commits, not talking to the svn server yet. 最后阶段..请注意,到目前为止,我们只有本地提交,而不是与svn服务器交谈。 Unless you've used --squash or other tricks, you now end up with a graph where your merge commit has 2 parents: the tips of your svn-mirror branches. 除非您使用了--squash或其他技巧,否则您现在最终会得到一个图表,其中您的合并提交有2个父项:svn-mirror分支的提示。 Now this is the usual gotcha: svn can only take linear history.. so 'git-svn' simplifies it by just dropping the second parent (svn-branch-to-merge in the above case).. so the real merge tracking is gone on the svn side..but otherwise it's fine in this case. 现在这是常见的问题:svn只能采用线性历史..所以'git-svn'通过删除第二个父(在上面的情况下为svn-branch-to-merge)简化了它。所以真正的合并跟踪是在svn方面走了......但是在这种情况下它很好。

If you want a safer/cleaner way, this is where my earlier snippet comes in: just do the final merge with --squash. 如果你想要一种更安全/更清洁的方式,这就是我早期代码片段的用武之地:只需用--squash进行最后的合并。 Adapted the earlier one to this flow: 将之前的一个改编为此流程:

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

oops, this is getting way too long, stopping before too late.. Good luck. 哎呀,这已经太久了,太晚之前停下来..祝你好运。

There are new tools available that fix many issues of git-svn and provide much better experience for using both Subversion and Git. 有一些新工具可以修复git-svn的许多问题,并为使用Subversion和Git提供更好的体验。

Among other things these tools fix some branching and merging problems. 除此之外,这些工具还解决了一些分支和合并问题。 Here is an overview: 这是一个概述:

  1. git-svn GIT-SVN

    From the documentation: 从文档:

    CAVEATS CAVEATS

    ... ...

    Running git merge or git pull is NOT recommended on a branch you plan to dcommit from. 不建议在您计划提交的分支上运行git merge或git pull。 Subversion does not represent merges in any reasonable or useful fashion; Subversion不以任何合理或有用的方式表示合并; so users using Subversion cannot see any merges you've made. 因此使用Subversion的用户无法看到您所做的任何合并。 Furthermore, if you merge or pull from a git branch that is a mirror of an SVN branch, dcommit may commit to the wrong branch. 此外,如果您从作为SVN分支镜像的git分支合并或拉出,则dcommit可能会提交到错误的分支。

    There are primarily three reasons not to dcommit merge commits: 不提交合并提交主要有三个原因:

    • git-svn doesn't automatically send svn:mergeinfo property for merged branches. git-svn不会自动为合并分支发送svn:mergeinfo属性。 As result Subversion is not able to track those merges performed by git. 结果Subversion无法跟踪git执行的那些合并。 This includes normal Git merges and cherry-picks. 这包括正常的Git合并和樱桃选择。

    • as git-svn does not convert svn:ignore, svn:eol-style and other SVN properties automatically, merge commit does not have corresponding metadata in Git. 由于git-svn不自动转换svn:ignore,svn:eol-style和其他SVN属性,因此合并提交在Git中没有相应的元数据。 As result, dcommit does not send these properties to SVN repository, so they get lost. 因此,dcommit不会将这些属性发送到SVN存储库,因此它们会丢失。

    • dcommit always sends changes to the branch referenced by a first parent of a merge commit. dcommit始终将更改发送到合并提交的第一个父级引用的分支。 Sometimes changes appear where user doesn't expect them. 有时,更改会出现在用户不期望的位置。

  2. SubGit SubGit

    SubGit is a Git-SVN bi-directional server-side mirror. SubGit是一个Git-SVN双向服务器端镜像。

    If one has local access to Subversion repository, one can install SubGit into it: 如果一个人可以本地访问Subversion存储库,可以在其中安装SubGit:

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

    At this moment SubGit converts Subversion repository into Git (it works in opposite direction as well) and installs SVN and Git hooks. 此时SubGit将Subversion存储库转换为Git(它也在相反的方向工作)并安装SVN和Git钩子。 As result Subversion and Git repositories are synchronized: every commit and push starts hooks that convert incoming modifications immediately. 结果Subversion和Git存储库是同步的:每次提交和推送都会启动挂钩,立即转换传入的修改。

    SubGit converts svn:ignore properties into .gitignore files, svn:eol-style and svn:mime-type properties to .gitattributes, so merge commits in Git retain this metadata. SubGit将svn:ignore属性转换为.gitignore文件,将svn:eol-style和svn:mime-type属性转换为.gitattributes,因此Git中的合并提交会保留此元数据。

    When one pushes merge commit, SubGit converts all the new commits into Subversion revisions. 当推送合并提交时,SubGit会将所有新提交转换为Subversion修订版。 It honors svn:mergeinfo property, so merge operation is properly tracked by SVN afterwards. 它尊重svn:mergeinfo属性,因此SVN之后会正确跟踪合并操作。

    Even if user pushes very complex Git history, SubGit converts all the commits keeping the merge tracking data valid. 即使用户推送非常复杂的Git历史记录,SubGit也会转换所有提交,使合并跟踪数据保持有效。 We once pushed the whole history of git.git repository at once and it was properly converted into SVN. 我们曾经立即推出了git.git存储库的整个历史记录,并将其正确转换为SVN。

    SubGit is a commercial product. SubGit是一种商业产品。 It is free for open-source and academic projects and also for projects with up to 10 committers. 它对于开源和学术项目以及最多10个提交者的项目是免费的。

    For more details please refer to SubGit documentation and git-svn comparison page. 有关更多详细信息,请参阅SubGit文档git-svn比较页面。

  3. SmartGit SmartGit

    SmartGit is a client-side alternative for git-svn. SmartGit是git-svn的客户端替代品。

    SmartGit also supports svn:ignore, svn:eol-style and svn:mime-type properties conversion. SmartGit还支持svn:ignore,svn:eol-style和svn:mime-type属性转换。 And it also sets svn:mergeinfo property for merge commits. 它还为合并提交设置了svn:mergeinfo属性。 It even updates necessary merge tracking data for cherry-pick commits. 它甚至为cherry-pick提交更新必要的合并跟踪数据。

    SmartGit is a commercial Git and Mercurial client. SmartGit是商业Git和Mercurial客户端。 It is free for non-commercial usage. 它可以免费用于非商业用途。

Full disclosure: I'm one of SubGit developers. 完全披露:我是SubGit开发人员之一。

I've just worked through this myself. 我自己刚刚解决了这个问题。 A simpler method is to pass git merge the --squash option, which will perform the merge without recording a merge commit, keeping the history linear so as not to confuse git-svn. 一个更简单的方法是传递git merge --squash选项,它将执行合并而不记录合并提交,保持历史线性,以免混淆git-svn。

My merge was also very large, and I had to set git config diff.renamelimit 0 so that git would correctly find all the renames. 我的合并也非常大,我不得不设置git config diff.renamelimit 0以便git能够正确找到所有重命名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM