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