Projet

Général

Profil

GitBonnesPratiques » Historique » Version 40

Daniel Dehennin, 05/12/2011 10:48
Introduction et affichage des commandes

1 40 Daniel Dehennin
{{toc}}
2 1 Redmine Admin
3 40 Daniel Dehennin
h1. Les bonnes pratiques c’est quoi ?
4 1 Redmine Admin
5 40 Daniel Dehennin
Ce document n’est pas une référence git, nous n’allons pas réécrire le
6 40 Daniel Dehennin
"progit book":http://progit.org/book/fr, ni les autres références disponibles sur Internet.
7 1 Redmine Admin
8 40 Daniel Dehennin
Nous allons partir du principe qu’un minimum de connaissance de l’outil git est acquis, notamment 
9 40 Daniel Dehennin
le "Démarrage rapide":http://progit.org/book/fr/ch1-0.html du livre "progit book":http://progit.org/book/fr.
10 1 Redmine Admin
11 40 Daniel Dehennin
Nous allons essayer de décrire ici une méthodologie de travail basée sur le
12 40 Daniel Dehennin
système de gestion de version décentralisé "git":https://fr.wikipedia.org/wiki/Git avec les objectifs suivants :
13 1 Redmine Admin
14 40 Daniel Dehennin
* Communiquer entre développeur
15 40 Daniel Dehennin
* S’y retrouver dans ses développements, ou comment gérer des ajouts fonctionnels et des corrections de bug en parallèle
16 40 Daniel Dehennin
* Publier des modifications clairement identifiables et analysables, par des humains et des outils de tests automatiques
17 35 Daniel Dehennin
18 35 Daniel Dehennin
Ce document ne représente en rien _LA_ bonne méthode de travail, il
19 40 Daniel Dehennin
s’agit juste d’une façon de faire, appuyée par l’expérience d’autres personnes que l’on trouve un peu
20 35 Daniel Dehennin
partout sur Internet.
21 35 Daniel Dehennin
22 1 Redmine Admin
Il est tout à fait possible de trouver autant, voir plus, de références
23 14 Klaas TJEBBES
prônant un point de vue opposé ou orthogonal au mien.
24 14 Klaas TJEBBES
25 35 Daniel Dehennin
26 1 Redmine Admin
h1. De la méthode agile
27 35 Daniel Dehennin
28 35 Daniel Dehennin
Comme il est défini dans le "manifeste agile":https://fr.wikipedia.org/wiki/Manifeste_agile#Les_4_valeurs, la première valeur est
29 1 Redmine Admin
« Les individus et leurs interactions ».
30 35 Daniel Dehennin
31 35 Daniel Dehennin
Afin de travailler correctement en équipe, il faut communiquer, et
32 35 Daniel Dehennin
l’outil de gestion de version "git":https://fr.wikipedia.org/wiki/Git, utilisé à EOLE, peut-être un excellent
33 23 Redmine Admin
outil de communication.
34 23 Redmine Admin
35 35 Daniel Dehennin
36 23 Redmine Admin
h1. De l’écriture des "ChangeLog":https://fr.wikipedia.org/wiki/ChangeLog
37 35 Daniel Dehennin
38 35 Daniel Dehennin
Afin de communiquer avec les autres membres d’une équipe sur le
39 35 Daniel Dehennin
travail que chacun effectue, l’écriture d’un ChangeLog, ou plus
40 35 Daniel Dehennin
précisément d’un « commit message » dans la littérature en anglaise
41 35 Daniel Dehennin
(qui pourrait être traduit par « message de consignation ») se doit
42 1 Redmine Admin
d’être fait correctement(sic).
43 35 Daniel Dehennin
44 23 Redmine Admin
Que penser d’un message comme « "typo":http://dev-eole.ac-dijon.fr/projects/eole-sso/repository/revisions/f2e5c52482c896b84e57333ba61654286b856f02 » ou encore « "correction d'une coquille":http://dev-eole.ac-dijon.fr/projects/cdc/repository/revisions/0dc6d59ca9c5294790ae1ebe0b035d8a3296ed22 » ?
45 35 Daniel Dehennin
46 1 Redmine Admin
Nous pouvons établir une règle simple et souple, par exemple :
47 35 Daniel Dehennin
48 23 Redmine Admin
Un message de commit comprend :
49 35 Daniel Dehennin
50 23 Redmine Admin
* Une première ligne résumant le pourquoi du patch ;
51 35 Daniel Dehennin
52 35 Daniel Dehennin
* Une description longue optionnelle permettant d’expliciter le
53 1 Redmine Admin
  contexte du résumé donné en première ligne ;
54 35 Daniel Dehennin
55 34 Bruno Boiget
* Une liste de fichier et leur modification.
56 35 Daniel Dehennin
57 35 Daniel Dehennin
Une ligne vide sépare les différentes parties : la première est
58 23 Redmine Admin
obligatoire et la troisième est optionnelle pour les changements triviaux
59 35 Daniel Dehennin
60 14 Klaas TJEBBES
Par exemple :
61 1 Redmine Admin
62 35 Daniel Dehennin
<pre>
63 1 Redmine Admin
  Le répertoire /usr/share/eole/noyau/ est nécessaire (Fixes: #2405).
64 35 Daniel Dehennin
65 1 Redmine Admin
  * debian/dirs: Création du répertoire.
66 1 Redmine Admin
</pre>
67 1 Redmine Admin
68 35 Daniel Dehennin
<pre>
69 35 Daniel Dehennin
  Simplification de la gestion des noyaux (ref: #2406).
70 35 Daniel Dehennin
  
71 35 Daniel Dehennin
  * creole/fonctionseole.py: Suppression du code effectué par
72 35 Daniel Dehennin
    eole-kernel-version depuis sa version 2.3-eole37~2.
73 1 Redmine Admin
    Renommage de la variable 'boot_ok' en 'need_boot'.
74 1 Redmine Admin
</pre>
75 35 Daniel Dehennin
76 1 Redmine Admin
Cela impose la règle suivante :
77 35 Daniel Dehennin
78 1 Redmine Admin
« Ne jamais utiliser l’option "-m" de la commande "git commit" »
79 1 Redmine Admin
80 35 Daniel Dehennin
81 1 Redmine Admin
h1. De la cohérence de l’histoire du monde
82 35 Daniel Dehennin
83 35 Daniel Dehennin
Un système de gestion de version permet avant tout de conserver un
84 14 Klaas TJEBBES
livre d’histoire d’un projet.
85 35 Daniel Dehennin
86 35 Daniel Dehennin
Dans les premiers systèmes de gestion de version, cette histoire était
87 35 Daniel Dehennin
centralisée. Il fallait avoir le droit d’écrire dans le « livre des
88 35 Daniel Dehennin
comptes et légendes » afin d’y ajouter un morceau, impossible donc de
89 1 Redmine Admin
réécrire l’histoire sans être tout puissant sur le registre.
90 35 Daniel Dehennin
91 35 Daniel Dehennin
Grâce aux systèmes décentralisés comme "git":https://fr.wikipedia.org/wiki/Git, tout le monde peut avoir
92 35 Daniel Dehennin
une copie privée de l’histoire publique d’un projet, pour cela il
93 1 Redmine Admin
suffit de « cloner » l’histoire originale :
94 1 Redmine Admin
95 35 Daniel Dehennin
<pre>
96 14 Klaas TJEBBES
  moi@work:~/src$ git clone git://far-far.away.example.net/bidule.git
97 14 Klaas TJEBBES
</pre>
98 35 Daniel Dehennin
99 35 Daniel Dehennin
À partir de là il est possible de vouloir y ajouter ses propres
100 1 Redmine Admin
morceaux, et cela sans rien demander à personne.
101 35 Daniel Dehennin
102 35 Daniel Dehennin
On modifie le projet et on consigne les nouveaux événements dans
103 35 Daniel Dehennin
notre copie locale de l’histoire du projet :
104 1 Redmine Admin
105 35 Daniel Dehennin
<pre>
106 35 Daniel Dehennin
  moi@work:~/src/bidule(master)$ $EDITOR src/bidule.c # On modifie un fichier du projet
107 35 Daniel Dehennin
  moi@work:~/src/bidule(master)$ git add src/bidule.c # On ajoute un événement à enregistrer dans le livre d’histoire
108 1 Redmine Admin
  moi@work:~/src/bidule(master)$ git commit # On consigne ce nouvel événement
109 1 Redmine Admin
</pre>
110 35 Daniel Dehennin
111 35 Daniel Dehennin
Mais l’histoire, c’est un sujet sensible. On ne badine pas avec
112 1 Redmine Admin
l’histoire et on ne la réécrit sous aucun prétexte.
113 35 Daniel Dehennin
114 35 Daniel Dehennin
Peu importe si la vérité est ailleurs, l’important c’est que tout le
115 1 Redmine Admin
monde soit d’accord sur la même version des faits.
116 35 Daniel Dehennin
117 35 Daniel Dehennin
Si un plaisantin modifie l’histoire et la publie à tout vent, il y
118 17 Gérald Schwartzmann
aura conflit.
119 35 Daniel Dehennin
120 1 Redmine Admin
Nous allons donc édicter la règle suivante :
121 35 Daniel Dehennin
122 16 Gaston TJEBBES
« On ne réécrit pas l’histoire connue »
123 35 Daniel Dehennin
124 35 Daniel Dehennin
Cela sous entend donc que nous pouvons réécrire comme il nous plaît
125 35 Daniel Dehennin
toute l’histoire qui nous est privée, c’est à dire inconnue de tous
126 1 Redmine Admin
les autres.
127 35 Daniel Dehennin
128 1 Redmine Admin
Mais dès qu’un événement est rendu public, ça n'est plus possible.
129 8 Gaston TJEBBES
130 35 Daniel Dehennin
131 8 Gaston TJEBBES
h1. Trop de pull, c’est trop chaud !
132 35 Daniel Dehennin
133 35 Daniel Dehennin
Que se passe-t-il si un jour nous souhaitons apprendre les nouvelles
134 8 Gaston TJEBBES
histoires de par le monde ?
135 35 Daniel Dehennin
136 35 Daniel Dehennin
Que ce passe-t-il si un jour nous souhaitons partager nos petites
137 1 Redmine Admin
histoires avec le reste du monde ?
138 35 Daniel Dehennin
139 35 Daniel Dehennin
La plupart du temps, la réponse donnée à ces questions commence par
140 1 Redmine Admin
quelque chose comme « fais-toi donc un pull ».
141 35 Daniel Dehennin
142 11 Gaston TJEBBES
Cela se traduit, en terme git, par :
143 1 Redmine Admin
144 35 Daniel Dehennin
<pre>
145 1 Redmine Admin
  moi@work:~/src/bidule(master)$ git pull
146 1 Redmine Admin
</pre>
147 35 Daniel Dehennin
148 1 Redmine Admin
Cela est strictement équivalent aux deux commandes suivantes :
149 1 Redmine Admin
150 35 Daniel Dehennin
<pre>
151 35 Daniel Dehennin
  moi@work:~/src/bidule(master)$ git fetch origin
152 1 Redmine Admin
  moi@work:~/src/bidule(master)$ git merge origin/master
153 1 Redmine Admin
</pre>
154 35 Daniel Dehennin
155 35 Daniel Dehennin
Mais il existe quelques soucis avec cette méthode, la première étant
156 29 Joël Cuissinat
« qu’une histoire entre en conflit avec l’une des vôtres ».
157 35 Daniel Dehennin
158 35 Daniel Dehennin
Un autre problème est que cette méthode « mélange » littéralement
159 35 Daniel Dehennin
l’histoire publique avec vos histoires privées, même s’il n’y a pas de
160 35 Daniel Dehennin
conflit, il peut-être difficile de savoir si le résultat aura un sens
161 1 Redmine Admin
ou non.
162 35 Daniel Dehennin
163 35 Daniel Dehennin
Dans git, chaque commit a une généalogie, le parent du commit que je
164 1 Redmine Admin
m’apprête à faire est le dernier commit enregistré dans le dépôt.
165 35 Daniel Dehennin
166 35 Daniel Dehennin
Lors d’un pull sur un dépôt contenant des modifications, git créé un
167 35 Daniel Dehennin
commit ayant deux parents dont le seul but est de mélanger la
168 21 Joël Cuissinat
généalogie.
169 35 Daniel Dehennin
170 37 Daniel Dehennin
Il est donc préférable d’utiliser la méthode décomposée en deux
171 37 Daniel Dehennin
commandes.
172 37 Daniel Dehennin
173 37 Daniel Dehennin
Cela permet de vérifier au préalable si des changements
174 37 Daniel Dehennin
sont à intégrer, et lesquels, avec les commandes suivantes :
175 37 Daniel Dehennin
176 37 Daniel Dehennin
* ChangeLog des différences
177 38 Daniel Dehennin
<pre>
178 37 Daniel Dehennin
  moi@work:~/src/bidule(master)$ git log master..origin/master
179 37 Daniel Dehennin
</pre>
180 37 Daniel Dehennin
* Liste des fichies modifiés
181 38 Daniel Dehennin
<pre>
182 37 Daniel Dehennin
  moi@work:~/src/bidule(master)$ git diff --stat master..origin/master
183 37 Daniel Dehennin
</pre>
184 37 Daniel Dehennin
* Modification du code
185 38 Daniel Dehennin
<pre>
186 37 Daniel Dehennin
  moi@work:~/src/bidule(master)$ git diff master..origin/master
187 21 Joël Cuissinat
</pre>
188 35 Daniel Dehennin
189 21 Joël Cuissinat
Mais cela n’empêche nullement :
190 35 Daniel Dehennin
191 35 Daniel Dehennin
* D’être potentiellement désastreux : chaque « fusion » (merge) et
192 35 Daniel Dehennin
  « consignation » de « fusion » (merge commit) sont à la charge de
193 21 Joël Cuissinat
  chaque développeur ;
194 35 Daniel Dehennin
195 35 Daniel Dehennin
* Votre histoire devient illisible. Elle intègre tout un tas de
196 21 Joël Cuissinat
  « fusion » inexplicables ;
197 35 Daniel Dehennin
198 35 Daniel Dehennin
* Retrouver à quel moment précis et quel modification a entraîné un
199 35 Daniel Dehennin
  changement de comportement devient impossible du fait des
200 1 Redmine Admin
  « fusions »
201 1 Redmine Admin
202 1 Redmine Admin
Tout mélanger dans la même branche, qui devient alors un tronc, pose
203 1 Redmine Admin
des soucis quant à la lecture de l’histoire du projet.
204 21 Joël Cuissinat
205 21 Joël Cuissinat
206 35 Daniel Dehennin
207 21 Joël Cuissinat
h1. Pour s’y retrouver, il faut s’accrocher aux branches
208 35 Daniel Dehennin
209 35 Daniel Dehennin
Une branche est une ligne d’histoire divergente d’un projet, leur
210 1 Redmine Admin
utilisations dans git est très simple et légère.
211 35 Daniel Dehennin
212 1 Redmine Admin
La création d’une branche peut se faire de deux façons :
213 35 Daniel Dehennin
214 35 Daniel Dehennin
# Créer une branche que j’utiliserais plus tard :
215 40 Daniel Dehennin
<pre>
216 40 Daniel Dehennin
  moi@work:~/src/projet(master)$ git branch mabranche
217 40 Daniel Dehennin
  moi@work:~/src/projet(master)$ # on commit dans la branche « master »
218 40 Daniel Dehennin
</pre>
219 35 Daniel Dehennin
# Créer une branche et commencer à travailler dedans :
220 40 Daniel Dehennin
<pre>
221 40 Daniel Dehennin
  moi@work:~/src/projet(master)$ git checkout -b mabranche
222 40 Daniel Dehennin
  moi@work:~/src/projet(mabranche)$ # on commit dans la branche « mabranche »
223 40 Daniel Dehennin
</pre>
224 35 Daniel Dehennin
225 35 Daniel Dehennin
Chacune de ces commandes permet de définir, en dernier argument, le
226 1 Redmine Admin
point de départ de la nouvelle branche.
227 35 Daniel Dehennin
228 1 Redmine Admin
Par défaut ce point de départ est le dernier commit de la branche courante.
229 35 Daniel Dehennin
230 1 Redmine Admin
Tout les commit effectués sur cette branche sont localisés à cette branche.
231 35 Daniel Dehennin
232 1 Redmine Admin
Cela permet de se focaliser sur une activité :
233 35 Daniel Dehennin
234 1 Redmine Admin
* Sans risquer d’impacter la vision que les autres ont de l’histoire ;
235 35 Daniel Dehennin
236 1 Redmine Admin
* Sans se soucier de ce qui peut arriver sur les autres branches ;
237 35 Daniel Dehennin
238 35 Daniel Dehennin
* Sans fusionner les modifications de la branche principale dans la
239 1 Redmine Admin
  branche courante.
240 35 Daniel Dehennin
241 35 Daniel Dehennin
Il faut travailler ensuite à intégrer cette nouvelle histoire à la
242 1 Redmine Admin
ligne principale.
243 35 Daniel Dehennin
244 35 Daniel Dehennin
h2. Les voies du temps sont interpénétrables
245 35 Daniel Dehennin
246 35 Daniel Dehennin
C’est le principe utilisé par le pull, ce qui est nommé dans la
247 35 Daniel Dehennin
littérature le « merge workflow ».
248 36 Daniel Dehennin
249 35 Daniel Dehennin
Ce qui est fait lors d’un @git pull@ entre une branche locale et une
250 35 Daniel Dehennin
branche sur un dépôt distant, « remote » en jargon git, est applicable
251 35 Daniel Dehennin
entre deux branches d’un dépôt local.
252 35 Daniel Dehennin
253 35 Daniel Dehennin
En pratique, on se positionne sur la branche qui doit intégrer les
254 35 Daniel Dehennin
modifications d’une autre, par exemple une branche publique, et on
255 35 Daniel Dehennin
fusionne la branche privée de développement dans cette
256 35 Daniel Dehennin
branche publique :
257 1 Redmine Admin
258 35 Daniel Dehennin
<pre>
259 1 Redmine Admin
  moi@work:~/src/projet(master)$ git merge mabranche
260 1 Redmine Admin
</pre>
261 36 Daniel Dehennin
262 1 Redmine Admin
Pour ensuite publier ces modifications par @git push@.
263 35 Daniel Dehennin
264 1 Redmine Admin
Ceci induit les mêmes inconvénients que l’utilisation des pull.
265 35 Daniel Dehennin
266 35 Daniel Dehennin
Lorsque l’on passe du temps à travailler sur une branche privée, il
267 35 Daniel Dehennin
est tentant de « fusionner » régulièrement une branche publique de
268 1 Redmine Admin
référence, afin de se mettre à jour.
269 35 Daniel Dehennin
270 35 Daniel Dehennin
Mais cette pratique ne fait que rendre illisible l’histoire privée de
271 1 Redmine Admin
cette branche.
272 35 Daniel Dehennin
273 35 Daniel Dehennin
Cela rend très difficile la relecture de chaque modification apportée
274 35 Daniel Dehennin
par cette branche car son histoire n’est plus simplement une suite
275 1 Redmine Admin
logique d’étapes afin d’arriver à un résultat voulu.
276 35 Daniel Dehennin
277 1 Redmine Admin
h2. On ne construit que sur les épaules de géants
278 35 Daniel Dehennin
279 35 Daniel Dehennin
Il existe une autre approche à la problématique généalogique des
280 1 Redmine Admin
commits, nommé dans la littérature « rebase workflow ».
281 35 Daniel Dehennin
282 35 Daniel Dehennin
Ce principe utilise la réécriture de l’historique, par conséquent,
283 1 Redmine Admin
elle ne peut être utilisée que sur des commits non publiés.
284 35 Daniel Dehennin
285 1 Redmine Admin
Le principe est le même que le greffage en botanique :
286 35 Daniel Dehennin
287 35 Daniel Dehennin
# On coupe la branche ;
288 1 Redmine Admin
# On la greffe sur une autre.
289 35 Daniel Dehennin
290 35 Daniel Dehennin
En pratique, c’est surtout utiliser pour préparer l’intégration de nos
291 1 Redmine Admin
modifications dans une branche publique.
292 35 Daniel Dehennin
293 1 Redmine Admin
C’est un peu le miroir du « merge workflow ».
294 35 Daniel Dehennin
295 35 Daniel Dehennin
Dans le « merge workflow », la fusion se fait sur la branche publique
296 1 Redmine Admin
et les conflits sont gérés dans l’histoire de la branche publique.
297 35 Daniel Dehennin
298 35 Daniel Dehennin
Dans le « rebase workflow », c’est l’inverse, tout se fait dans la
299 1 Redmine Admin
branche que l’on souhaite intégrer à la branche publique.
300 35 Daniel Dehennin
301 35 Daniel Dehennin
La procédure est décomposée comme suit :
302 35 Daniel Dehennin
303 35 Daniel Dehennin
# Mise de côté de tous les commits de la branche depuis sa création :
304 35 Daniel Dehennin
  on revient dans le tronc de développement (branche privée) à la
305 35 Daniel Dehennin
  version sur laquelle notre branche est basée ;
306 35 Daniel Dehennin
# Intégration de tous les changements de la branche publique survenus
307 35 Daniel Dehennin
  depuis ;
308 35 Daniel Dehennin
# Application de tous les commits mis de côté, il faut gérer les
309 35 Daniel Dehennin
  éventuels conflits.
310 35 Daniel Dehennin
311 35 Daniel Dehennin
Avant la procédure, la branche privée était basée sur la branche
312 35 Daniel Dehennin
publique à un certains instant dans le passé.
313 35 Daniel Dehennin
314 35 Daniel Dehennin
Après la procédure, la branche privée est basée sur le dernier commit
315 35 Daniel Dehennin
de la branche publique.
316 35 Daniel Dehennin
317 35 Daniel Dehennin
On a donc changé la base de la branche, d’où le nom de cette méthode.
318 35 Daniel Dehennin
319 35 Daniel Dehennin
Tout cela se fait simplement par :
320 1 Redmine Admin
321 35 Daniel Dehennin
<pre>
322 1 Redmine Admin
  moi@work:~/src/projet(mabranche)$ git rebase master
323 1 Redmine Admin
</pre>
324 35 Daniel Dehennin
325 35 Daniel Dehennin
Il est possible de faire fréquemment des rebases des branches privées
326 35 Daniel Dehennin
par rapport à la branche publique où seront intégrés les
327 1 Redmine Admin
modifications.
328 35 Daniel Dehennin
329 35 Daniel Dehennin
On minimise ainsi les conflits ou, plus précisément, on les dilue dans
330 1 Redmine Admin
le temps.
331 35 Daniel Dehennin
332 35 Daniel Dehennin
Ce principe de rebase est à utiliser, au moins avant l’intégration à
333 35 Daniel Dehennin
la branche publique, afin d'avoir une histoire plus propre de la
334 1 Redmine Admin
branche et ce en fusionnant certains commits.
335 35 Daniel Dehennin
336 35 Daniel Dehennin
Dans ce cas on ne rebase par par rapport à une branche publique, mais
337 19 Joël Cuissinat
par rapport à un commit de la branche privée.
338 35 Daniel Dehennin
339 35 Daniel Dehennin
Par exemple, ne pas avoir un commit ajoutant une fonctionnalité et les
340 19 Joël Cuissinat
30 suivants qui corrigent les inévitables erreurs typographiques.
341 19 Joël Cuissinat
342 35 Daniel Dehennin
343 1 Redmine Admin
h1. « Le blabla c’est bien, mais en pratique ? » par moi©®™
344 35 Daniel Dehennin
345 1 Redmine Admin
h2. Puisque je vous dis que les branches ça ne coûte rien !
346 35 Daniel Dehennin
347 36 Daniel Dehennin
Dans git, une branche est simplement un fichier dans l’arborescence du
348 1 Redmine Admin
répertoire @.git/refs/heads/@.
349 35 Daniel Dehennin
350 35 Daniel Dehennin
Ce fichier contient l’identifiant du dernier commit de cette branche,
351 35 Daniel Dehennin
c’est le "SHA1":http://fr.wikipedia.org/wiki/SHA1 du contenu de l’objet (les détails sont accessibles dans
352 1 Redmine Admin
"Les tripes de Git":http://progit.org/book/fr/ch9-0.html).
353 35 Daniel Dehennin
354 36 Daniel Dehennin
L’identifiant de commit référence un fichier dans l’arborescence du
355 1 Redmine Admin
répertoire @.git/objects/@, avec :
356 35 Daniel Dehennin
357 35 Daniel Dehennin
* les deux premiers caractères (1 octet noté en hexadécimal) sont le
358 1 Redmine Admin
  nom d’un sous répertoire ;
359 35 Daniel Dehennin
360 1 Redmine Admin
* le reste des caractères sont le nom du fichier.
361 35 Daniel Dehennin
362 35 Daniel Dehennin
Connaître l’identifiant du dernier commit est suffisant pour remonter
363 1 Redmine Admin
l’arbre généalogique.
364 35 Daniel Dehennin
365 35 Daniel Dehennin
Faire une nouvelle branche se résume donc à créer un fichier ne
366 1 Redmine Admin
contenant qu’un identifiant.
367 35 Daniel Dehennin
368 1 Redmine Admin
On créé une branche dédiée pour le développement à faire :
369 35 Daniel Dehennin
<pre>
370 1 Redmine Admin
  moi@work:~/src/projet(master)$ git checkout -b issue/42 master
371 1 Redmine Admin
</pre>
372 35 Daniel Dehennin
373 1 Redmine Admin
h2. Le clonage déontologiquement correcte
374 35 Daniel Dehennin
375 35 Daniel Dehennin
Afin de tester nos modifications avant publication, nous pouvons
376 35 Daniel Dehennin
copier les fichiers sur une machine de test, par quelque moyen que ce
377 1 Redmine Admin
soit.
378 35 Daniel Dehennin
379 35 Daniel Dehennin
Un de ces moyens, et le plus simple dans notre cas, est d’utiliser
380 1 Redmine Admin
git.
381 35 Daniel Dehennin
382 1 Redmine Admin
Étant donné que :
383 35 Daniel Dehennin
384 35 Daniel Dehennin
* Nous souhaitons tester les modifications apportées par le
385 1 Redmine Admin
  développement enregistré dans une branche non publiée ;
386 35 Daniel Dehennin
387 35 Daniel Dehennin
* Nous ne souhaitons pas publier cette branche privée tant que tout ne
388 1 Redmine Admin
  sera pas propre ;
389 35 Daniel Dehennin
390 1 Redmine Admin
Nous allons créer une copie conforme de notre dépôt, sur la machine de test.
391 35 Daniel Dehennin
392 35 Daniel Dehennin
Le fonctionnement est simple, un dépôt git, qu’il soit sur un serveur
393 1 Redmine Admin
http ou dans notre répertoire, peut servir de base à un clone.
394 35 Daniel Dehennin
395 2 samuel morin
Et un clone, ça peut se faire par "SSH":http://fr.wikipedia.org/wiki/SSH.
396 35 Daniel Dehennin
397 1 Redmine Admin
Nous avons besoin :
398 35 Daniel Dehennin
399 1 Redmine Admin
* D’une machine de test ;
400 35 Daniel Dehennin
401 1 Redmine Admin
* De l’outil git installé sur cette machine ;
402 35 Daniel Dehennin
403 1 Redmine Admin
* D’un accès "SSH":http://fr.wikipedia.org/wiki/SSH sur cette machine.
404 35 Daniel Dehennin
405 35 Daniel Dehennin
Aucun fichier ne sera éditer sur cette machine, cela évite de
406 1 Redmine Admin
s’éparpiller.
407 35 Daniel Dehennin
408 35 Daniel Dehennin
Nous mettrons à jour ce dépôt par des pull, ce qui ne posera aucun
409 35 Daniel Dehennin
soucis comme expliqué plus haut du fait qu’il n’y aura aucune
410 1 Redmine Admin
modification locale à la machine de test.
411 1 Redmine Admin
412 35 Daniel Dehennin
<pre>
413 35 Daniel Dehennin
  moi@work:~/src/projet(master)$ ssh user@test-machine
414 35 Daniel Dehennin
  user@test-machine:~$ git clone ssh://moi@work/home/moi/src/projet && cd projet
415 1 Redmine Admin
  user@test-machine:~/projet(master)$ git checkout -b issue/42 origin/issue/42
416 1 Redmine Admin
  user@test-machine:~/projet(issue/42)$ # On est prêt
417 1 Redmine Admin
</pre>
418 1 Redmine Admin
419 1 Redmine Admin
On garde un shell sur la machine de test, on y reviendra souvent, à
420 1 Redmine Admin
moins d’être très fort et de tout réussir du premier coup.
421 35 Daniel Dehennin
422 1 Redmine Admin
h2. Les commits, c’est radioactif ?
423 1 Redmine Admin
424 1 Redmine Admin
Un commit, c’est un instantané du code à un instant « T ».
425 1 Redmine Admin
426 1 Redmine Admin
Si nous souhaitons tester l’impact de chaque commit sur un projet, il
427 1 Redmine Admin
est préférable que chacun d’eux soit fonctionnel.
428 1 Redmine Admin
429 1 Redmine Admin
Par exemple, si on modifie le nom d’une fonction ou d’une variable, on
430 35 Daniel Dehennin
doit, dans le même commit, modifier tous les utilisations de l’ancien
431 35 Daniel Dehennin
nom.
432 35 Daniel Dehennin
433 35 Daniel Dehennin
Chaque commit se doit d’être le plus « atomique » possible.
434 35 Daniel Dehennin
435 35 Daniel Dehennin
h2. Cycle de développement et tests
436 35 Daniel Dehennin
437 35 Daniel Dehennin
# On code :
438 40 Daniel Dehennin
<pre>
439 40 Daniel Dehennin
 moi@work:~/src/projet(issue/42)$ ${EDITOR} src/bidule.py
440 40 Daniel Dehennin
  moi@work:~/src/projet(issue/42)$ git add src/bidule.py
441 40 Daniel Dehennin
  moi@work:~/src/projet(issue/42)$ git commit
442 40 Daniel Dehennin
</pre>
443 35 Daniel Dehennin
# On nettoie la machine de test :
444 40 Daniel Dehennin
<pre>
445 40 Daniel Dehennin
  user@test-machine:~/projet(issue/42)$ make uninstall
446 40 Daniel Dehennin
</pre>
447 35 Daniel Dehennin
# On met à jour le dépôt de la machine de test :
448 40 Daniel Dehennin
<pre>
449 40 Daniel Dehennin
  user@test-machine:~/projet(issue/42)$ git pull origin
450 40 Daniel Dehennin
</pre>
451 35 Daniel Dehennin
# On met en place la nouvelle version du code à tester :
452 40 Daniel Dehennin
<pre>
453 40 Daniel Dehennin
  user@test-machine:~/projet(issue/42)$ make install
454 40 Daniel Dehennin
</pre>
455 35 Daniel Dehennin
# On test, si des problèmes persistent, on boucle sur 1.
456 35 Daniel Dehennin
457 35 Daniel Dehennin
h2. Publication du développement
458 35 Daniel Dehennin
459 35 Daniel Dehennin
# On nettoie notre histoire privée :
460 40 Daniel Dehennin
<pre>
461 40 Daniel Dehennin
  moi@work:~/src/projet(issue/42)$ git rebase -i $(git merge-base master HEAD)
462 40 Daniel Dehennin
</pre>
463 35 Daniel Dehennin
# On rebase sur la dernière version de la branche publique :
464 40 Daniel Dehennin
<pre>
465 40 Daniel Dehennin
  moi@work:~/src/projet(issue/42)$ git fetch origin
466 40 Daniel Dehennin
  moi@work:~/src/projet(issue/42)$ git rebase origin/master
467 40 Daniel Dehennin
</pre>
468 35 Daniel Dehennin
# On intègre à la branche publique :
469 40 Daniel Dehennin
<pre>
470 40 Daniel Dehennin
  moi@work:~/src/projet(issue/42)$ git checkout master
471 40 Daniel Dehennin
  moi@work:~/src/projet(master)$ git merge issue/42
472 40 Daniel Dehennin
</pre>
473 35 Daniel Dehennin
# On tag un numéro de version :
474 40 Daniel Dehennin
<pre>
475 40 Daniel Dehennin
  moi@work:~/src/projet(master)$ git tag -s -m "release/$(date +%Y%m%d.%H%M)" release/$(date +%Y%m%d.%H%M)
476 40 Daniel Dehennin
</pre>
477 35 Daniel Dehennin
# On publie :
478 40 Daniel Dehennin
<pre>
479 40 Daniel Dehennin
  moi@work:~/src/projet(master)$ git push origin
480 40 Daniel Dehennin
</pre>
481 35 Daniel Dehennin
482 35 Daniel Dehennin
483 35 Daniel Dehennin
h1. Webographie
484 35 Daniel Dehennin
485 35 Daniel Dehennin
* "Avoiding Git Disasters: A Gory Story":www.randyfay.com/node/89
486 35 Daniel Dehennin
* "A rebase workflow":http://www.randyfay.com/node/91
487 35 Daniel Dehennin
* "Simpler Rebasing (avoiding unintentional merge commits)":http://randyfay.com/node/103
488 35 Daniel Dehennin
* "A git workflow for agile teams":http://reinh.com/blog/2009/03/02/a-git-workflow-for-agile-teams.html
489 35 Daniel Dehennin
* "The case for git rebase":http://darwinweb.net/articles/the-case-for-git-rebase
490 35 Daniel Dehennin
* "Pro git book":http://progit.org/book/ch5-3.html
491 35 Daniel Dehennin
* "Maintaining a project":http://progit.org/book/ch5-3.html
492 35 Daniel Dehennin
* "Packaging software using Git":http://www.golden-gryphon.com/software/misc/packaging.html
493 1 Redmine Admin
* "Packaging with git":http://wiki.debian.org/PackagingWithGit/