Projet

Général

Profil

GitBonnesPratiques » Historique » Version 88

Daniel Dehennin, 12/01/2017 15:38

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