Utiliser git-svn (ou similaire) * just* pour aider avec une fusion svn?

des fusions subversion complexes apparaissent dans mon projet: de grandes branches séparées depuis longtemps. Svn donne trop de conflits - et certains d'entre eux semblent fausses.


étant donné que git est loué pour une expérience de fusion supérieure, Serait-il utile d'utiliser git-svn juste pour l'avantage de rendre la fusion plus gérable?


Peut vous recommandez d'autres solutions (p. ex. svk , hgsvn ) pour atténuer la douleur de fusion?

certains conflits sont assez faciles à résoudre (E. g Java imports, whitespaces) - je me demande aussi s'il existe des solutions automatisées pour ceux-là.

un basculement complet vers les DVCS pourrait se produire dans le futur (certains d'entre nous aimeraient cela), mais pas maintenant. (Mise à jour: ce n'est plus vrai depuis longtemps - l'équipe a changé complètement récemment et sont heureux à ce sujet).

Merci d'avance.

PS: il y a des messages qui semblent être liés (par ex. git-svn merge 2 branches svn ) mais ils ne répondent pas entièrement à cette question.

mise à Jour: voir mon -novice - réponse après avoir descendu (et jusqu':) cette route.

26
demandé sur Community 2010-06-01 00:31:12

3 réponses

essayer de répondre à ma question: utiliser git pour svn merges semble prometteur.

mise à jour: ce n'est pas seulement prometteur, c'est un grand succès. En bref, Linus avait raison .

vient de compléter une énorme fusion de 2 branches svn qui sont séparées depuis 1,5 ans; les fichiers 3k ont été changés, ont eu des tonnes de conflits dans svn (~800 je pense).

j'ai trouvé git & git-svn un sauveur de vie:

  • auto-résolution de conflits: pour commencer, il a donné beaucoup moins de fichiers en conflit (~demi je crois)
  • une performance incroyable
  • excellent repo/branching model , flux de travail flexibles: expérimentation facile avec diverses approches, telles que la fusion de morceaux par morceaux(dans le temps), toujours en faisant des contrôles de santé mentale(compiler, etc); chaque fois que le problème frappe: juste revenir en arrière. Vous pouvez toujours prendre du recul au besoin.
  • la facilité d'utilisation, une grande outillage:
    • git-log (et les options sous-jacentes git-rev-parse ), rien ne peut être plus puissant que cela. C'est pratique aussi: -p vous donne des diffs en une seule fois; dans svn vous obtenez un log, puis trouvez la diff pour cette "révision-1:révision", ou utilisez des UIs maladroits. Trouver lorsqu'une chaîne de caractères a été ajouté/supprimé dans les pensions de titres, la recherche de multiples branches simultanément
    • gitk : extrêmement utile pour visualiser la branche histoires, combinée avec de grandes capacités de recherche. Je n'ai rien vu de Tel dans d'autres outils, surtout pas aussi vite que ça. Peu importe que ce soit dans Tk, c'est tout simplement génial
    • git gui : fonctionne bien, même si ce n'est pas le plus sexy-grande aide pour le novice de découvrir des choses
    • blame : un miracle. Oui, il détecte lorsque le segment initial vient (copier-coller, etc)
    • mergetool : une expérience bien plus agréable que le coup d'envoi de la grande svn merge qui s'arrête alors chaque fois (c.-à-d. toutes les 5 minutes) il se trouve dans un conflit, appuyez sur '(p)ostpone', que la chasse manuelle pour les fichiers en conflit plus tard. Préféré une saveur de ce intégré dans git gui (avait besoin d'un petit patch pour cela). Trouvé l'intégration des outils de diff externes mieux configurable que dans svn .
    • pilotes de fusion branchés et commande à grains fins de ceux-ci
    • rebase autorisé à filtrer les parties de messier de l'histoire de svn
  • distribution: pas besoin de venir au bureau lorsque vous travaillez sur ce, pourrait pause & progression étape par étape sur le train/avion, etc..
    • une clé USB avec l'Unisson fait de la synchronisation de travail<->la maison un morceau de gâteau
    • cela n'aurait pas été possible sans la compression folle de git (projet de 5 ans avec 26k commits, des tonnes de branches et de fichiers binaires, trunk svn checkout: 1.9 Gb => tous ceux-ci dans la pleine git repo: 1.4 Gb!)

ainsi, cela peut vraiment faire la différence d'un cauchemar à la joie - surtout si vous aimez apprendre (qui ne prend pas un certain effort dans ce cas - je suppose que l'apprentissage d'une moto après une bicyclette).

même si Je ne peux pas forcer tout le monde dans la compagnie à changer immédiatement - je vraiment n'ai pas l'intention de vous en fait. Encore une fois, git-svn nous sauve en" trempant le premier orteil " approche.. Mais en voyant les réactions de ses collègues, le changement pourrait se produire bien avant que l'on s'y attende:)

je dirais - même si nous oublions les fusions et les propagations, ce truc est déjà génial comme interface en lecture seule pour les requêtes, la visualisation, les sauvegardes, etc..

avertissement:

"Ne pas dcommit Git merge s'engage à Subversion référentiel. Subversion ne gère pas les fusions de la même façon comme Git, et cela va causer des problèmes. Cela signifie que vous devriez garder votre Git histoire du développement linéaire (c.-à-d. non la fusion d'autres branches, juste changement d'année de base)." (dernier paragraphe de http://learn.github.com/p/git-svn.html )

une autre excellente source est le Pro Git book , section "Commutation Branches actives" essentiellement dit que la la fusion fonctionne, mais dcommit ne stockera que le contenu de la fusion, mais l'histoire sera compromise (ce qui casse les fusions subséquentes), donc vous devriez laisser tomber la branche de travail après la fusion. De toute façon il est logique après tout, et, dans la pratique, il est facile d'éviter les pièges ici.. en svn, j'ai découvert que les gens ne fusionnent généralement pas de toute façon, donc cela ne peut être considéré comme un pas en arrière que si vous venez de git world en premier lieu.

quoi qu'il en soit, le dsommit vient de travailler pour moi. Je l'ai fait sur mon propre SVN workbranch que j'ai gardé pour cela seulement, de sorte à éviter tout conflit supplémentaire cette fois. Cependant, j'ai décidé de faire la fusion finale de cette chaîne de travail vers le tronc svn dans svn (après avoir synchronisé tout dans git); --ignore-ancestry a donné les meilleurs résultats là-bas.

mise à jour: comme je l'ai découvert plus tard, les dernières étapes ci-dessus (extra SVN branch et merge--ignore-ancestry) sont facilement évitées en gardant simplement la branche que vous choisissez de linéaire. Comme dit Gabe ci-dessous, merge --squash crée simplement un simple SVN-friendly commit. Juste au moment où je suis prêt avec une énorme Fusion(s) sur ma branche locale( ce qui pourrait prendre des jours/semaines), je voudrais maintenant juste:

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

je sais que le tracking de fusion ne fonctionnera pas très bien du côté svn, jusqu'à ce que nous commutons complètement. Je ne peux pas attendre pour que.


mise à jour : @Kevin demande plus de détails sur l'ensemble du processus de fusion des branches svn.. Il ya beaucoup d'articles, les messages là-bas, mais en tant que novice j'ai trouvé certains de la confuse/trompeuse/périmée.. Quoi qu'il en soit, la façon dont je le fais ces jours-ci (bien sûr, coincé avec git-svn après cette affaire de fusion; tout comme certains collègues nouvellement infectés)..

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

en fait, j'ai préféré utiliser 'git gui' builtin mergetool integration (clic droit sur le fichier en conflit). C'est un peu limité cependant,alors voyez mon petit patch ci-dessus, qui vous permet d'ajouter un script shell là où vous pouvez invoquer les outils de fusion que vous préférez (j'ai essayé une variété d'entre eux parfois en parallèle car ils ont causé une quantité surprenante de chagrin.. mais normalement, je suis coincé avec kdiff3..

quand une étape de fusion se passe bien (pas de conflit), une propagation de fusion est faite automatiquement; sinon, vous résolvez les conflits alors

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

la dernière phase.. Notez que jusqu'à présent nous n'avions que des propagations locales, pas encore parlé au serveur svn. Sauf si vous avez utilisé -- squash ou autres astuces, vous finissez maintenant avec un graphique où votre commit de fusion a 2 parents: les bouts de vos branches SVN-mirror. Voici l'habituel gotcha: svn ne peut prendre que l'histoire linéaire.. donc git-svn " simplifie il en déposant le second parent (svn-direction-de-la fusion dans le cas ci-dessus).. donc le vrai tracking de fusion est parti du côté svn..mais sinon c'est bien dans ce cas.

si vous voulez un moyen plus sûr/plus propre, c'est ici que mon plus ancien extrait vient en: fais juste la fusion finale avec ... squash. Adapté le précédent à ce flux:

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

oups, ça devient trop longue, s'arrêter avant de trop tard.. Bonne chance.

33
répondu inger 2011-02-18 19:26:43

je viens de m'en occuper moi-même. Une méthode plus simple est de passer git merge l'option --squash , qui effectuera la fusion sans enregistrer une commit de fusion, en gardant l'histoire linéaire afin de ne pas confondre git-svn.

ma fusion était aussi très grande, et j'ai dû mettre git config diff.renamelimit 0 pour que git trouve correctement tous les noms.

3
répondu Gabe Moothart 2017-05-23 12:14:28

il y a de nouveaux outils disponibles qui corrigent de nombreux problèmes de git-svn et offrent une bien meilleure expérience pour utiliser à la fois Subversion et git.

entre autres ces outils résolvent quelques problèmes de branchement et de fusion. Voici un aperçu:

  1. git-svn

    de la documentation:

    CAVEATS

    ...

    Lancer git merge ou git pull n'est pas recommandé sur une branche à partir de laquelle vous prévoyez dcommit. Subversion ne représente pas les fusions d'une manière raisonnable ou utile; les utilisateurs qui utilisent Subversion ne peuvent donc pas voir les fusions que vous avez faites. De plus, si vous fusionnez ou tirez d'une branche git qui est un miroir D'une branche SVN, dcommit peut s'engager dans la mauvaise branche.

    il y a principalement trois raisons de ne pas dc commit merge commits:

    • git-svn n'envoie pas automatiquement la propriété svn:mergeinfo pour les branches fusionnées. Par conséquent, Subversion n'est pas en mesure de suivre les fusions effectuées par git. Cela inclut les fusionnements de gitans et de cerisiers.

    • comme git-svn ne convertit pas svn:ignore, svn:eol-style et d'autres propriétés SVN automatiquement, merge commit n'a pas de métadonnées correspondantes dans Git. Par conséquent, dcommit n'envoie pas ces propriétés au dépôt SVN, se perdre.

    • ddcommit envoie toujours des modifications à la branche référencée par un premier parent d'une commit de fusion. Parfois des changements apparaissent là où l'utilisateur ne s'y attend pas.

  2. SubGit

    SubGit est un Git-SVN bi-directionnelle côté serveur miroir.

    si vous avez un accès local au dépôt Subversion, vous pouvez installez SubGit en elle:

    $ 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
    

    actuellement SubGit convertit le dépôt Subversion en Git (il fonctionne également dans la direction opposée) et installe SVN et git hooks. Par conséquent, les dépôts Subversion et Git sont synchronisés: chaque procédure de propagation et d'impulsion démarre des hooks qui convertissent immédiatement les modifications entrantes.

    sous-Git convertit svn: ignore properties into .gitignore fichiers svn:eol-style et svn:mime-type de propriétés .gitattributes, de sorte de fusion s'engage dans Git conserver ces métadonnées.

    Lorsqu'on pousse la commande merge commit, SubGit convertit toutes les nouvelles propagations en révisions Subversion. Il honore la propriété svn:mergeinfo, donc l'opération de fusion est correctement suivie par SVN après.

    même si l'utilisateur pousse l'historique Git très complexe, SubGit convertit toutes les propagations en gardant les données de suivi de fusion valides. Nous avons une fois poussé toute l'histoire de git.dépôt git à la fois et il a été correctement converti en SVN.

    Le sous-vêtement

    est un produit commercial. Il est gratuit pour les projets open-source et académiques ainsi que pour les projets avec jusqu'à 10 committers.

    pour plus de détails, veuillez vous reporter à la page de comparaison sous-Git documentation et git-svn .

  3. SmartGit

    SmartGit est une alternative côté client pour git-svn.

    SmartGit supporte également la conversion des propriétés svn:ignore, svn:eol-style et svn:mime-type. Et il définit également la propriété svn:mergeinfo pour merge commits. Il met même à jour les données de suivi de fusion nécessaires pour cherry-pick commits.

    SmartGit est un client commercial Git et Mercurial. Il est gratuit pour les non-utilisation commerciale.

divulgation Complète: je suis l'un de SubGit développeurs.

3
répondu vadishev 2012-10-06 02:04:56