Une solution simple : Supprimer la branche "travail" après la fusion
Réponse courte : Vous pouvez utiliser git comme vous le souhaitez (voir ci-dessous pour un flux de travail simple), y compris la fusion. Assurez-vous simplement de suivre chaque ' travail de fusion git avec git branch -d work ' pour supprimer la branche de travail temporaire.
Explication du contexte : Le problème de la fusion/du commit est que chaque fois que vous "git svn dcommit" une branche, l'historique de fusion de cette branche est "aplati" : git oublie toutes les opérations de fusion qui ont été effectuées dans cette branche : Seul le contenu du fichier est préservé, mais le fait que ce contenu provenait (partiellement) d'une autre branche spécifique est perdu. Voir : Pourquoi git svn dcommit perd-il l'historique des commits de fusion pour les branches locales ?
(Note : il n'y a pas grand chose que git-svn puisse faire à ce sujet : svn ne comprend tout simplement pas les fusions git, beaucoup plus puissantes. Ainsi, à l'intérieur du dépôt svn, cette information de fusion ne peut être représentée d'aucune manière).
Mais c'est le ensemble du site problème. Si vous supprimez la branche 'work' après qu'elle ait été fusionnée dans la branche 'master', votre dépôt git est 100% propre et ressemble exactement à votre dépôt svn.
Mon flux de travail : Bien sûr, j'ai d'abord cloné le dépôt svn distant dans un dépôt git local (cela peut prendre un certain temps) :
$> git svn clone <svn-repository-url> <local-directory>
Tout le travail se fait alors dans le "local-directory". Lorsque j'ai besoin d'obtenir des mises à jour du serveur (comme 'svn update'), je le fais :
$> git checkout master
$> git svn rebase
Je fais tout mon travail de développement dans une branche séparée 'work' qui est créée comme ceci :
$> git checkout -b work
Bien sûr, vous pouvez créer autant de branches que vous le souhaitez pour votre travail et fusionner et rebaser entre elles comme vous le souhaitez (il suffit de les supprimer lorsque vous en avez fini avec elles --- comme indiqué ci-dessous). Dans mon travail normal, je commets très fréquemment :
$> git commit -am '-- finished a little piece of work'
L'étape suivante (git rebase -i) est optionnelle --- il s'agit juste de nettoyer l'historique avant de l'archiver sur svn : Une fois que j'ai atteint une étape stable que je veux partager avec d'autres, je réécris l'historique de cette branche 'travail' et nettoie les messages de commit (les autres développeurs n'ont pas besoin de voir toutes les petites étapes et erreurs que j'ai faites en chemin --- juste le résultat). Pour cela, je fais
$> git log
et copier le hash sha-1 du dernier commit qui est en direct dans le dépôt svn (comme indiqué par un git-svn-id). Puis j'appelle
$> git rebase -i 74e4068360e34b2ccf0c5869703af458cde0cdcb
Il suffit de coller le hachage sha-1 de notre dernier commit svn au lieu du mien. Vous pouvez lire la documentation avec 'git help rebase' pour les détails. En bref : cette commande ouvre d'abord un éditeur présentant vos commits ----. Changez simplement 'pick' en 'squash' pour tous les commits que vous voulez écraser avec les commits précédents. Bien sûr, la première ligne doit rester un 'pick'. De cette façon, vous pouvez condenser vos nombreux petits commits en une ou plusieurs unités significatives. Sauvegardez et quittez l'éditeur. Vous obtiendrez un autre éditeur vous demandant de réécrire les messages du journal de commit.
En bref : après avoir terminé le "piratage du code", je masse ma branche "travail" jusqu'à ce qu'elle ressemble à ce que je veux présenter aux autres programmeurs (ou à ce que je veux voir dans quelques semaines lorsque je consulterai l'historique).
Afin de pousser les changements vers le dépôt svn, je fais :
$> git checkout master
$> git svn rebase
Maintenant nous sommes de retour à l'ancienne branche 'master' mise à jour avec tous les changements qui ont eu lieu entre-temps dans le dépôt svn (vos nouveaux changements sont cachés dans la branche 'work').
Si certaines modifications risquent d'entrer en conflit avec les modifications de votre nouveau "travail", vous devez les résoudre localement avant de pouvoir pousser votre nouveau travail (voir les détails plus loin). Ensuite, nous pouvons pousser nos changements vers 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
Note 1 : La commande 'git branch -d work' est assez sûre : Elle vous permet uniquement de supprimer les branches dont vous n'avez plus besoin (car elles sont déjà fusionnées dans votre branche actuelle). Si vous exécutez cette commande par erreur avant de fusionner votre travail avec la branche 'master', vous obtenez un message d'erreur.
Note 2 : Assurez-vous de supprimer votre branche avec 'git branch -d work'. entre fusion et dcommit : Si vous essayez de supprimer la branche après dcommit, vous obtenez un message d'erreur : Lorsque vous faites 'git svn dcommit', git oublie que votre branche a été fusionnée avec 'master'. Vous devez la supprimer avec 'git branch -D work' qui ne fait pas le contrôle de sécurité.
Maintenant, je crée immédiatement une nouvelle branche "travail" pour éviter de pirater accidentellement la branche "master" :
$> git checkout -b work
$> git branch # show my branches:
master
* work
Intégrer votre "travail" avec les changements sur svn : Voici ce que je fais lorsque 'git svn rebase' révèle que d'autres personnes ont modifié le dépôt svn pendant que je travaillais sur ma branche 'travail' :
$> 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
Des solutions plus puissantes existent : Le flux de travail présenté est simpliste : il n'utilise les pouvoirs de git qu'à chaque tour de " update/hack/dcommit " --- mais laisse l'historique du projet à long terme tout aussi linéaire que le dépôt svn. Cela convient si vous voulez simplement commencer à utiliser les fusions git par petites étapes dans un projet svn hérité.
Lorsque vous serez plus familier avec la fusion git, n'hésitez pas à explorer d'autres flux de travail : Si vous savez ce que vous faites, vous puede mélanger les fusions git avec les fusions svn ( Utiliser git-svn (ou similaire) juste pour aider à la fusion svn ? )