Projet

Général

Profil

GitBonnesPratiques » Historique » Version 67

Daniel Dehennin, 20/07/2012 12:01
Mise en valeur de git immersion

1 40 Daniel Dehennin
{{toc}}
2 1 Redmine Admin
3 54 Klaas TJEBBES
L'ancienne page GitBonnesPratiques est ici http://dev-eole.ac-dijon.fr/projects/eole/wiki/RecueilGit
4 54 Klaas TJEBBES
5 40 Daniel Dehennin
h1. Les bonnes pratiques c’est quoi ?
6 1 Redmine Admin
7 40 Daniel Dehennin
Ce document n’est pas une référence git, nous n’allons pas réécrire le
8 40 Daniel Dehennin
"progit book":http://progit.org/book/fr, ni les autres références disponibles sur Internet.
9 1 Redmine Admin
10 67 Daniel Dehennin
Il existe même des "tutoriels":http://gitimmersion.fr/index.html pas à pas bien fait.
11 67 Daniel Dehennin
12 40 Daniel Dehennin
Nous allons partir du principe qu’un minimum de connaissance de l’outil git est acquis, notamment 
13 42 Daniel Dehennin
le "démarrage rapide":http://progit.org/book/fr/ch1-0.html et les "bases de git":http://progit.org/book/fr/ch2-0.html du livre "progit book":http://progit.org/book/fr.
14 1 Redmine Admin
15 40 Daniel Dehennin
Nous allons essayer de décrire ici une méthodologie de travail basée sur le
16 40 Daniel Dehennin
système de gestion de version décentralisé "git":https://fr.wikipedia.org/wiki/Git avec les objectifs suivants :
17 1 Redmine Admin
18 40 Daniel Dehennin
* Communiquer entre développeur
19 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
20 40 Daniel Dehennin
* Publier des modifications clairement identifiables et analysables, par des humains et des outils de tests automatiques
21 35 Daniel Dehennin
22 41 Daniel Dehennin
Ce document ne représente en rien _LA_ bonne méthode de travail, il s’agit juste d’une façon de faire,
23 41 Daniel Dehennin
appuyée par l’expérience d’autres personnes que l’on trouve un peu partout sur Internet.
24 1 Redmine Admin
25 41 Daniel Dehennin
Il est tout à fait possible de trouver autant, voir plus, de références prônant un point de vue opposé ou orthogonal au mien.
26 14 Klaas TJEBBES
27 35 Daniel Dehennin
28 1 Redmine Admin
h1. De la méthode agile
29 35 Daniel Dehennin
30 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
31 1 Redmine Admin
« Les individus et leurs interactions ».
32 35 Daniel Dehennin
33 35 Daniel Dehennin
Afin de travailler correctement en équipe, il faut communiquer, et
34 35 Daniel Dehennin
l’outil de gestion de version "git":https://fr.wikipedia.org/wiki/Git, utilisé à EOLE, peut-être un excellent
35 23 Redmine Admin
outil de communication.
36 23 Redmine Admin
37 35 Daniel Dehennin
38 23 Redmine Admin
h1. De l’écriture des "ChangeLog":https://fr.wikipedia.org/wiki/ChangeLog
39 35 Daniel Dehennin
40 35 Daniel Dehennin
Afin de communiquer avec les autres membres d’une équipe sur le
41 35 Daniel Dehennin
travail que chacun effectue, l’écriture d’un ChangeLog, ou plus
42 35 Daniel Dehennin
précisément d’un « commit message » dans la littérature en anglaise
43 35 Daniel Dehennin
(qui pourrait être traduit par « message de consignation ») se doit
44 1 Redmine Admin
d’être fait correctement(sic).
45 35 Daniel Dehennin
46 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 » ?
47 35 Daniel Dehennin
48 1 Redmine Admin
Nous pouvons établir une règle simple et souple, par exemple :
49 35 Daniel Dehennin
50 23 Redmine Admin
Un message de commit comprend :
51 35 Daniel Dehennin
52 23 Redmine Admin
* Une première ligne résumant le pourquoi du patch ;
53 35 Daniel Dehennin
* Une description longue optionnelle permettant d’expliciter le
54 1 Redmine Admin
  contexte du résumé donné en première ligne ;
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 62 Daniel Dehennin
Cela impose les règles suivantes :
77 1 Redmine Admin
78 62 Daniel Dehennin
# « Ne jamais utiliser l’option "-m" de la commande "git commit" »
79 62 Daniel Dehennin
# « Ne pas décrire ce que fait le commit mais pourquoi »
80 1 Redmine Admin
81 62 Daniel Dehennin
La description de se que fait un commit est le rôle du "diff":https://fr.wikipedia.org/wiki/Diff.
82 62 Daniel Dehennin
83 62 Daniel Dehennin
Ainsi, le second exemple donné plus haut n’est pas correcte : « la première ligne ne décrit pas pourquoi on simplifie la gestion des noyaux ».
84 35 Daniel Dehennin
85 1 Redmine Admin
h1. De la cohérence de l’histoire du monde
86 35 Daniel Dehennin
87 35 Daniel Dehennin
Un système de gestion de version permet avant tout de conserver un
88 14 Klaas TJEBBES
livre d’histoire d’un projet.
89 35 Daniel Dehennin
90 35 Daniel Dehennin
Dans les premiers systèmes de gestion de version, cette histoire était
91 35 Daniel Dehennin
centralisée. Il fallait avoir le droit d’écrire dans le « livre des
92 35 Daniel Dehennin
comptes et légendes » afin d’y ajouter un morceau, impossible donc de
93 1 Redmine Admin
réécrire l’histoire sans être tout puissant sur le registre.
94 35 Daniel Dehennin
95 35 Daniel Dehennin
Grâce aux systèmes décentralisés comme "git":https://fr.wikipedia.org/wiki/Git, tout le monde peut avoir
96 35 Daniel Dehennin
une copie privée de l’histoire publique d’un projet, pour cela il
97 1 Redmine Admin
suffit de « cloner » l’histoire originale :
98 1 Redmine Admin
99 35 Daniel Dehennin
<pre>
100 14 Klaas TJEBBES
  moi@work:~/src$ git clone git://far-far.away.example.net/bidule.git
101 14 Klaas TJEBBES
</pre>
102 35 Daniel Dehennin
103 35 Daniel Dehennin
À partir de là il est possible de vouloir y ajouter ses propres
104 1 Redmine Admin
morceaux, et cela sans rien demander à personne.
105 35 Daniel Dehennin
106 35 Daniel Dehennin
On modifie le projet et on consigne les nouveaux événements dans
107 35 Daniel Dehennin
notre copie locale de l’histoire du projet :
108 1 Redmine Admin
109 35 Daniel Dehennin
<pre>
110 35 Daniel Dehennin
  moi@work:~/src/bidule(master)$ $EDITOR src/bidule.c # On modifie un fichier du projet
111 35 Daniel Dehennin
  moi@work:~/src/bidule(master)$ git add src/bidule.c # On ajoute un événement à enregistrer dans le livre d’histoire
112 1 Redmine Admin
  moi@work:~/src/bidule(master)$ git commit # On consigne ce nouvel événement
113 1 Redmine Admin
</pre>
114 35 Daniel Dehennin
115 35 Daniel Dehennin
Mais l’histoire, c’est un sujet sensible. On ne badine pas avec
116 1 Redmine Admin
l’histoire et on ne la réécrit sous aucun prétexte.
117 35 Daniel Dehennin
118 35 Daniel Dehennin
Peu importe si la vérité est ailleurs, l’important c’est que tout le
119 1 Redmine Admin
monde soit d’accord sur la même version des faits.
120 35 Daniel Dehennin
121 35 Daniel Dehennin
Si un plaisantin modifie l’histoire et la publie à tout vent, il y
122 17 Gérald Schwartzmann
aura conflit.
123 35 Daniel Dehennin
124 1 Redmine Admin
Nous allons donc édicter la règle suivante :
125 35 Daniel Dehennin
126 16 Gaston TJEBBES
« On ne réécrit pas l’histoire connue »
127 35 Daniel Dehennin
128 35 Daniel Dehennin
Cela sous entend donc que nous pouvons réécrire comme il nous plaît
129 35 Daniel Dehennin
toute l’histoire qui nous est privée, c’est à dire inconnue de tous
130 1 Redmine Admin
les autres.
131 35 Daniel Dehennin
132 1 Redmine Admin
Mais dès qu’un événement est rendu public, ça n'est plus possible.
133 8 Gaston TJEBBES
134 35 Daniel Dehennin
135 8 Gaston TJEBBES
h1. Trop de pull, c’est trop chaud !
136 35 Daniel Dehennin
137 35 Daniel Dehennin
Que se passe-t-il si un jour nous souhaitons apprendre les nouvelles
138 8 Gaston TJEBBES
histoires de par le monde ?
139 35 Daniel Dehennin
140 35 Daniel Dehennin
Que ce passe-t-il si un jour nous souhaitons partager nos petites
141 1 Redmine Admin
histoires avec le reste du monde ?
142 35 Daniel Dehennin
143 35 Daniel Dehennin
La plupart du temps, la réponse donnée à ces questions commence par
144 1 Redmine Admin
quelque chose comme « fais-toi donc un pull ».
145 35 Daniel Dehennin
146 11 Gaston TJEBBES
Cela se traduit, en terme git, par :
147 1 Redmine Admin
148 35 Daniel Dehennin
<pre>
149 1 Redmine Admin
  moi@work:~/src/bidule(master)$ git pull
150 1 Redmine Admin
</pre>
151 35 Daniel Dehennin
152 1 Redmine Admin
Cela est strictement équivalent aux deux commandes suivantes :
153 1 Redmine Admin
154 35 Daniel Dehennin
<pre>
155 35 Daniel Dehennin
  moi@work:~/src/bidule(master)$ git fetch origin
156 1 Redmine Admin
  moi@work:~/src/bidule(master)$ git merge origin/master
157 1 Redmine Admin
</pre>
158 35 Daniel Dehennin
159 35 Daniel Dehennin
Mais il existe quelques soucis avec cette méthode, la première étant
160 29 Joël Cuissinat
« qu’une histoire entre en conflit avec l’une des vôtres ».
161 35 Daniel Dehennin
162 35 Daniel Dehennin
Un autre problème est que cette méthode « mélange » littéralement
163 35 Daniel Dehennin
l’histoire publique avec vos histoires privées, même s’il n’y a pas de
164 35 Daniel Dehennin
conflit, il peut-être difficile de savoir si le résultat aura un sens
165 1 Redmine Admin
ou non.
166 1 Redmine Admin
167 35 Daniel Dehennin
Dans git, chaque commit a une généalogie, le parent du commit que je
168 1 Redmine Admin
m’apprête à faire est le dernier commit enregistré dans le dépôt.
169 35 Daniel Dehennin
170 21 Joël Cuissinat
Lors d’un pull sur un dépôt contenant des modifications, git créé un
171 41 Daniel Dehennin
commit ayant deux parents dont le seul but est de mélanger la généalogie.
172 37 Daniel Dehennin
173 41 Daniel Dehennin
Il est donc préférable d’utiliser la méthode décomposée en deux commandes.
174 37 Daniel Dehennin
175 37 Daniel Dehennin
Cela permet de vérifier au préalable si des changements
176 37 Daniel Dehennin
sont à intégrer, et lesquels, avec les commandes suivantes :
177 37 Daniel Dehennin
178 37 Daniel Dehennin
* ChangeLog des différences
179 38 Daniel Dehennin
<pre>
180 37 Daniel Dehennin
  moi@work:~/src/bidule(master)$ git log master..origin/master
181 37 Daniel Dehennin
</pre>
182 44 Fabrice Barconnière
* Liste des fichiers modifiés
183 38 Daniel Dehennin
<pre>
184 37 Daniel Dehennin
  moi@work:~/src/bidule(master)$ git diff --stat master..origin/master
185 37 Daniel Dehennin
</pre>
186 37 Daniel Dehennin
* Modification du code
187 38 Daniel Dehennin
<pre>
188 37 Daniel Dehennin
  moi@work:~/src/bidule(master)$ git diff master..origin/master
189 21 Joël Cuissinat
</pre>
190 35 Daniel Dehennin
191 21 Joël Cuissinat
Mais cela n’empêche nullement :
192 35 Daniel Dehennin
193 35 Daniel Dehennin
* D’être potentiellement désastreux : chaque « fusion » (merge) et
194 35 Daniel Dehennin
  « consignation » de « fusion » (merge commit) sont à la charge de
195 21 Joël Cuissinat
  chaque développeur ;
196 35 Daniel Dehennin
* Votre histoire devient illisible. Elle intègre tout un tas de
197 21 Joël Cuissinat
  « fusion » inexplicables ;
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 44 Fabrice Barconnière
utilisation 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 1 Redmine Admin
  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 40 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 35 Daniel Dehennin
</pre>
224 35 Daniel Dehennin
225 41 Daniel Dehennin
Chacune de ces commandes permet de définir, en dernier argument, le point de départ de la nouvelle branche.
226 35 Daniel Dehennin
227 1 Redmine Admin
Par défaut ce point de départ est le dernier commit de la branche courante.
228 35 Daniel Dehennin
229 1 Redmine Admin
Tout les commit effectués sur cette branche sont localisés à cette branche.
230 1 Redmine Admin
231 35 Daniel Dehennin
Cela permet de se focaliser sur une activité :
232 1 Redmine Admin
233 1 Redmine Admin
* Sans risquer d’impacter la vision que les autres ont de l’histoire ;
234 1 Redmine Admin
* Sans se soucier de ce qui peut arriver sur les autres branches ;
235 1 Redmine Admin
* Sans fusionner les modifications de la branche principale dans la
236 35 Daniel Dehennin
  branche courante.
237 1 Redmine Admin
238 41 Daniel Dehennin
Il faut travailler ensuite à intégrer cette nouvelle histoire à la ligne principale.
239 1 Redmine Admin
240 35 Daniel Dehennin
h2. Les voies du temps sont interpénétrables
241 35 Daniel Dehennin
242 41 Daniel Dehennin
C’est le principe utilisé par le pull, ce qui est nommé dans la littérature le « merge workflow ».
243 36 Daniel Dehennin
244 41 Daniel Dehennin
Ce qui est fait lors d’un @git pull@ entre une branche locale et une branche sur un dépôt distant,
245 41 Daniel Dehennin
« remote » en jargon git, est applicable entre deux branches d’un dépôt local.
246 35 Daniel Dehennin
247 41 Daniel Dehennin
En pratique, on se positionne sur la branche qui doit intégrer les modifications d’une autre,
248 41 Daniel Dehennin
par exemple une branche publique, et on fusionne la branche privée de développement dans cette branche publique :
249 1 Redmine Admin
250 1 Redmine Admin
<pre>
251 36 Daniel Dehennin
  moi@work:~/src/projet(master)$ git merge mabranche
252 1 Redmine Admin
</pre>
253 35 Daniel Dehennin
254 1 Redmine Admin
Pour ensuite publier ces modifications par @git push@.
255 35 Daniel Dehennin
256 35 Daniel Dehennin
Ceci induit les mêmes inconvénients que l’utilisation des pull.
257 35 Daniel Dehennin
258 59 Daniel Dehennin
Lorsque l’on passe du temps à travailler sur une branche privée, il est tentant de « fusionner » régulièrement une branche publique de référence, afin de se mettre à jour.
259 35 Daniel Dehennin
260 1 Redmine Admin
Mais cette pratique ne fait que rendre illisible l’histoire privée de cette branche.
261 1 Redmine Admin
262 59 Daniel Dehennin
Cela rend très difficile la relecture de chaque modification apportée par cette branche car son histoire n’est plus simplement une suite logique d’étapes afin d’arriver à un résultat voulu.
263 59 Daniel Dehennin
264 59 Daniel Dehennin
Fusionner des branches amont ("upstream":http://fr.wiktionary.org/wiki/upstream) dans votre branche de travail en cours sans une raison réellement valable est considéré comme une très mauvaise pratique.
265 59 Daniel Dehennin
266 59 Daniel Dehennin
Un telle fusion dans une direction erronée (upstream=>branche privée) ne devrait être fait qu’en cas d’absolue nécessitée, par exemple, lorsque votre travail en cours nécessite des nouveautés effectuées sur la branche upstream.
267 59 Daniel Dehennin
268 59 Daniel Dehennin
Autrement, votre branche de travail ne sera plus sur un sujet particulier mais deviendra un amas informe de commit de sources diverses et avariées, venant de votre propre branche mais aussi d’upstream contenant du travail fait par d’autres sur des sujets tout aussi divers et variés.
269 35 Daniel Dehennin
270 1 Redmine Admin
h2. On ne construit que sur les épaules de géants
271 35 Daniel Dehennin
272 35 Daniel Dehennin
Il existe une autre approche à la problématique généalogique des
273 1 Redmine Admin
commits, nommé dans la littérature « rebase workflow ».
274 35 Daniel Dehennin
275 35 Daniel Dehennin
Ce principe utilise la réécriture de l’historique, par conséquent,
276 1 Redmine Admin
elle ne peut être utilisée que sur des commits non publiés.
277 35 Daniel Dehennin
278 1 Redmine Admin
Le principe est le même que le greffage en botanique :
279 35 Daniel Dehennin
280 35 Daniel Dehennin
# On coupe la branche ;
281 1 Redmine Admin
# On la greffe sur une autre.
282 35 Daniel Dehennin
283 45 Fabrice Barconnière
En pratique, c’est surtout utilisé pour préparer l’intégration de nos
284 1 Redmine Admin
modifications dans une branche publique.
285 35 Daniel Dehennin
286 1 Redmine Admin
C’est un peu le miroir du « merge workflow ».
287 35 Daniel Dehennin
288 35 Daniel Dehennin
Dans le « merge workflow », la fusion se fait sur la branche publique
289 1 Redmine Admin
et les conflits sont gérés dans l’histoire de la branche publique.
290 35 Daniel Dehennin
291 35 Daniel Dehennin
Dans le « rebase workflow », c’est l’inverse, tout se fait dans la
292 1 Redmine Admin
branche que l’on souhaite intégrer à la branche publique.
293 35 Daniel Dehennin
294 35 Daniel Dehennin
La procédure est décomposée comme suit :
295 35 Daniel Dehennin
296 35 Daniel Dehennin
# Mise de côté de tous les commits de la branche depuis sa création :
297 35 Daniel Dehennin
  on revient dans le tronc de développement (branche privée) à la
298 35 Daniel Dehennin
  version sur laquelle notre branche est basée ;
299 35 Daniel Dehennin
# Intégration de tous les changements de la branche publique survenus
300 35 Daniel Dehennin
  depuis ;
301 35 Daniel Dehennin
# Application de tous les commits mis de côté, il faut gérer les
302 35 Daniel Dehennin
  éventuels conflits.
303 35 Daniel Dehennin
304 35 Daniel Dehennin
Avant la procédure, la branche privée était basée sur la branche
305 45 Fabrice Barconnière
publique à un certain instant dans le passé.
306 35 Daniel Dehennin
307 35 Daniel Dehennin
Après la procédure, la branche privée est basée sur le dernier commit
308 35 Daniel Dehennin
de la branche publique.
309 35 Daniel Dehennin
310 35 Daniel Dehennin
On a donc changé la base de la branche, d’où le nom de cette méthode.
311 35 Daniel Dehennin
312 35 Daniel Dehennin
Tout cela se fait simplement par :
313 1 Redmine Admin
314 35 Daniel Dehennin
<pre>
315 1 Redmine Admin
  moi@work:~/src/projet(mabranche)$ git rebase master
316 1 Redmine Admin
</pre>
317 35 Daniel Dehennin
318 35 Daniel Dehennin
Il est possible de faire fréquemment des rebases des branches privées
319 45 Fabrice Barconnière
par rapport à la branche publique où seront intégrées les
320 1 Redmine Admin
modifications.
321 35 Daniel Dehennin
322 35 Daniel Dehennin
On minimise ainsi les conflits ou, plus précisément, on les dilue dans
323 1 Redmine Admin
le temps.
324 35 Daniel Dehennin
325 35 Daniel Dehennin
Ce principe de rebase est à utiliser, au moins avant l’intégration à
326 35 Daniel Dehennin
la branche publique, afin d'avoir une histoire plus propre de la
327 1 Redmine Admin
branche et ce en fusionnant certains commits.
328 35 Daniel Dehennin
329 45 Fabrice Barconnière
Dans ce cas on ne rebase pas par rapport à une branche publique, mais
330 19 Joël Cuissinat
par rapport à un commit de la branche privée.
331 35 Daniel Dehennin
332 35 Daniel Dehennin
Par exemple, ne pas avoir un commit ajoutant une fonctionnalité et les
333 19 Joël Cuissinat
30 suivants qui corrigent les inévitables erreurs typographiques.
334 19 Joël Cuissinat
335 35 Daniel Dehennin
336 1 Redmine Admin
h1. « Le blabla c’est bien, mais en pratique ? » par moi©®™
337 35 Daniel Dehennin
338 1 Redmine Admin
h2. Puisque je vous dis que les branches ça ne coûte rien !
339 35 Daniel Dehennin
340 36 Daniel Dehennin
Dans git, une branche est simplement un fichier dans l’arborescence du
341 1 Redmine Admin
répertoire @.git/refs/heads/@.
342 35 Daniel Dehennin
343 35 Daniel Dehennin
Ce fichier contient l’identifiant du dernier commit de cette branche,
344 35 Daniel Dehennin
c’est le "SHA1":http://fr.wikipedia.org/wiki/SHA1 du contenu de l’objet (les détails sont accessibles dans
345 1 Redmine Admin
"Les tripes de Git":http://progit.org/book/fr/ch9-0.html).
346 35 Daniel Dehennin
347 36 Daniel Dehennin
L’identifiant de commit référence un fichier dans l’arborescence du
348 1 Redmine Admin
répertoire @.git/objects/@, avec :
349 35 Daniel Dehennin
350 35 Daniel Dehennin
* les deux premiers caractères (1 octet noté en hexadécimal) sont le
351 1 Redmine Admin
  nom d’un sous répertoire ;
352 1 Redmine Admin
* le reste des caractères sont le nom du fichier.
353 35 Daniel Dehennin
354 35 Daniel Dehennin
Connaître l’identifiant du dernier commit est suffisant pour remonter
355 1 Redmine Admin
l’arbre généalogique.
356 35 Daniel Dehennin
357 35 Daniel Dehennin
Faire une nouvelle branche se résume donc à créer un fichier ne
358 1 Redmine Admin
contenant qu’un identifiant.
359 35 Daniel Dehennin
360 1 Redmine Admin
On créé une branche dédiée pour le développement à faire :
361 35 Daniel Dehennin
<pre>
362 1 Redmine Admin
  moi@work:~/src/projet(master)$ git checkout -b issue/42 master
363 1 Redmine Admin
</pre>
364 35 Daniel Dehennin
365 1 Redmine Admin
h2. Le clonage déontologiquement correcte
366 35 Daniel Dehennin
367 35 Daniel Dehennin
Afin de tester nos modifications avant publication, nous pouvons
368 35 Daniel Dehennin
copier les fichiers sur une machine de test, par quelque moyen que ce
369 1 Redmine Admin
soit.
370 35 Daniel Dehennin
371 35 Daniel Dehennin
Un de ces moyens, et le plus simple dans notre cas, est d’utiliser
372 1 Redmine Admin
git.
373 35 Daniel Dehennin
374 1 Redmine Admin
Étant donné que :
375 35 Daniel Dehennin
376 35 Daniel Dehennin
* Nous souhaitons tester les modifications apportées par le
377 1 Redmine Admin
  développement enregistré dans une branche non publiée ;
378 35 Daniel Dehennin
* Nous ne souhaitons pas publier cette branche privée tant que tout ne
379 1 Redmine Admin
  sera pas propre ;
380 35 Daniel Dehennin
381 1 Redmine Admin
Nous allons créer une copie conforme de notre dépôt, sur la machine de test.
382 35 Daniel Dehennin
383 1 Redmine Admin
Le fonctionnement est simple, un dépôt git, qu’il soit sur un serveur
384 1 Redmine Admin
http ou dans notre répertoire, peut servir de base à un clone.
385 35 Daniel Dehennin
386 1 Redmine Admin
Et un clone, ça peut se faire par "SSH":http://fr.wikipedia.org/wiki/SSH.
387 35 Daniel Dehennin
388 2 samuel morin
Nous avons besoin :
389 35 Daniel Dehennin
390 1 Redmine Admin
* D’une machine de test ;
391 53 Daniel Dehennin
* D’un accès "SSH":http://fr.wikipedia.org/wiki/SSH sur cette machine ;
392 53 Daniel Dehennin
* De l’outil git installé sur cette machine.
393 35 Daniel Dehennin
394 35 Daniel Dehennin
Aucun fichier ne sera éditer sur cette machine, cela évite de
395 1 Redmine Admin
s’éparpiller.
396 35 Daniel Dehennin
397 35 Daniel Dehennin
Nous mettrons à jour ce dépôt par des pull, ce qui ne posera aucun
398 35 Daniel Dehennin
soucis comme expliqué plus haut du fait qu’il n’y aura aucune
399 1 Redmine Admin
modification locale à la machine de test.
400 1 Redmine Admin
401 35 Daniel Dehennin
<pre>
402 35 Daniel Dehennin
  moi@work:~/src/projet(master)$ ssh user@test-machine
403 35 Daniel Dehennin
  user@test-machine:~$ git clone ssh://moi@work/home/moi/src/projet && cd projet
404 1 Redmine Admin
  user@test-machine:~/projet(master)$ git checkout -b issue/42 origin/issue/42
405 1 Redmine Admin
  user@test-machine:~/projet(issue/42)$ # On est prêt
406 1 Redmine Admin
</pre>
407 1 Redmine Admin
408 1 Redmine Admin
On garde un shell sur la machine de test, on y reviendra souvent, à
409 1 Redmine Admin
moins d’être très fort et de tout réussir du premier coup.
410 35 Daniel Dehennin
411 1 Redmine Admin
h2. Les commits, c’est radioactif ?
412 1 Redmine Admin
413 1 Redmine Admin
Un commit, c’est un instantané du code à un instant « T ».
414 1 Redmine Admin
415 1 Redmine Admin
Si nous souhaitons tester l’impact de chaque commit sur un projet, il
416 1 Redmine Admin
est préférable que chacun d’eux soit fonctionnel.
417 1 Redmine Admin
418 1 Redmine Admin
Par exemple, si on modifie le nom d’une fonction ou d’une variable, on
419 46 Fabrice Barconnière
doit, dans le même commit, modifier toutes les utilisations de l’ancien
420 35 Daniel Dehennin
nom.
421 1 Redmine Admin
422 35 Daniel Dehennin
Chaque commit se doit d’être le plus « atomique » possible.
423 1 Redmine Admin
424 1 Redmine Admin
h2. Cycle de développement et tests
425 1 Redmine Admin
426 1 Redmine Admin
# On code :
427 1 Redmine Admin
<pre>
428 47 Daniel Dehennin
  moi@work:~/src/projet(issue/42)$ ${EDITOR} src/bidule.py
429 35 Daniel Dehennin
  moi@work:~/src/projet(issue/42)$ git add src/bidule.py
430 35 Daniel Dehennin
  moi@work:~/src/projet(issue/42)$ git commit
431 35 Daniel Dehennin
</pre>
432 35 Daniel Dehennin
# On nettoie la machine de test :
433 40 Daniel Dehennin
<pre>
434 40 Daniel Dehennin
  user@test-machine:~/projet(issue/42)$ make uninstall
435 40 Daniel Dehennin
</pre>
436 40 Daniel Dehennin
# On met à jour le dépôt de la machine de test :
437 35 Daniel Dehennin
<pre>
438 40 Daniel Dehennin
  user@test-machine:~/projet(issue/42)$ git pull origin
439 40 Daniel Dehennin
</pre>
440 40 Daniel Dehennin
# On met en place la nouvelle version du code à tester :
441 35 Daniel Dehennin
<pre>
442 40 Daniel Dehennin
  user@test-machine:~/projet(issue/42)$ make install
443 40 Daniel Dehennin
</pre>
444 48 Daniel Dehennin
# On test, si des problèmes persistent, on boucle sur 1 et on peut même utiliser un [[GitTrucsEtAstuces#Tu-balises-quand-tu-commit|petit truc]] pour s’y retrouver dans toutes ces itérations.
445 35 Daniel Dehennin
446 40 Daniel Dehennin
h2. Publication du développement
447 40 Daniel Dehennin
448 41 Daniel Dehennin
# On détermine le nombre de modification de notre branche par rapport à la branche « master »:
449 35 Daniel Dehennin
<pre>
450 41 Daniel Dehennin
  moi@work:~/src/projet(issue/42)$ git log --oneline master..HEAD | wc -l
451 41 Daniel Dehennin
5
452 41 Daniel Dehennin
</pre>
453 41 Daniel Dehennin
# On nettoie notre histoire privée, dans notre exemple, à partir du 5e commit avant la fin:
454 41 Daniel Dehennin
<pre>
455 41 Daniel Dehennin
  moi@work:~/src/projet(issue/42)$ git rebase -i HEAD~5
456 40 Daniel Dehennin
</pre>
457 35 Daniel Dehennin
# On rebase sur la dernière version de la branche publique :
458 40 Daniel Dehennin
<pre>
459 40 Daniel Dehennin
  moi@work:~/src/projet(issue/42)$ git fetch origin
460 40 Daniel Dehennin
  moi@work:~/src/projet(issue/42)$ git rebase origin/master
461 40 Daniel Dehennin
</pre>
462 35 Daniel Dehennin
# On intègre à la branche publique :
463 40 Daniel Dehennin
<pre>
464 40 Daniel Dehennin
  moi@work:~/src/projet(issue/42)$ git checkout master
465 40 Daniel Dehennin
  moi@work:~/src/projet(master)$ git merge issue/42
466 40 Daniel Dehennin
</pre>
467 56 Daniel Dehennin
# On [[GitTagging|tag]] un numéro de version, dans cet exemple, nous utilisons un "timestamp":http://fr.wikipedia.org/wiki/Timestamp :
468 40 Daniel Dehennin
<pre>
469 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)
470 40 Daniel Dehennin
</pre>
471 35 Daniel Dehennin
# On publie :
472 40 Daniel Dehennin
<pre>
473 40 Daniel Dehennin
  moi@work:~/src/projet(master)$ git push origin
474 40 Daniel Dehennin
</pre>
475 35 Daniel Dehennin
476 35 Daniel Dehennin
477 35 Daniel Dehennin
h1. Webographie
478 52 Daniel Dehennin
479 65 Daniel Dehennin
* "Pro git book":http://progit.org/book/fr/
480 1 Redmine Admin
* "Git Immersion":http://gitimmersion.fr
481 66 Daniel Dehennin
* "Activer le complètement automatique pour Bash":http://repo.or.cz/w/git/debian.git/blob/HEAD:/contrib/completion/git-completion.bash#l24
482 65 Daniel Dehennin
* "A successful git branching model":http://nvie.com/posts/a-successful-git-branching-model/
483 65 Daniel Dehennin
* "Le principe de DaggyFixes, par mercurial":http://mercurial.selenic.com/wiki/DaggyFixes
484 65 Daniel Dehennin
* "Le principe de DaggyFixes, par monotone":http://wiki.monotone.ca/DaggyFixes/
485 43 Daniel Dehennin
* "Avoiding Git Disasters: A Gory Story":http://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
* "Maintaining a project":http://progit.org/book/ch5-3.html
491 35 Daniel Dehennin
* "Packaging software using Git":http://www.golden-gryphon.com/software/misc/packaging.html
492 1 Redmine Admin
* "Packaging with git":http://wiki.debian.org/PackagingWithGit/
493 58 Daniel Dehennin
* "Software Branching and Parallel Universes":http://www.codinghorror.com/blog/2007/10/software-branching-and-parallel-universes.html
494 60 Daniel Dehennin
* "Anticipating Git 1.7.10":http://git-blame.blogspot.com/2012/02/anticipating-git-1710.html
495 60 Daniel Dehennin
* "Using signed tag in pull requests":http://git-blame.blogspot.com/2012/01/using-signed-tag-in-pull-requests.html
496 60 Daniel Dehennin
* "Trouver la source des cherry-pick avec git ?":http://stackoverflow.com/questions/2922652/git-is-there-a-way-to-figure-out-where-a-commit-was-cherry-picked-from
497 60 Daniel Dehennin
* "Making Sense of Revision-Control Systems":http://cacm.acm.org/magazines/2009/9/38901-making-sense-of-revision-control-systems/fulltext
498 61 Daniel Dehennin
* "One best practice workflow with git":http://wildfalcon.com/archives/2008/05/05/best-practice-work-flow-with-git/
499 63 Daniel Dehennin
* "GitGuys":http://www.gitguys.com/