Merge branch 'master' of https://github.com/matrig/gitmagic
[gitmagic.git] / fr / history.txt
blob8aabe8dce2a07faff3b27c503161681cc873b79a
1 // -*- mode: doc; mode: flyspell; coding: utf-8; fill-column: 79; -*-
2 == Les leçons de l'histoire ==
4 L'une des conséquences de la nature distribuée de Git est qu'il est facile de
5 modifier l'historique. Mais si vous réécrivez le passé, faites attention : ne
6 modifiez que la partie de l'historique que vous êtes le seul à posséder. Sinon,
7 comme des nations qui se battent éternellement pour savoir qui a commis telle
8 ou telle atrocité, si quelqu'un d'autre possède un clone dont l'historique
9 diffère du vôtre, vous aurez des difficultés à vous réconcilier lorsque vous
10 interagirez.
12 Certains développeurs insistent très fortement pour que l'historique soit
13 considéré comme immuable. D'autres pensent au contraire que les historiques
14 doivent être rendus présentables avant d'être présentés publiquement. Git
15 s'accommode des deux points de vue. Comme les clones, les branches et les
16 fusions, la réécriture de l'historique est juste un pouvoir supplémentaire que
17 vous donne Git. C'est à vous de l'utiliser à bon escient.
19 === Je me corrige... ===
21 Que faire si vous avez fait un commit mais que vous souhaitez y attacher un
22 message différent ? Pour modifier le dernier message, tapez :
24  $ git commit --amend
26 Vous apercevez-vous que vous avez oublié un fichier ? Faites *git add* pour
27 l'ajouter puis exécutez la commande ci-dessus.
29 Voulez-vous ajouter quelques modifications supplémentaires au dernier commit ?
30 Faites ces modifications puis exécutez :
32  $ git commit --amend -a
34 === ... et bien plus ===
36 Supposons que le problème précédent est dix fois pire. Après une longue séance,
37 vous avez effectué une série de commits. Mais vous n'êtes pas satisfait de la
38 manière dont ils sont organisés et certains des messages associés doivent être
39 revus. Tapez alors :
41  $ git rebase -i HEAD~10
43 et les dix derniers commits apparaissent dans votre $EDITOR favori. Voici un
44 petit extrait :
46     pick 5c6eb73 Added repo.or.cz link
47     pick a311a64 Reordered analogies in "Work How You Want"
48     pick 100834f Added push target to Makefile
50 Ensuite :
52 - Supprimez un commit en supprimant sa ligne.
54 - Réordonnez des commits en réordonnant leurs lignes.
56 - Remplacez `pick` par :
58    * `edit` pour marquer ce commit pour amendement.
60    * `reword` pour modifier le message associé.
62    * `squash` pour fusionner ce commit avec le précédent.
64    * `fixup` pour fusionner ce commit avec le précédent en supprimant le
65      message associé.
67 Sauvegardez et quittez. Si vous avez marqué un commit pour amendement alors
68 tapez :
70  $ git commit --amend
72 Sinon, tapez :
74  $ git rebase --continue
77 Donc faites des commits très tôt et faites-en souvent : vous pourrez tout
78 ranger plus tard grâce à 'rebase'.
80 === Les changements locaux en dernier ===
82 Vous travaillez sur un projet actif. Vous faites quelques commits locaux puis
83 vous vous resynchronisez avec le dépôt officiel grâce à une fusion (merge). Ce
84 cycle se répète jusqu'au moment où vous êtes prêt à pousser vos contributions
85 vers le dépôt central.
87 Mais à cet instant l'historique de votre clone Git local est un fouillis infâme
88 mélangeant les modifications officielles et les vôtres. Vous préféreriez que
89 toutes vos modifications soient contiguës et se situent après toutes les
90 modifications officielles.
92 C'est un boulot pour *git rebase* comme décrit ci-dessus. Dans la plupart des
93 cas, vous pouvez utilisez l'option *--onto* et éviter les interactions.
95 Lisez *git help rebase* pour des exemples détaillés sur cette merveilleuse
96 commande. Vous pouvez scinder des commits. Vous pouvez même réarranger des
97 branches de l'arbre.
99 === Réécriture de l'histoire ===
101 De temps en temps, vous avez besoin de faire des modifications équivalentes à
102 la suppression d'une personne d'une photo officielle, la gommant ainsi de
103 l'histoire d'une manière quasi Stalinienne. Supposons que vous ayez publié un
104 projet mais en y intégrant un fichier que vous auriez dû conserver secret. Par
105 exemple, vous avez accidentellement ajouté un fichier texte contenant votre
106 numéro de carte de crédit. Supprimer ce fichier n'est pas suffisant puisqu'il
107 pourra encore être retrouvé via d'anciennes versions du projet. Vous devez
108 supprimer ce fichier dans toutes les versions :
110  $ git filter-branch --tree-filter 'rm top/secret/fichier' HEAD
112 La documentation *git help filter-branch* explique cette exemple et donne une
113 méthode plus rapide. De manière générale, *filter-branch* vous permet de
114 modifier des pans entiers de votre historique grâce à une seule commande.
116 Après cela, le dossier +.git/refs/original+ contiendra l'état de votre dépôt
117 avant l'opération. Vérifiez que la commande filter-branch a bien fait ce que
118 vous souhaitiez puis effacer ce dossier si vous voulez appliquer d'autres
119 commandes filter-branch.
121 Finalement, remplacez tous les clones de votre projet par votre version révisée
122 si vous voulez pouvoir interagir avec eux plus tard.
124 === Faire l'histoire ===
126 [[makinghistory]] Voulez-vous faire migrer un projet vers Git ? S'il est géré
127 par l'un des systèmes bien connus alors il y a de grandes chances que quelqu'un
128 ait déjà écrit un script afin d'importer l'ensemble de l'historique dans Git.
130 Sinon, regarder du côté de *git fast-import* qui lit un fichier texte dans un
131 format spécifique pour créer un historique Git à partir de rien.  Typiquement
132 un script utilisant cette commande est un script jetable qui ne servira qu'une
133 seule fois pour migrer le projet d'un seul coup.
135 À titre d'exemple, collez le texte suivant dans un fichier temporaire
136 (`/tmp/historique`) :
138 ----------------------------------
139 commit refs/heads/master
140 committer Alice <alice@example.com> Thu, 01 Jan 1970 00:00:00 +0000
141 data <<EOT
142 Commit initial
145 M 100644 inline hello.c
146 data <<EOT
147 #include <stdio.h>
149 int main() {
150   printf("Hello, world!\n");
151   return 0;
156 commit refs/heads/master
157 committer Bob <bob@example.com> Tue, 14 Mar 2000 01:59:26 -0800
158 data <<EOT
159 Remplacement de printf() par write().
162 M 100644 inline hello.c
163 data <<EOT
164 #include <unistd.h>
166 int main() {
167   write(1, "Hello, world!\n", 14);
168   return 0;
171 ----------------------------------
173 Puis créez un dépôt Git à partir de ce fichier temporaire en tapant :
175  $ mkdir projet; cd projet; git init
176  $ git fast-import --date-format=rfc2822 < /tmp/historique
178 Vous pouvez extraire la dernière version de ce projet avec :
180  $ git checkout master .
182 La commande *git fast-export* peut convertir n'importe quel dépôt Git en un
183 fichier au format *git fast-import* ce qui vous permet de l'étudier pour écrire
184 des scripts d'exportation mais vous permet aussi de transporter un dépôt dans
185 un format lisible. Ces commandes permettent aussi d'envoyer un dépôt via un
186 canal qui n'accepte que du texte pur.
188 === Qu'est-ce qui a tout cassé ? ===
190 Vous venez tout juste de découvrir un bug dans une fonctionnalité de votre
191 programme et pourtant vous êtes sûr qu'elle fonctionnait encore parfaitement il
192 y a quelques mois. Zut ! D'où provient ce bug ? Si seulement vous aviez testé
193 cette fonctionnalité pendant vos développements.
195 Mais il est trop tard. En revanche, en supposant que vous avez fait des commits
196 suffisamment souvent, Git peut cerner le problème.
198  $ git bisect start
199  $ git bisect bad HEAD
200  $ git bisect good 1b6d
202 Git extrait un état à mi-chemin entre ces deux versions (HEAD et 1b6d). Testez
203 la fonctionnalité et si le bug se manifeste :
205  $ git bisect bad
207 Si elle ne se manifeste pas, remplacer "bad" (mauvais) par "good" (bon). Git
208 vous transporte à nouveau dans un état à mi-chemin entre la bonne et la
209 mauvaise version, en réduisant ainsi les possibilités. Après quelques
210 itérations, cette recherche dichotomique vous amènera au commit où le bug est
211 survenu. Une fois vos investigations terminées, retourner à votre état original
212 en tapant :
214  $ git bisect reset
216 Au lieu de tester chaque état à la main, automatisez la recherche en tapant :
218  $ git bisect run mon_script
220 Git utilise la valeur de retour du script fourni pour décider si un état est
221 bon ou mauvais : mon_script doit retourner 0 si l'état courant est ok, 125 si
222 cet état doit être sauté et n'importe quelle valeur entre 1 et 127 si l'état
223 est mauvais. Une valeur négative abandonne la commande bisect.
225 Vous pouvez faire bien plus : la page d'aide explique comment visualiser les
226 bisects, comment examiner ou rejouer le log d'un bisect et comment éliminer des
227 changements que vous savez sans conséquence afin d'accélérer la recherche.
229 === Qui a tout cassé ? ===
231 Comme de nombreux systèmes de gestion de versions, Git a sa commande blame :
233  $ git blame bug.c
235 Cette commande annote chaque ligne du fichier afin de montrer par qui et quand
236 elle a été modifiée la dernière fois. À l'inverse de la plupart des autres
237 systèmes, cette commande marche hors-ligne et ne lit que le disque local.
239 === Expérience personnelle ===
241 Avec un système de gestion de versions centralisé, la modification de
242 l'historique est une opération difficile et faisable uniquement par les
243 administrateurs. Créer un clone, créer une branche ou en fusionner plusieurs
244 sont des opérations impossibles à réaliser sans communication réseau. Il en est
245 de même pour certains opérations basiques telles que parcourir l'historique ou
246 intégrer une modification. Avec certains systèmes, des communications réseaux
247 sont même nécessaires juste pour voir ses propres modifications ou pour ouvrir
248 un fichier avec le droit de modification.
250 Ces systèmes centralisés empêchent le travail hors-ligne et nécessitent une
251 infrastructure réseau d'autant plus lourde que le nombre de développeurs
252 augmentent. Plus important encore, certaines opérations deviennent si lentes
253 que les utilisateurs les évitent à moins qu'elles soient absolument
254 indispensables. Dans les cas extrêmes cela devient vrai même pour les commandes
255 les plus basiques. Lorsque les utilisateurs doivent effectuer des opérations
256 lentes, la productivité souffre des interruptions répétées.
258 J'ai moi-même vécu ce phénomène. Git a été le premier système de gestion de
259 versions que j'ai utilisé. Je me suis vite accoutumé à lui, tenant la plupart
260 de ses fonctionnalités pour acquises. Je pensais que les autres systèmes
261 étaient similaires : le choix d'un système de gestion de versions ne devait pas
262 être bien différent du choix d'un éditeur de texte ou d'un navigateur web.
264 J'ai été très surpris lorsque, plus tard, il m'a fallu utilisé un système
265 centralisé. Une liaison internet épisodique importe peu avec Git mais rend le
266 développement quasi impossible lorsque le système exige qu'elle soit aussi
267 fiable que les accès au disque local. De plus, je me restreignais afin d'éviter
268 certaines commandes trop longues, ce qui m'empêchait de suivre ma méthode de
269 travail habituelle.
271 Lorsqu'il me fallait utiliser ces commandes lentes, cela interrompait mes
272 réflexions et avait des effets pervers. En attendant la fin des communications
273 avec le serveur, je me lançais dans autre chose pour passer le temps comme lire
274 mes mails ou écrire de la documentation. Lorsque je revenais à mon travail
275 initial, la commande s'était terminée depuis longtemps et je perdais du temps à
276 retrouver le fil de mes pensées. Les être humains ne sont pas bons pour changer
277 de contexte.
279 Il y a aussi un effet intéressant du type « tragédie des biens communs » : afin
280 d'anticiper la congestion du réseau, certains vont consommer plus de bandes
281 passantes que nécessaire pour effectuer des opérations visant à réduire leurs
282 attentes futures. Ces efforts combinés vont encore augmenter la congestion,
283 incitant ces personnes à consommer encore plus de bande passante pour éviter
284 ces délais toujours plus longs.
286 // LocalWords:  Git doc visual-line flyspell coding utf git amend add commits
287 // LocalWords:  apercevez-vous Voulez-vous rebase HEAD EDITOR pick eb Added How
288 // LocalWords:  link Reordered Work You Want push target to Makefile edit fixup
289 // LocalWords:  reword faites-en merge onto help filter-branch tree-filter rm
290 // LocalWords:  filter-banch makinghistory fast-import refs committer Alice Thu
291 // LocalWords:  EOT inline hello.c include stdio.h int printf world return Mar
292 // LocalWords:  write unistd.h mkdir cd init date-format rfc checkout master ok
293 // LocalWords:  fast-export bug bisect start bad good reset run bisects log web
294 // LocalWords:  blame bug.c