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