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