Projet

Général

Profil

GitBonnesPratiques » Historique » Version 39

Daniel Dehennin, 05/12/2011 10:14
Suppression de ce qui n’est pas bonne pratique de git

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