Git/Travailler avec Git local et un dépôt Subversion distant
Git permet de participer à de nombreux autres systèmes de contrôle de version, comme git-svn
ou git-cvsimport
.
SVN
modifierLa compatibilité entre Git et Subversion est assurée par git-svn
qui autorise un utilisateur à accéder et participer à un dépôt SVN. Les utilisateurs peuvent générer des patchs locaux pour les envoyer par liste de diffusion, ou soumettre leurs changements aux dépôts d'origine.
Premiers pas
modifierPour commencer à utiliser Git avec des projets sur des serveurs Subversion, il faut créer un dépôt local, et configurer git-svn
:
mkdir projet1
cd projet1
git svn init <URL du dépôt root> -T/chemin/du/tronc
git svn fetch -r <première révision>:HEAD
Le paramètre "première révision" peut être "1", mais pour gagner du temps il est possible de ne prendre que les 10 dernières révisions. svn info
indique alors ces révisions.
Généralement quand on travaille avec des dépôts Subversion, on communique l'URL du projet complète. Pour déterminer l'URL du dépôt racine :
git svn info <URL du dépôt root>
Une ligne du résultat indique le dépôt racine. Le chemin du tronc est simplement le reste de l'URL qui suit.
Il est possible de simplement donner à git-svn
l'URL complète du projet, mais cela peut stopper la possibilité de travailler sur des branches SVN.
Exemples
modifierObtenir Pywikipedia :
$ git svn init http://svn.wikimedia.org/svnroot/pywikipedia/trunk/pywikipedia/
Initialized empty Git repository in .../.git/
$ git svn fetch -r 1:HEAD
...
r370 = 318fb412e5d1f1136a92d079f3607ac23bde2c34 (refs/remotes/git-svn)
D treelang_all.py
D treelang.py
W: -empty_dir: treelang.py
W: -empty_dir: treelang_all.py
r371 = e8477f292b077f023e4cebad843e0d36d3765db8 (refs/remotes/git-svn)
D parsepopular.py
W: -empty_dir: parsepopular.py
r372 = 8803111b0411243af419868388fc8c7398e8ab9d (refs/remotes/git-svn)
D getlang.py
W: -empty_dir: getlang.py
r373 = ad935dd0472db28379809f150fcf53678630076c (refs/remotes/git-svn)
A splitwarning.py
...
Récupérer AWB (AutoWikiBrowser) :
$ git svn init svn://svn.code.sf.net/p/autowikibrowser/code/
Initialized empty Git repository in .../.git/
$ git svn fetch -r 1:HEAD
...
r15 = 086d4ff454a9ddfac92edb4013ec845f65e14ace (refs/remotes/git-svn)
M AWB/AWB/Main.cs
M AWB/WikiFunctions/WebControl.cs
r16 = 14f49de6b3c984bb8a87900e8be42a6576902a06 (refs/remotes/git-svn)
M AWB/AWB/ExitQuestion.Designer.cs
M AWB/WikiFunctions/GetLists.cs
M AWB/WikiFunctions/Tools.cs
r17 = 8b58f6e5b21c91f0819bea9bc9a8110c2cab540d (refs/remotes/git-svn)
M AWB/AWB/Main.Designer.cs
M AWB/AWB/Main.cs
M AWB/WikiFunctions/GetLists.cs
r18 = 51683925cedb8effb274fadd2417cc9b1f860e3c (refs/remotes/git-svn)
M AWB/AWB/specialFilter.Designer.cs
M AWB/AWB/specialFilter.cs
r19 = 712edb32a20d6d2ab4066acf056f14daa67a9d4b (refs/remotes/git-svn)
M AWB/WikiFunctions/WPEditor.cs
r20 = 3116588b52a8e27e1dc72d25b1981d181d6ba203 (refs/remotes/git-svn)
...
Cette opération de téléchargement peut prendre une heure.
Interagir avec le dépôt
modifierL'avantage de travailler avec Git sur des dépôts SVN est l'utilisation en local. Dans ce cas :
- Ne pas lancer
git pull
- Dans une branche mieux vaut éviter de lancer
git-svn dcommit
car les soumissions fusionnées ont tendance à embrouillergit-svn
. Par contre, combiner les changements avec ceux de Subversion en amont est équivalent àsvn update
:
git stash # cache les changements pour obtenir un arbre propre
git svn fetch # amène les derniers changements
git rebase trunk
git stash apply
La première et la dernière ligne ne sont pas nécessaires si l'arbre est propre.
Le git rebase trunk
laisse les soumissions locales au dessus du HEAD SVN[1].
Changements locaux
modifierPour éviter de propager des modifications locales indésirables (débogages, tests...), avec git svn dcommit
, sans les perdre peut passer par deux approches.
Premièrement, maintenir une branche locale pour chacune qui devra contenir des changements locaux. Par exemple faire un rebase
sur "branche1" au-dessus de "branche1-locale". Exemple :
git rebase trunk branche1-locale
git rebase branche1-locale branche1
Deux choix sont ensuite possibles, effectuer directement les changements sur la branche locale, ce qui est plus rapide que de les soumettre à la branche distante avant de les récupérer dans la locale. Ensuite il est possible d'utiliser git reset
[2] pour les retirer de la branche distante.
Comme une alternative à l'approche centrée recombinaison, il existe une méthode basée sur la fusion. Tout en conservant les changements sur une branche locale, mais sans avoir à conserver la branche au dessus de la branche locale par recombinaison.
C'est un avantage car :
- Sinon il y a plus à écrire[précision nécessaire].
- Historiquement, la recombinaison a souvent demandé de résoudre le même conflit deux fois, s'il survient pendant la première recombinaison.
Donc à la place des recombinaisons, on crée une nouvelle branche servant à la construction. Il faut la démarrer avec la soumission à tester. Ensuite git merge
fusionne la branche locale, apportant tous les changements dans un seul arbre. La raison de cette fusion dans une branche reconstruction est pour dissuader l'utilisation de git-svn dcommit
(qui soumettrait les tests indésirables sur le serveur).
Cette approche peut même rendre facultative la recombinaison quotidienne la branche avec le tronc. En cas de branches multiples, les recombinaisons permanentes peuvent s'avérer chronophages :
git checkout build
git reset --hard trunk # s'assurer de l'absence de changement important
git merge branche1 branche1-locale
La construction contient ensuite les changements du tronc, branche1 et branche1-locale !
Il est possible de conserver plusieurs branches locales dont une avec les tests. Cette approche peut être développée avec une branche par sujet dans un arbre :
git merge sujet1 sujet2 config debug...
Malheureusement, la fusion de cette pieuvre ne résout pas les conflits. Dans ce cas il faut appliquer les fusions une par une :
git merge sujet1
git merge sujet1
git merge local
...
Envoyer des changements en amont
modifierÉventuellement, pour soumettre au serveur des branches sujet avec un accès commit
, on peut lancer git-svn dcommit
. Cela prendra chaque soumission locale dans la branche courante et le soumettra à subversion. Par exemple avec trois soumissions locales, après dcommit
il y aura trois nouvelles soumissions dans subversion.
Sans accès commit
, le patch devra probablement être soumis via une liste de diffusion ou un logiciel de suivi de problèmes (bug tracker). Pour cela on peut utiliser git-format-patch. Par exemple pour trois soumissions locales :
git format-patch HEAD~3..
Le résultat sera trois fichiers en $PWD, 0001-commit-name.patch, 0002-commit-name.patch, et 0003-commit-name.patch, qui pourront être attachés à des emails ou joint à Bugzilla. Remarque : il existe git-send-email pour envoyer les emails directement :
git send-email *.patch
Si les séries de patchs ne sont pas dans l'ordre, voir git rebase -i
.