all repos — slides @ fd8c9cfab9a3969c5b3d87d9724ed0d645b041d9

Reveal-md slides I made for various occasions

réalise/_static/Git.html (view raw)

  1<!DOCTYPE html>
  2<html lang="en">
  3  <head>
  4    <meta charset="utf-8" />
  5    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
  6
  7    <title>Organiser le développement en équipe avec git</title>
  8    <link rel="shortcut icon" href="./favicon.ico" />
  9    <link rel="stylesheet" href="./dist/reset.css" />
 10    <link rel="stylesheet" href="./dist/reveal.css" />
 11    <link rel="stylesheet" href="/_assets/./_themes/5ika.css" id="theme" />
 12    <link rel="stylesheet" href="./css/highlight/base16/zenburn.css" />
 13
 14
 15  </head>
 16  <body>
 17    <div class="reveal">
 18      <div class="slides"><section  data-markdown><script type="text/template">
 19
 20# **Organiser le développement en équipe avec git**
 21
 22À la fin de la master class, les participants seront en mesure de :
 23- Comprendre comment et pourquoi utiliser un modèle de branche git
 24- Utiliser les outils de gestion de projet de GitHub liés à la base de code
 25- Effectuer des tâches simples avec Docker
 26</script></section><section  data-markdown><script type="text/template">
 27# Tim Izzo
 28
 29- Ingénieur IT et développeur
 30- Travail chez [Octree](https://octree.ch) et en tant qu'indépendant
 31- Enseigne les réseaux et la sécurité IT
 32- Approche minimaliste et écologique du développement
 33
 34🦌 [5ika.ch](https://5ika.ch)<br/>
 35 [tim@5ika.ch](mailto:tim@5ika.ch)<br/>
 36👔 [LinkedIn](https://www.linkedin.com/in/tim-izzo/)
 37</script></section><section  data-markdown><script type="text/template">
 38Qui êtes-vous ?
 39</script></section><section  data-markdown><script type="text/template">
 40**Vous êtes membre d'une équipe de développement devant développer un site web.**
 41
 42Vous avez besoin de:
 43
 441. Organiser le développement à plusieurs pour ne pas vous marcher sur les pieds
 452. Tester votre site web pendant le développement pour s'assurer que tout fonctionne à chaque étape
 463. Déployer votre site web en production une fois qu'une version est prête
 47</script></section><section  data-markdown><script type="text/template">
 48Pour comprendre les différentes étapes, nous allons toutes et tous collaborer
 49sur une même base de projet:
 50
 51https://github.com/5ika/Deer
 52
 53<center>
 54
 55![Capture d'écran du site](img/deer.png)
 56
 57</center>
 58</script></section><section  data-markdown><script type="text/template">
 59# Créer un projet git
 60
 61```bash
 62# Je me déplace dans le dossier qui contient mon site
 63cd /home/tim/projets/Deer
 64# J'initialise git pour ce dossier
 65git init
 66# J'ajoute toutes les modifications à la zone de staging
 67git add -A
 68# Je crée un premier commit
 69git commit -m "🎉 First commit"
 70```
 71
 72> Pas besoin de réaliser cette étape de votre côté.
 73> Elle est à faire une seule fois par la personne qui initialise le projet.
 74</script></section><section  data-markdown><script type="text/template">
 75# Synchroniser le projet avec GitHub
 76
 77Dans un premier temps, je crée un nouveau projet sur GitHub
 78puis je connecte mon dépôt local avec le dépôt distant.
 79
 80```bash
 81# Je configure un dépôt distant (en utilisant l'adresse SSH plutôt que HTTP)
 82git remote add origin git@github.com:5ika/Deer.git
 83# Je push la branche locale 'main' sur le dépôt distant
 84git push -u origin main
 85```
 86
 87Le dépôt local correspond au dossier sur ma machine tandis que le dépôt distant correspond au projet GitHub.
 88
 89> Pas besoin de réaliser cette étape de votre côté.
 90> Elle est à faire une seule fois par la personne qui initialise le projet.
 91</script></section><section  data-markdown><script type="text/template">
 92# Récupérer le projet sur sa machine
 93
 94🫵 **À vous !**
 95
 96En tant que collaborateur/trice, vous pouvez récupérer le code du site
 97sur votre machine en le *clonant*.
 98
 99```bash
100# Je me déplace sur ma machine à l'endroit où je place mes projets
101cd /home/tim/projets
102# Je récupère le projet commun depuis GitHub
103git clone git@github.com:5ika/Deer.git
104# Je me déplace dans le nouveau dossier contenant le code
105cd Deer
106```
107</script></section><section  data-markdown><script type="text/template">
108# Exploration
109
110Les commandes suivantes nous permettent de constater ce qui se passe:
111
112```bash
113# Lister les fichiers et dossiers présents dans le projet
114ls -la
115# Voir les commits déjà faits sur le projet
116git log
117# Voir les modifications pas encore dans un commit
118git status
119```
120
121Ces commandes ne modifient rien. Elles servent juste à voir.
122On peut en abuser 😁
123</script></section><section  data-markdown><script type="text/template">
124Nous avons désormais toutes et tous une copie du même projet
125sur notre machine avec un seul commit: celui que j'ai fait.
126
127Maintenant, **comment ajouter du nouveau code dans notre projet ?**
128
129Que se passe-t-il si chacun.e fait un commit et le push sur GitHub ? 🤔
130</script></section><section  data-markdown><script type="text/template">
131<center>
132
133![](img/git_parallel.png)
134
135</center>
136</script></section><section  data-markdown><script type="text/template">
137# Les branches
138
139Comme les commits forment une suite ordonnée, on appelle un ensemble de commits une **branche**.
140
141Le dernier commit correspond à la version la plus actuelle de notre code.
142On nomme ce commit le *HEAD*. Cest le bout de la branche.
143
144![](img/git_branch.png)
145
146Par défaut, quand rien n'est précisé, les commits sont automatiquement ajoutés à la branche nommée *main*.
147</script></section><section  data-markdown><script type="text/template">
148# Les branches
149
150Il est possible de créer plusieurs branches pour paralléliser le travail sur une même base de code.
151
152![](img/git_branches.png)
153</script></section><section  data-markdown><script type="text/template">
154# Créer une nouvelle branche
155
156La commande suivante crée une nouvelle branche `my-new-branch` à partir du dernier
157commit de la branche `main`.
158
159```bash
160git checkout -b my-new-branch
161```
162
163Tous les commits qui seront faits ensuite seront placés sur cette nouvelle branche.
164</script></section><section  data-markdown><script type="text/template">
165# Se déplacer entre les branches
166
167Si on retire le `-b` dans la commande, on indique qu'on souhaite juste se déplacer
168d'une branche à une autre.
169
170```bash
171# Je me trouve sur la branche `my-new-branch`
172git checkout main
173# Je me trouve maintenant sur la branche `main`
174git checkout my-new-branch
175# Je me trouve sur la branche `my-new-branch`
176git checkout one-more-branch # Erreur car la branche `one-more-branch` n'existe pas
177git checkout -b  one-more-branch
178# Je me trouve sur la branche `one-more-branch`
179```
180</script></section><section  data-markdown><script type="text/template">
181Pour voir sur quelle branche on se trouve, on peut utiliser la commande suivante:
182
183```
184git branch
185```
186
187Cela retourne par exemple:
188
189```bash
190* main
191  my-new-branch
192  one-more-branch
193```
194
195J'ai donc 3 branches actuellement et je me trouve sur la branche *main* (celle indiquée par un `*`).
196</script></section><section  data-markdown><script type="text/template">
197# Supprimer une branche
198
199Pour supprimer une branche locale:
200
201```bash
202# D'abord, je me déplace sur une branche autre
203git checkout main
204# Ensuite, je retire la branche
205git branch -d one-more-branch
206# On peut vérifier avec
207git branch
208```
209</script></section><section  data-markdown><script type="text/template">
210# Pusher une nouvelle branche
211
212Quand on crée un nouvelle branche, elle n'existe que localement dans un premier temps.
213Comme un commit, il faut la *pusher* sur GitHub pour qu'elle soit visible par les autres devs.
214
215```bash
216git push -u origin my-new-branch
217```
218
219Ici, on indique que l'on veut pusher la branche `my-new-branch` vers le dépôt distant
220nommé `origin`.
221
222`origin` est un alias correspondant à notre projet commun sur GitHub.
223</script></section><section  data-markdown><script type="text/template">
224🫵 À vous maintenant de **créer une nouvelle branche** à partir de la branche *main* et de la **pusher sur GitHub**.
225
226Pour qu'on puisse s'y retrouver, nommer cette branche avec votre prénom, sans accent, sans majuscule et sans espace.
227
228Il faut donc entrer deux commandes que l'on a vu dans les slides précédentes.
229
230> Vous pouvez constater sur GitHub que votre branche s'y trouve bien pour vérifier.
231</script></section><section  data-markdown><script type="text/template">
232# Faire un commit
233
234Désormais, nous avons toutes et tous une branche à notre nom sur notre machine et sur GitHub.
235
236Pour le moment, cette branche est identique à la branche *main* car nous n'avons pas fait de
237commit dessus.
238
239🫵 De votre côté:
2401. Modifiez un petit peu le CSS ou le HTML du projet. Par exemple, changer la couleur de la tête du cerf ou un autre élément.
2412. Créez un nouveau commit avec votre modification (sur votre branche, pas sur *main*)
2423. Pusher ce commit sur GitHub
2434. Constater sur GitHub que votre commit est présent **au niveau de votre branche**
244</script></section><section  data-markdown><script type="text/template">
245# Faire un commit
246
247<center>
248
249![](img/git_steps.png)
250
251</center>
252</script></section><section  data-markdown><script type="text/template">
253# Code review: C'est quoi ?
254
255Dans une équipe de développement, pour assurer une bonne **qualité de code**
256et éviter que chaque dev porte seul.e la responsabilité du code qu'il ou elle produit,
257il est courant de faire du *code review*.
258
259Cela consiste à faire relire son code par une autre personne de l'équipe afin de
260s'assure que le code est bien fait, les choix sont bons, les règles de l'équipe
261sont respectées et que le cahier des charges est remplie.
262
263> Dans certains projets, il y a une personne spécifique qui s'occupe de faire
264> tout le code review. On la nomme *Mainteneur/euse"*.
265</script></section><section  data-markdown><script type="text/template">
266# Code review: C'est quand ?
267
268En tant que dev, nous faisons généralement du code review au moment où nous souhaitons
269que les modifications faites sur notre branche soient ajoutées sur la branche principale
270(*main*).
271
272Pour ce faire, nous créons une **Pull Request** sur GitHub. Une Pull Request est la
273manière de demander à l'équipe de dev de **merger** notre branche dans la branche principale.
274
275Cette fonctionnalité permet à des centaines de devs de collaborer sur un projet, notamment
276dans le monde de l'Open-Source.
277
278=> [Exemple avec le projet Caroster](https://github.com/octree-gva/caroster)
279</script></section><section  data-markdown><script type="text/template">
280# Créer une Pull Request
281
282On crée une Pull Request directement sur l'interface de GitHub, dans le menu *Pull Requests* du projet.
283
284On nous demande d'indiquer deux branches:
285- Un branche **source** qui correspond à la branche que l'on souhaite merger.
286- Une branche **destination** qui correspond à la branche qui doit recevoir les changements. Généralement, c'est *main*.
287
288🫵 **À vous** de créer une Pull Requests au niveau du projet GitHub commun pour demander que l'on merge
289votre branche dans la branche *main*.
290
291<aside class="notes"><p>Repasser sur quelques Pull Requests faites pour montrer la page d&#39;une Pull Request et le système de commentaires</p>
292</aside></script></section><section  data-markdown><script type="text/template">
293Imaginez la situation suivante :
294
2951. Alice a modifié la couleur de la tête du cerf ([ligne 101 de style.css](https://github.com/5ika/Deer/commit/be7f148d518c61fc77d18eab2154dcf6443be185#diff-b78be019f1dc6d57753ea900c3805b114cd53ab7c0db836cc081836df1b99b7aR101)) dans sa branche
2962. Bob a également modifié la couleur de la tête à la même ligne dans sa propre branche
2973. Les deux devs font une Pull Requests pour demander que l'on merge leur branche dans *main*
298
299Est-ce que vous voyez un problème ? 🤔
300</script></section><section  data-markdown><script type="text/template">
301# Conflits
302
303Cette situation s'appelle un **conflit**:
304
305Comme Alice et Bob travaillent en même temps, ils ne savent pas ce que l'autre fait.
306Quand on demande à git de merger leur travail, le programme ne sait pas comment faire car la machine
307est incapable de définir lequel des deux à le + raison.
308
309Il est donc nécessaire de passer par une action humaine pour résoudre cela.
310
3111. On merge une première branche dans *main* (disons, celle d'Alice). GitHub nous indique un conflit au niveau de la branche de Bob.
3122. Bob merge *main* (avec les modifications d'Alice) dans sa branche à lui.
3133. Bob résout les conflits entre l'état actuel de *main* et ses modifications puis push les corrections.
3144. On merge la deuxième branche dans *main*
315</script></section><section  data-markdown><script type="text/template">
316# Éviter les conflits
317
318Les conflits git ne sont pas désirables et en tant que dev, on cherche à en avoir le moins souvent possible.
319Pour cela, quelques règles à respecter:
320
321- Pullez souvent pour mettre à jour votre copie locale avec ce qu'il y a dans le dépôt commun
322- Il est préférable de faire beaucoup de petits commits avec peu de modifications que des commits avec énormément de modification: plus facile à débugger, à lire, à commenter et à revenir en arrière
323- Avoir une bonne gestion de projet pour éviter que deux personnes de l'équipe travaillent sur la même chose en même temps
324</script></section><section  data-markdown><script type="text/template">
325# Gestion de projet avec GitHub
326
327Suivant l'approche Agile / SCRUM, GitHub propose des outils au niveau d'un projet pour organiser le projet autour du code.
328
329Il y a notamment deux outils très utiles :
330
331- Les **Issues** qui permettent de lister des fonctionnalités à développer ou déclarer des bugs/problèmes
332- Les "**Projects**" qui permettent d'organiser les issues
333</script></section><section  data-markdown><script type="text/template">
334# Issues
335
336Les issues sont très utilisées. Très grossièrement, cela correspond à la liste des tâches de développement à faire
337pour faire avancer un projet.
338
339Leur utilisation est très flexible et chaque projet s'organise comme il le souhaite.
340En exemple dans ce cours, nous allons voir une utilisation compatible avec une approche Agile/SCRUM.
341</script></section><section  data-markdown><script type="text/template">
342# Étape 1: Créer les issues
343
344En début de projet, on crée une issue pour chaque fonctionnalité qu'on souhaite implémenter
345dans l'itération Agile à venir.
346
347🫵 Par équipe de 2, créez une issue décrivant une fonctionnalité originale à faire.
348Évitez d'avoir la même qu'un autre binôme.
349
350> Pas besoin de voir trop compliqué. Cela doit pouvoir être fait rapidement, en quelques lignes de CSS, HTML ou JS.
351
352Une fois l'issue créée:
353- Assignez les deux membres du binôme au niveau du champ *Assignees*
354- Assignez l'issue au *projet* "Développement du site web"
355- Au niveau du [projet Développement du site web](https://github.com/users/5ika/projects/1), glissez votre issue dans la colonne "In Progress"
356
357<aside class="notes"><p>Faire un exemple en //</p>
358</aside></script></section><section  data-markdown><script type="text/template">
359# Étape 2: Créer une branche
360
361À chaque fois qu'on implémente une nouvelle fonctionnalité, décrite dans une issue, on crée une nouvelle branche
362dans le dépôt avec un nom clair. Ces branches qui concernent de nouvelles fonctionnalités s'appellent
363des **feature branches**.
364
365🫵 Créez une branche sur laquelle vous allez prochainement modifier le code pour implémenter la fonctionnalité décrite
366dans votre issue. Vous pouvez donnez un nom clair à la branche. Par exemple `ajout-3e-oeil`.
367
368> Un seul des deux membres du binôme doit faire le travail mais les deux doivent comprendre ce qui est fait.
369</script></section><section  data-markdown><script type="text/template">
370# Étape 3: Développer !
371
372🫵 Sur votre machine, développez la fonctionnalité sur la bonne branche et pushez le ou les commits sur
373GitHub.
374</script></section><section  data-markdown><script type="text/template">
375# Étape 4: Créer une Pull Request
376
377🫵
378
3791. Créer une Pull Request pour merger votre branche dans *main*
3802. Assigner le membre du binôme qui n'a pas fait le développement à la PR (Pull Request)
3813. Sur la page projet "Développement du site web", glissez votre issue dans "In Review"
382</script></section><section  data-markdown><script type="text/template">
383# Étape 5: Code Review
384
385🫵 La personne assignée à la PR peut maintenant relire le code et éventuellement faire des commentaires
386si le travail est incomplet ou incorrect.
387
388Une fois que tout est bon, elle peut *merger* la Pull Request pour l'ajouter à *main*. Puis, on peut
389déplacer l'issue dans la colonne "Done" sur le projet.
390
391> À cette étape, il y aura surement des conflits et des résolutions à faire. Nous allons gérer cela
392> au cas par cas.
393</script></section><section  data-markdown><script type="text/template">
394# Bravo 🎉
395
396Nous avons développé ensemble une nouvelle version du site web.
397
398Le travail pratique d'aujourd'hui n'est pas si loin de la réalité.
399
400En général:
401- La création des issues est faite de manière plus réflechie en impliquant le Product Owner, le client et d'autres
402rôles
403- Le code review est une étape qui prend du temps et qui peut nécessiter plusieurs aller-retours
404</script></section><section  data-markdown><script type="text/template">
405# Liaison entre commits et issues
406
407Quand on crée une issue, il lui est attribué un numéro.
408Par exemple, l'issue https://github.com/5ika/Deer/issues/1 a obtenu le numéro `1`.
409
410Quand on fait un commit, dans le *commit message* on peut ajouter `#1` pour indiquer
411que ce commit est lié à notre issue. GitHub est ensuite capable de comprendre cela
412et de faire des liens sur l'interface.
413
414C'est facultatif mais c'est très utile quand on avance dans un projet afin de
415garder un historique cohérent et de pouvoir s'y retrouver dans le futur.
416
417<aside class="notes"><p>Faire une démonstration</p>
418</aside></script></section><section  data-markdown><script type="text/template">
419# Bugs 🐛
420
421Les bugs font parties intégrantes du développement.
422Ils peuvent être trouvés par différentes personnes: devs, testeurs, clients, utilisateurs/trices,
423contributeurs/trices,...
424
425Les issues servent également à relever et gérer les bugs: quand une personne rencontre un souci,
426elle peut créer une issue détaillant son bug.
427On peut ensuite gérer un bug comme une feature avec notre gestion de projet.
428
429La modification du code relatif est faite sur une *fix branch* qui sera aussi soumise à
430travers une Pull Request.
431
432<aside class="notes"><p>Montrer des exemples d&#39;issues bug dans un projet Open-Source sur GitHub</p>
433</aside></script></section><section  data-markdown><script type="text/template">
434![Exemple de mauvaise issue de bug](img/bug_bad.png)
435</script></section><section  data-markdown><script type="text/template">
436# Relever un bug
437
438Quand on crée une issue de bug, il est important d'être le plus clair possible pour
439faciliter la résolution.
440
441Il est important de fournir:
442
443- Une description claire du bug
444- Les étapes permettant de **reproduire** le problème
445- Une description de ce qui est attendu
446- Des captures d'écran ou une vidéo pour montrer
447
448[Exemple de bug dans le projet Strapi](https://github.com/strapi/strapi/issues/16539)
449</script></section><section  data-markdown><script type="text/template">
450Sur un projet git, tout le monde est libre de créer des branches et les nommer comme il ou elle veut.
451Quand on travaille à plusieurs et/ou sur une longue période, cela devient vite chaotique 💥.
452
453![Branches chaos](img/branches_chaos.png)
454</script></section><section  data-markdown><script type="text/template">
455En équipe, il faut donc se mettre d'accord sur une manière de gérer les branches afin
456de rester efficaces.
457
458On appelle cela un **modèle de branche** 🌳
459</script></section><section  data-markdown><script type="text/template">
460Le modèle de branche le plus utilisé est le *Feature Branch Worflow*.
461
462![](https://wac-cdn.atlassian.com/dam/jcr:09308632-38a3-4637-bba2-af2110629d56/07.svg?cdnVersion=1004)
463
464... et c'est celui que nous avons déjà appris précédemment.
465
466C'est le fait d'utiliser une autre branche que la principale pour faire des modifications:
467feature branch, fix branch,...
468
469> Ce modèle est la base des autres modèles, il est donc important de bien le comprendre.
470> [Cette documentation](https://www.atlassian.com/git/tutorials/comparing-workflows/feature-branch-workflow) est
471> particulièrement bien faite pour comprendre (en anglais).
472</script></section><section  data-markdown><script type="text/template">
473# Feature Branch Worfklow
474
4751. Je crée une branche annexe (feature ou fix) dans laquelle je fais mes modifications
4762. Je crée une Pull Request pour demander que l'on merge ma branche dans *main*
4773. Une autre personne vérifie mon code et je l'affine si nécessaire
4784. L'autre personne valide la Pull Request et les commits de ma branche sont ajoutés à *main*
4795. Je supprime ma branche annexe (si ce n'est pas fait automatiquement)
480</script></section><section  data-markdown><script type="text/template">
481# L'ancien modèle 'Gitflow'
482
483![Ancien modèle Gitflow](https://wac-cdn.atlassian.com/dam/jcr:34c86360-8dea-4be4-92f7-6597d4d5bfae/02%20Feature%20branches.svg?cdnVersion=1004)
484</script></section><section  data-markdown><script type="text/template">
485# Et dans les projets Open-Source ?
486
487Dans les projets Open-Source, il n'y a pas une équipe précise qui travaille sur le code car
488tout le monde peut participer et proposer des modifications.
489
490**Mais comment faire pour autoriser tout le monde à modifier le code sans perdre le contrôle de son app ?**
491</script></section><section  data-markdown><script type="text/template">
492# Fork ! 🍴
493
494GitHub nous permet de *forker* des projets.
495
496"Forker" signifie *copier tout le projet et son historique vers son propre espace*.
497
498En forkant un projet, j'obtiens une copie de tout le code de ce projet sur laquelle
499j'ai le droit de faire ce que je veux.
500
501<aside class="notes"><p>Faire un exemple de fork de Caroster</p>
502</aside></script></section><section  data-markdown><script type="text/template">
503# Forking workflow
504
505Le forking workflow est un modèle de branche très semblable au feature branch workflow
506mais considère des branches qui ne sont pas dans le même projet.
507</script></section><section  data-markdown><script type="text/template">
508Par exemple, je souhaite proposer une modification de code au projet Strapi.
509Voilà les étapes qui je réalise:
510
5111. Je fork le [dépôt de Strapi](https://github.com/strapi/strapi) pour obtenir [ma propre copie](https://github.com/5ika/strapi)
5122. Sur la branche *main* de mon dépôt, je push des commits
5133. Une fois que je suis satisfait des modifications, je crée [une Pull Request](https://github.com/strapi/strapi/pull/14280) au niveau du dépôt officiel de Strapi pour demander
514aux devs de Strapi de merger la branche *main* de mon dépôt (`5ika:main`) dans la branche *main* du dépôt officiel (`strapi:main`)
515
516Ensuite, un mainteneur de Strapi va regarder ce que je propose comme modification et me faire des commentaires.
517Selon ses retours, je vais ajuster mon code jusqu'à ce que ça corresponde aux attentes du projet officiel
518jusqu'à ce que la branche soit mergée.
519</script></section><section  data-markdown><script type="text/template">
520🫵 Forkez le projet [Deer](https://github.com/5ika/Deer/) avec votre utilisateur GitHub et remarquez ce qui fait.
521
522Vous pouvez maintenant modifier le code comme vous voulez, sur les branches que vous voulez car
523vous êtes sur une copie du projet principal.
524</script></section><section  data-markdown><script type="text/template">
525🫵 Faites un commit sur la branche *main* de vôtre copie de dépôt Deer avec une petite modification de code
526puis créez une Pull Request au niveau du [dépôt principal](https://github.com/5ika/Deer/) pour me soumettre
527votre proposition de changement.
528</script></section><section  data-markdown><script type="text/template">
529Des questions concernant git et l'utilisation des branches 
530</script></section><section  data-markdown><script type="text/template">
531# Oh Shit, Git !?! 💩
532
533Git est puissant et très élastique mais il peut arriver quon se perde dans son utilisation et dans les pires des cas, quon perde des modifications.
534
535Un site référencie les plus grosses mauvaises manipulations et comment les résoudre:
536http://ohshitgit.com/ </script></section></div>
537    </div>
538
539    <script src="./dist/reveal.js"></script>
540
541    <script src="./plugin/markdown/markdown.js"></script>
542    <script src="./plugin/highlight/highlight.js"></script>
543    <script src="./plugin/zoom/zoom.js"></script>
544    <script src="./plugin/notes/notes.js"></script>
545    <script src="./plugin/math/math.js"></script>
546    <script>
547      function extend() {
548        var target = {};
549        for (var i = 0; i < arguments.length; i++) {
550          var source = arguments[i];
551          for (var key in source) {
552            if (source.hasOwnProperty(key)) {
553              target[key] = source[key];
554            }
555          }
556        }
557        return target;
558      }
559
560      // default options to init reveal.js
561      var defaultOptions = {
562        controls: true,
563        progress: true,
564        history: true,
565        center: true,
566        transition: 'default', // none/fade/slide/convex/concave/zoom
567        slideNumber: true,
568        plugins: [
569          RevealMarkdown,
570          RevealHighlight,
571          RevealZoom,
572          RevealNotes,
573          RevealMath
574        ]
575      };
576
577      // options from URL query string
578      var queryOptions = Reveal().getQueryHash() || {};
579
580      var options = extend(defaultOptions, {"transition":"fade"}, queryOptions);
581    </script>
582
583
584    <script>
585      Reveal.initialize(options);
586    </script>
587  </body>
588</html>