Git Repositories

Formation et TP pour concepts avancés master
authorCyrille Pontvieux <cyrille@enialis.net>
Wed, 27 Sep 2017 14:43:55 +0000 (16:43 +0200)
committerCyrille Pontvieux <cpontvieux@systra.com>
Fri, 29 Sep 2017 06:08:06 +0000 (08:08 +0200)
37 files changed:
.gitignore
installation/INSTALL.html [new file with mode: 0644]
installation/windows/git-eol.png [deleted file]
installation/windows/git-path-bash.png [deleted file]
installation/windows/git-ssh.png [deleted file]
make.sh
supports/.gitignore
supports/advanced/cc-by-sa-80x15.png [new file with mode: 0644]
supports/advanced/git.png [new file with mode: 0644]
supports/advanced/markdown-logo.png [new file with mode: 0644]
supports/advanced/requirements.txt [deleted file]
supports/advanced/slides_git_advanced.cfg
supports/advanced/slides_git_advanced.md
supports/advanced/slides_git_advanced_embed.cfg [new file with mode: 0644]
supports/advanced/support_tp_advanced.md [deleted file]
supports/advanced/tp_git_advanced.cfg [new file with mode: 0644]
supports/advanced/tp_git_advanced.md [new file with mode: 0644]
supports/advanced/tp_git_advanced_embed.cfg [new file with mode: 0644]
supports/basic/slides_git_basic.cfg
supports/basic/slides_git_basic.md
supports/basic/slides_git_basic_embed.cfg [new file with mode: 0644]
supports/basic/tp_git_basic.cfg
supports/basic/tp_git_basic.md
supports/basic/tp_git_basic_embed.cfg [new file with mode: 0644]
supports/blue/base.html [moved from supports/viseo/base.html with 100% similarity]
supports/blue/css/base.css [moved from supports/viseo/css/base.css with 100% similarity]
supports/blue/css/print.css [moved from supports/viseo/css/print.css with 100% similarity]
supports/blue/css/screen.css [moved from supports/viseo/css/screen.css with 100% similarity]
supports/blue/css/theme.css [moved from supports/viseo/css/theme.css with 99% similarity]
supports/blue/js/slides.js [moved from supports/viseo/js/slides.js with 96% similarity]
tp/.gitignore [new file with mode: 0644]
tp/advanced/.gitignore [new file with mode: 0644]
tp/advanced/md2html
tp/basic/md2html
tp/basic/tarte_aux_poireaux.txt [new file with mode: 0644]
tp/create-remotes.sh [new file with mode: 0755]
tp/serve-remotes.sh [new file with mode: 0755]

index 22cc836..aa1ec1e 100644 (file)
@@ -1,3 +1 @@
-*.html
-*.zip
-*.exe
+*.tgz
diff --git a/installation/INSTALL.html b/installation/INSTALL.html
new file mode 100644 (file)
index 0000000..613494d
--- /dev/null
@@ -0,0 +1,70 @@
+
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset='utf-8'>
+    <link href="gfm.css" media="all" rel="stylesheet" />
+  </head>
+  <body>
+    <div class="markdown-body">
+<h1>Installation sous Linux</h1>
+<p>Sous Linux, il suffit d'installer les paquets pour Git, et Python pour le TP.<br />
+La plupart des distributions installent ces paquets par défaut.<br />
+Il n'y a donc en général <strong><em>rien à faire</em></strong>.</p>
+<p>Voici les paquets <strong>git</strong> pour les principales distributions :</p>
+<table>
+<thead>
+<tr>
+<th align="center">Debian<em>-like</em> :</th>
+<th align="center">Fedora<em>-like</em></th>
+<th align="center">Slackware<em>-like</em></th>
+<th align="center">Arch<em>-like</em></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center"><code>git</code><br/>(<code>git-core</code> dans les vieilles Debian)</td>
+<td align="center"><code>git</code></td>
+<td align="center"><code>git</code></td>
+<td align="center"><code>git</code></td>
+</tr>
+<tr>
+<td align="center"><code>gitk</code></td>
+<td align="center"><code>gitk</code></td>
+<td align="center"></td>
+<td align="center"><code>tk</code><br/>(pour <code>gitk</code> et <code>git gui</code>)</td>
+</tr>
+<tr>
+<td align="center"><code>git-gui</code></td>
+<td align="center"><code>git-gui</code></td>
+<td align="center"></td>
+<td align="center"><code>subversion</code><br/>(pour <code>git svn</code>)</td>
+</tr>
+<tr>
+<td align="center"><code>git-svn</code></td>
+<td align="center"><code>git-svn</code></td>
+<td align="center"></td>
+<td align="center"></td>
+</tr>
+<tr>
+<td align="center"><em>OU</em></td>
+<td align="center"><em>OU</em></td>
+<td align="center"></td>
+<td align="center"></td>
+</tr>
+<tr>
+<td align="center"><code>git-all</code></td>
+<td align="center"><code>git-all</code></td>
+<td align="center"></td>
+<td align="center"></td>
+</tr>
+</tbody>
+</table>
+<p>Pour <strong>python</strong> c'est en général déjà installé sinon il faut les paquets :</p>
+<ul>
+<li><code>python</code></li>
+<li><code>pip</code></li>
+</ul>
+    </div>
+  </body>
+</html>
diff --git a/installation/windows/git-eol.png b/installation/windows/git-eol.png
deleted file mode 100644 (file)
index 67b555e..0000000
Binary files a/installation/windows/git-eol.png and /dev/null differ
diff --git a/installation/windows/git-path-bash.png b/installation/windows/git-path-bash.png
deleted file mode 100644 (file)
index e1f4fdc..0000000
Binary files a/installation/windows/git-path-bash.png and /dev/null differ
diff --git a/installation/windows/git-ssh.png b/installation/windows/git-ssh.png
deleted file mode 100644 (file)
index d34c91c..0000000
Binary files a/installation/windows/git-ssh.png and /dev/null differ
diff --git a/make.sh b/make.sh
index 60d55ee..d523ff7 100755 (executable)
--- a/make.sh
+++ b/make.sh
@@ -1,41 +1,28 @@
 #!/bin/sh
 
 usage() {
-       echo "make.sh TARGET
+  echo "make.sh TARGET
 TARGET:
-  stagiaire_git_basic
-  stagiaire_git_advanced
+  basic
+  advanced
 "
 }
 
-stagiaire_git_basic() {
-       D=$(mktemp -d)
-  curr_dir="$PWD"
-       (
-    cd $D
-    darkslide -c -i -l no -t "$curr_dir"/supports/viseo -x fenced_code,tables,dot,attr_list -d slides_git_basic.html "$curr_dir"/supports/basic/slides_git_basic.md
-    darkslide -c -i -l no -t "$curr_dir"/supports/viseo -x fenced_code,tables,attr_list -d tp_git_basic.html "$curr_dir"/supports/basic/tp_git_basic.md
-    rm -r *.png theme
-    cp -r "$curr_dir"/installation ./
-    cp -r "$curr_dir"/tp/basic ./tp
-    zip -0r "$curr_dir"/stagiaire_git_basic.zip *
+stagiaire_git() {
+  stage=$1
+  D=$(mktemp -d)
+  mkdir $D/stagiaire_git_${stage}
+  (
+    cd supports/${stage}
+    $(which darkslide) slides_git_${stage}_embed.cfg
+    $(which darkslide) tp_git_${stage}_embed.cfg
   )
-       rm -r $D
-}
-
-stagiaire_git_advanced() {
-       D=$(mktemp -d)
-  curr_dir="$PWD"
-       (
-    cd $D
-    darkslide -c -i -l no -t "$curr_dir"/supports/viseo -x fenced_code,tables,dot,attr_list -d slides_git_advanced.html "$curr_dir"/supports/basic/slides_git_advanced.md
-    darkslide -c -i -l no -t "$curr_dir"/supports/viseo -x fenced_code,tables,attr_list -d tp_git_advanced.html "$curr_dir"/supports/basic/tp_git_advanced.md
-    rm -r *.png theme
-    cp -r "$curr_dir"/installation ./
-    cp -r "$curr_dir"/tp/advanced ./tp
-    zip -0r "$curr_dir"/stagiaire_git_advanced.zip *
-  )
-       rm -r $D
+  cp supports/${stage}/*.html $D/stagiaire_git_${stage}/
+  cp -r installation $D/stagiaire_git_${stage}/
+  cp -r explain-git-with-d3 $D/stagiaire_git_${stage}/
+  cp -r tp/${stage} $D/stagiaire_git_${stage}/tp
+  tar caf stagiaire_git_${stage}.tgz -C $D stagiaire_git_${stage}
+  rm -r $D
 }
 
 ACTION=$1
@@ -43,10 +30,10 @@ if [ -z "$ACTION" ]; then
   usage
   exit 1
 fi
-if [ "$ACTION" = "stagiaire_git_basic" ]; then
-  stagiaire_git_basic
-elif [ "$ACTION" = "stagiaire_git_advanced" ]; then
-  stagiaire_git_advanced
+if [ "$ACTION" = "basic" ]; then
+  stagiaire_git basic
+elif [ "$ACTION" = "advanced" ]; then
+  stagiaire_git advanced
 else
   usage
   exit 1
index e5521f9..e3b219e 100644 (file)
@@ -1 +1,2 @@
 *.dot.png
+*.html
diff --git a/supports/advanced/cc-by-sa-80x15.png b/supports/advanced/cc-by-sa-80x15.png
new file mode 100644 (file)
index 0000000..c1b97c4
Binary files /dev/null and b/supports/advanced/cc-by-sa-80x15.png differ
diff --git a/supports/advanced/git.png b/supports/advanced/git.png
new file mode 100644 (file)
index 0000000..ed75aa7
Binary files /dev/null and b/supports/advanced/git.png differ
diff --git a/supports/advanced/markdown-logo.png b/supports/advanced/markdown-logo.png
new file mode 100644 (file)
index 0000000..93e729b
Binary files /dev/null and b/supports/advanced/markdown-logo.png differ
diff --git a/supports/advanced/requirements.txt b/supports/advanced/requirements.txt
deleted file mode 100644 (file)
index 2f9912f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-landslide
index b3c2e34..02f5b13 100644 (file)
@@ -1,7 +1,7 @@
 [landslide]
 source = slides_git_advanced.md
 destination = slides_git_advanced.html
-theme = ../viseo
+theme = ../blue
 embed = false
 relatives = true
 extensions = fenced_code,tables,dot,attr_list
index bf04b2a..ad3f795 100644 (file)
@@ -76,8 +76,7 @@
     - modifiées
     - supprimées
 1. un auteur
-    - nom
-    - courriel
+    - nom + courriel
 1. une date
 1. des parents
     - **0** : *nœud* racine
@@ -613,7 +612,7 @@ $ git config --global diff.lo.textconv 'soffice -env:UserInstallation=file:///tm
     - On peut voir où git en est avec `git bisect view`. On s'arrête avec `git bisect reset`.
 - Avec un script **automatique** (`0` → ok, `1` → ko, `125` → skip) :
     - `git bisect start`
-    - `git bisect run mon-scrip.sh`
+    - `git bisect run mon-script.sh`
 # Presenter Notes
 - Utilisé pour trouver le commit :
     - qui a créé une régression
@@ -707,26 +706,20 @@ $ git config --global diff.lo.textconv 'soffice -env:UserInstallation=file:///tm
 ---
 
 # subtree/submodule
-TODO
+- *Sous-modules* : dépôt git dans sous-répertoire dépôt git
+    - Fichier `.gitmodules` pour indiquer le *mapping*
+    - Après un `clone`, il faudra lancer `git submodule init` et `git submodule fetch`. Ou sinon ajouter l'option `--recursive` sur `clone`.
+    - Changer de **branche est compliqué**, les **conflits** des sous-modules sont **plus compliqués** à résoudre
+- Alternative : stratégie `subtree` de `merge` :
+    - `git read-tree --prefix=sous-rep/ -u branche-dépôt-externe`
+    - `git merge --squash -s subtree --no-commit branche-dépôt-externe`
 
----
-
-# Plate-formes
-.fx: chapter
-
----
-
-# github
-TODO
-
-- fork
-- pull request
-- merge request
-
----
-
-# gitlab et gitblit
-TODO
+# Presenter Notes
+- `git submodule update --remote [--merge|--rebase]` pour `fetch` dans les sous-modules.
+- Les sous-modules sont en `detached HEAD`, il faut checkouter une branche avant de faire des commits.
+- `git push --recurse-submodules=check|on-demand` pour prendre en compte les sous-modules.
+- Attention aux déplacements entre sous-rep et sous-modules et entre des branches avec ou sans le sous-module.
+- `git remote add rack_remote git@github.com:schacon/rack.git` puis `co -b rack_branch rack_remote/master`
 
 ---
 
diff --git a/supports/advanced/slides_git_advanced_embed.cfg b/supports/advanced/slides_git_advanced_embed.cfg
new file mode 100644 (file)
index 0000000..2cfc7cc
--- /dev/null
@@ -0,0 +1,8 @@
+[landslide]
+source = slides_git_advanced.md
+destination = slides_git_advanced.html
+theme = ../blue
+embed = true
+relatives = true
+extensions = fenced_code,tables,dot,attr_list
+linenos = no
diff --git a/supports/advanced/support_tp_advanced.md b/supports/advanced/support_tp_advanced.md
deleted file mode 100644 (file)
index 9a92dd5..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-# Formation Avancé – Support
-
-Édition de recettes de cuisine au format Markdown
-
-Prérequis : avoir l'installation de git, python et pip sur votre poste.
-
-Le but de ce TP va être de manipuler des fichiers sources pour les manipuler sous git. Afin de ne pas privilégier un langage de développements, tous les fichiers manipulés vont être des fichiers texte .md (MarkDown) permettant la publication de document formatés.
-
-# Mise en place de l'environnement
-
-## dézipper le support stagiaire sur votre home :
-~/formation_git/
-l'arbrescence du tp est la suivante :
-~/formation_git/tp/advanced
-
-## De préférence mettre en place un prompt git (linux) TODO 
-
-## Initialiser le dépôt, créer un commit avec le contenu du zip
-Placez vous en racine de ce qui sera votre dépôt : ~/formation_git/tp/advanced
-Créer le commit initial en initiant le dépôt (oublier pas d'indiquer à Git votre identité).
-Ajouter un fichier .md dans le répertoire src/ (la recette de la tarte Tatin par exemple) et réaliser un second commit.
-
-Questions :
-- sur quelle branche vous trouvez-vous ? (master)
-- quel est le remote associé ? (aucun)
-
-# Analyse du stockage de git
-## Trouver sur quoi pointe HEAD dans le répertoire .git/
-       Placez-vous sur le premier commit : git checkout HEAD^ (pas oublié le chapeau sinon c'est moins rigolo) et constater le message alarmant de git.
-       Sur quoi pointe maintenant HEAD dans le répertoire .git/ ?
-       En quoi est-ce gênant de réaliser d'autres commit dans cet état ?
-       Revenez sur master
-## Qu'est-ce qu'un commit pour git et comment sont stockés les fichiers versionnés ?
-       Afficher le type d'objet référencé par HEAD/master
-    $ git cat-file -t $(git rev-parse HEAD)
-       Trouver le fichier correspondant à cet objet dans .git/objects/
-       Afficher le contenu de l'objet référencé par HEAD/master
-    $ git cat-file -p $(git rev-parse HEAD)
-       
-## Voir le contenu des fichiers de branches :
-    $ cat .git/refs/heads/master 
-
-créer une branche manuellement pour tester
-    $  echo [votre hash de commit]  > .git/refs/heads/toto
-
-Lister les branches
-    $ git branch
- On a créé une branche sans commande git !
-
-# Rebase interactif
-Pour ceux qui ne sont pas à l'aise avec vim, vous pouvez configurer votre éditeur texte préféré avec par exemple la commande : 
-    $git config --global core.editor gedit
-ou
-    $export GIT_EDITOR=gedit
-
-- Créer une branche (crepes) et placez-vous dessus
-- Créer des commits avec les fichiers suivants (une crêpe par commit) :
-- crêpe chocolat
-- crêpe au fromage (comté)
-- crêpe au fromage de chèvre
-- crêpe à la banane
-- crêpe au jambon
-- crêpe à la crème de marron (avec ingrédient : marrons)
-- crêpe complète (jambon, fromage, œufs)
-- crêpe banane/chocolat (variante de la crêpe banane, à ajouter dans le fichierde la crêpe banane)
-- correction sur la crêpe à la crème de marron (marron → châtaigne)
-- Revenir sur master et ajouter un commit sur la recette de la tarte au citron meringuée. (Note : on a donc un commit qui diverge de la branche principale)
-- Rebaser la branche crepes sur master de manière à la faire partir depuis le commit sur la tarte au citron meringuée.
-- Rebaser de manière interactive la branche crepes de manière à avoir les commits suivants dans cet ordre :
-- Les crêpes sucrées d'abord
-- Un seul commit pour la crêpe à la banane et sa variante avec chocolat (et une description du commit qui correspond)
-- Un seul commit pour la crêpe à la crème de marron
-- La recette sur la crêpe complète ne mentionne pas les champignons, rajoutez-les
-
-## Le rebase de branche
-
-- Créer une branche (beurrer_les_crepes) et placez-vous dessus
-Ajouter une noix de beurre sur les crèpes sucrées (à la fin pour avoir un conflit)
-
-- repartir de la branche crepes, Créer une branche (crepes_sucrees) et placez-vous dessus
-Ajouter « sucrer la pâte » sur les crêpes sucrées (à la fin pour avoir un conflit)
-- je créée une nouvelle branche beurrer_les_crepes_avant_rebase pour historique))
-
-- **Rebasez** beurrer_les_crepes sur crepes_sucrees
-- résoudre les conflits
-
-
-Utilisation de HEAD^
-- créer un fichier vide xxx.md, le commiter
-- Supprimer ce commit en utilisant HEAD^
-
-    $git reset --hard HEAD^
-
-Utilisation de HEAD~2 (ou HEAD^^ )
-- Fusionnez les 2 derniers commit.
-
-    $ git rebase -i HEAD~2
-
-Utilisation de git reflog
-- Le commit que l'on a supprimé n'est pas complètement perdu lancer reflog pour trouver la référence pour ensuite picorer le commit correspondant.
-    $ git reflog
-    $ git chery-pick <N° hash>
-
-# Workflow
-
-## Workflow avec une branche de développements + une branche par feature.
-On commence par un workflow classique une branche dev + une branche par fonction avec merge fast forward.
-
-Créer une branche « dev » à partir de la branche crèpe
-La branche « crepes_sucrees » est une feature, mergez la au développement.
-Supprimez les branches une fois qu'elles sont mergées.
-Question : y a-t-il encore des branches non mergées ?
-
-Note : on peut également choisir de rebaser les branches de feature avant le merge, ou aussi de merger sans fast-forward (forcer le commit de merge) 
-
-## Workflow avec une branche de production en plus
-// variante workflow avec branche de prod
-Créer la branche « prod »
-
-     $ git checkout --orphan prod
-Avec un commit initial vide
-     $ git reset
-     $ git commit –allow-empty
-
-Ajouter une version dans la branche de production
-     $ git merge dev --no-ff -X theirs 
-     $ git tag crepe_v1
-
-A chaque version on ajoute donc un commit de merge  (sans fast forward) qui supporte le tag de version. Aucun commit ayant du contenu ne se trouve sur la branche de production. Si on a besoin d'un commit rapidement, on peut opter pour le hotfix comme présenté ci-dessous.
-
-## Ajout d'un « hotfix » à 2 branches
-La prod plante !
-On part de la branche de prod pour créer la branche hotfix_beurresel, et on va ajouter la galette beurre sel en urgence.
-
-// variante avec hotfix en plus
diff --git a/supports/advanced/tp_git_advanced.cfg b/supports/advanced/tp_git_advanced.cfg
new file mode 100644 (file)
index 0000000..ff3fbf1
--- /dev/null
@@ -0,0 +1,8 @@
+[landslide]
+source = tp_git_advanced.md
+destination = tp_git_advanced.html
+theme = ../blue
+embed = false
+relatives = true
+extensions = fenced_code,tables,attr_list
+linenos = no
diff --git a/supports/advanced/tp_git_advanced.md b/supports/advanced/tp_git_advanced.md
new file mode 100644 (file)
index 0000000..d057e82
--- /dev/null
@@ -0,0 +1,311 @@
+# TP Git<br>Concepts avancés
+.fx: first-slide
+
+<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/deed.fr"><img alt="CC-by-sa" style="display: inline;" src="cc-by-sa-80x15.png" title="La présentation « Git Basic » de Cyrille Pontvieux est mis à disposition selon les termes de la licence Creative Commons Attribution - Partage dans les Mêmes Conditions 4.0 International"/></a>
+
+<a href="mailto:cyrille@enialis.net">Cyrille Pontvieux</a>
+
+<a href="https://github.com/jrd">Github</a>
+
+---
+
+# Introduction
+.fx: chapter
+
+---
+
+## Recettes de cuisine en *Markdown*
+.fx: table-full-width
+
+Le but de ce TP va être de gérer des fichiers sources pour les manipuler sous **git**.
+
+Afin de ne pas privilégier un langage de développements, tous les fichiers manipulés vont être des fichiers texte **.md** (format [MarkDown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)) permettant la publication de document formatés.
+
+| ![](git.png) | ![](markdown-logo.png) |
+| :---: | :---: |
+
+---
+
+## Mise en place de l'environnement 
+.fx: top
+
+Les composants suivants sont requis :
+
+- git
+- python
+- pip
+
+L'installation de ces composants sont détaillés par plateforme dans le fichier **INSTALL.html**
+
+- Aller dans le répertoire `stagiaire_git_advanced/tp`
+- Installer les dépendances python :  
+`pip install --user -r requirements.txt`
+- Configurer votre `~/.gitconfig` avec votre nom et courriel
+- Configurer votre [prompt Git](https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh)
+
+---
+
+# Initialiser le dépôt
+
+On va créer des recettes de crêpes.
+
+- Cloner le dépôt en utilisant votre numéro de stagiaire :  
+`$ git clone git://10.20.30.40/advanced-N.git`
+- Créer un premier commit avec le contenu du zip
+    - Placez vous en racine de ce qui sera votre dépôt
+    - Créer le commit initial en ajoutant tous les fichiers (n'oublier pas les fichiers cachés)
+- Ajouter un fichier `.md` dans le répertoire `src/`
+- Réaliser un second commit.
+
+# Presenter Notes
+- sur quelle branche vous trouvez-vous ? (master)
+- quel est le remote associé ? (celui sur le poste du formateur)
+
+---
+
+# Analyse du stockage de git<br>Plomberie de git
+.fx: chapter
+
+---
+
+## Où est la tête ?
+- Trouver sur quoi pointe `HEAD` dans le répertoire `.git/`
+- Placez-vous sur le premier commit :
+`git checkout HEAD^` (ne pas oublier le chapeau sinon c'est moins rigolo)
+- Constater le message alarmant de git.
+
+- Sur quoi pointe maintenant HEAD dans le répertoire `.git/` ?
+- En quoi est-ce gênant de réaliser d'autres commit dans cet état ?
+- Revenez sur `master`
+
+# Presenter Notes
+- On peut aussi utiliser `git log` ou `gitk`/`gitg` qui vont nous informer sur quoi pointe la tête.
+
+---
+
+## Qu'est-ce qu'un commit pour git
+Comment sont stockés les fichiers versionnés ?
+
+- Afficher le `sha1` d'une référence avec
+`$ git rev-parse HEAD^`
+- Afficher le type d'objet référencé par `HEAD` / `master`  
+`$ git cat-file -t $(git rev-parse HEAD)`
+- Trouver le fichier correspondant à cet objet dans `.git/objects/`
+- Afficher le contenu de l'objet référencé par `HEAD` / `master`  
+`$ git cat-file -p $(git rev-parse master)`
+
+# Presenter Notes
+- On peut utiliser `--short` avec `rev-parse`
+- Il existe aussi `--symbolic`
+- Le format de git est documenté, on pourrait le lire avec un simple [script python](https://gist.github.com/leonidessaguisagjr/594cd8fbbc9b18a1dde5084d981b8028)
+- Faire un `git cat-file -p` jusqu'à afficher le contenu de votre `.md`
+
+---
+       
+## Qu'est-ce qu'une branche pour git
+- Voir le contenu des fichiers de branches :  
+`$ cat .git/refs/heads/master`
+- Créer une branche manuellement pour tester  
+`$ echo [votre hash de commit]  > .git/refs/heads/toto`
+- Lister les branches  
+`$ git branch`
+- On a créé une branche sans commande git !
+
+# Presenter Notes
+- On peut faire une branche sur `git rev-parse HEAD^`
+- Demander aux stagiaires de se placer temporairement sur cette branche pour voir qu'elle est pleinement fonctionnelle
+
+---
+
+# Rebase interactif<br>ou<br>« Comment nettoyer son historique ? »
+.fx: chapter
+
+---
+
+## Prérequis
+
+Git a souvent besoin que vous saisissiez du texte et pour cela ouvre un éditeur texte. Par défaut c'est `vim`.
+
+Pour ceux qui ne sont pas à l'aise avec `vim`, vous pouvez configurer votre éditeur texte préféré avec par exemple la commande :  
+`$ git config --global core.editor gedit`  
+ou  
+`$ export GIT_EDITOR=gedit`  
+Ajouter également cette ligne dans votre `~/.bashrc` pour que ça reste permanent.
+
+Vous pouvez aussi utiliser `nano` ou encore `mousepad` par exemple.
+
+---
+
+## Historique brouillon
+- Créer une branche (`crepes`) et placez-vous dessus.
+- Créer les commits suivants (une crêpe par commit) :
+    - crêpe chocolat
+    - crêpe au fromage (comté)
+    - crêpe au fromage de chèvre
+    - crêpe à la banane
+    - crêpe au jambon
+    - crêpe à la crème de marron (avec ingrédient : marrons)
+    - crêpe complète (jambon, fromage, œufs)
+    - crêpe banane/chocolat (variante de la crêpe banane, à ajouter dans le fichierde la crêpe banane)
+    - correction sur la crêpe à la crème de marron (marron → châtaigne)
+
+---
+
+## Rebase -i
+- Revenir sur `master` et ajouter un commit sur la recette de la *tarte au citron meringuée*.  
+(Note : on diverge donc de la branche principale)
+- *Rebaser* la branche `crepes` sur `master` de manière à la faire partir depuis le commit sur *la tarte au citron meringuée*.
+- *Rebaser* de manière **interactive** la branche `crepes` de manière à avoir les commits suivants dans cet ordre :
+    - Les crêpes **sucrées** d'abord
+    - Un seul commit pour la crêpe à la **banane** et sa variante avec **chocolat** (et une description du commit qui correspond)
+    - Un seul commit pour la crêpe à la **crème de marron**
+    - La recette sur la crêpe **complète** ne mentionne pas les **champignons**, rajoutez-les
+
+# Presenter Notes
+- pick chocolat
+- pick banane
+- squash banane/chocolat
+- pick marron
+- fixup châtaigne
+- pick fromage/comté
+- pick fromage/chèvre
+- pick jambon
+- edit complète → vi → git add -u → git ci --amend → git rebase --continue
+
+---
+
+# Rebase de branche
+.fx: chapter
+
+---
+
+## Rebase avec conflits
+
+- Créer une branche `beurrer_les_crepes` et placez-vous dessus
+- Ajouter « une noix de beurre » sur les *crèpes sucrées* (à la fin pour avoir un conflit) et commiter
+- Repartir de la branche `crepes`
+- Créer une branche `crepes_sucrees` et placez-vous dessus
+- Ajouter « sucrer la pâte » sur les *crêpes sucrées* (à la fin pour avoir un conflit) et commiter
+- Créer un tag `beurrer_les_crepes_avant_rebase` pointant sur `beurrer_les_crepes`
+- **Rebaser** `beurrer_les_crepes` sur `crepes_sucrees`
+
+# Presenter Notes
+- Et oui, il y a des conflits, maintenant il faut les résoudre !
+- Utilisation de `git mergetool` et `git rebase --continue`
+- Montrer qu'on peut annuler à tout moment avec `git rebase --abort`
+- Utilisation de `gitk --all` pour montrer ce qui a été fait
+- Utilisation de `git clean -f` pour virer les `.orig`
+
+---
+
+# Manipulation de commits
+.fx: chapter
+
+---
+
+## Notations relatives
+
+- Utilisation de `HEAD^`
+    - Créer un fichier vide `xxx.md`, le commiter
+    - Supprimer ce commit en utilisant `HEAD^`  
+`$ git reset --hard HEAD^`
+- Utilisation de `HEAD~2` (ou `HEAD^^`)
+    - Créer deux commits
+    - Fusionnez les 2 derniers commit.  
+`$ git rebase -i HEAD~2` et faire un `fixup`
+
+# Presenter Notes
+
+- `^` c'est le premier parent
+- `^x` c'est le parent numéro `x` (famille multi-parentale)
+- `~x` c'est l'ancêtre numéro `x` en prenant systématiquement le premier parent
+- `^ == ^1 == ~ == ~1`
+
+---
+
+# Utilisation du `reflog`
+- Le commit que l'on a supprimé (avec le `fixup`) n'est pas complètement perdu
+- Lancer `reflog` pour trouver sa **référence** (*sha1*)
+- Picorer le commit correspondant  
+`$ git reflog`  
+`$ git chery-pick <N° hash>`
+
+# Presenter Notes
+- Oui il a déjà été appliqué et git s'en rend compte
+- Annuler le picorage avec `git cherry-pick --abort`
+
+---
+
+# Workflow
+.fx: chapter
+
+---
+
+## Branche *dev* + *feature*
+Un workflow classique est d'utiliser une branche `dev` + une branche **par fonction** avec fusion.
+
+- Créer une branche `dev` à partir de la branche `crepes`
+- La branche `crepes_sucrees` est une *feature*, merger celle-ci sur `dev`
+- Supprimer les branches une fois qu'elles sont mergées.
+- Question : y a-t-il encore des branches non mergées ?
+
+Note : on peut également choisir de :
+
+- Rebaser les branches de feature avant le merge
+- Merger explicitement (c'est à dire sans *fast-forward*) avec `--no-ff`
+
+# Presenter Notes
+- `git branch -d` pour supprimer une branche
+- `git tag -d` pour supprimer un tag
+- Utiliser `maj+F5` dans `gitk` pour forcer le raffraichissement et ne plus afficher les *dandling commits*
+
+---
+
+## Branche de *prod* en plus
+Des **corrections** sont nécessaires **sans attendre** la prochaine livraison.
+
+- Créer la branche `prod` sans aucun parent  
+`$ git checkout --orphan prod`
+- Nettoyer : `git reset && git clean -f -d`
+- Avec un commit initial vide : `git commit –allow-empty`
+- Ajouter une version dans la branche de production  
+`$ git merge dev --no-ff -X theirs --allow-unrelated-histories`  
+`$ git tag -a -m "Version 1" crepe_v1`
+
+Besoin d'une correction rapide → worklow **hotfix**.  
+Ce processus est un peu **lourd**. Slt pour ceux ne regardant que la **tête** de la branche `prod`.
+
+# Presenter Notes
+- Utile quand on a une production qui commence à vivre un peu.
+- À chaque version on ajoute donc un commit de merge (sans *fast forward*) qui supporte le **tag de version**.
+- Aucun commit n'ayant du contenu ne se trouve sur la branche de production.
+- Devient trop compliqué quand on gère plusieurs **versions majeures** en même temps.
+- Je préfère faire des tags sur la branche `dev` et utiliser le workflow `hotfix` depuis les tags.
+- Regarder les infos sur le tag annoté
+
+---
+
+## Ajout d'un « hotfix » à 2 branches
+La prod plante ! On doit corriger **rapidement**.  
+On ne **veut pas** des développements **en cours** sur `dev`.
+
+- Partir du tag déployé pour créer et utiliser la branche `hotfix_beurresel`
+- Ajouter la *galette beurre sel* en urgence.
+- Si vous choisisser d'utiliser le workflow avec la branche de `prod` :
+    - Merger cette branche sur `prod`
+    - Faire un nouveau tag `crepe_v1.1` sur `prod`
+- Sinon :
+    - Faire un nouveau tag `crepe_v1.1` sur cette branche.
+- Merger la branche `hotfix_beurresel` sur `dev`
+- Supprimer la branche de hotfix
+
+# Presenter Notes
+- On veut profiter des corrections de prod sur dev
+- Créer la branche permet de tester (CI, pré-prod, …)
+- La branche ne sert plus à rien une fois mergée
+- On a l'historique même si on supprime la branche, constater tout ça dans `gitk --all`
+
+---
+
+# Bravo !
+.fx: last-slide
diff --git a/supports/advanced/tp_git_advanced_embed.cfg b/supports/advanced/tp_git_advanced_embed.cfg
new file mode 100644 (file)
index 0000000..e984d10
--- /dev/null
@@ -0,0 +1,8 @@
+[landslide]
+source = tp_git_advanced.md
+destination = tp_git_advanced.html
+theme = ../blue
+embed = true
+relatives = true
+extensions = fenced_code,tables,attr_list
+linenos = no
index b5600d7..74e79e9 100644 (file)
@@ -1,7 +1,7 @@
 [landslide]
 source = slides_git_basic.md
 destination = slides_git_basic.html
-theme = ../viseo
+theme = ../blue
 embed = false
 relatives = true
 extensions = fenced_code,tables,dot,attr_list
index 82545ca..4af704c 100644 (file)
@@ -5,7 +5,7 @@
 
 <a href="mailto:cyrille@enialis.net">Cyrille Pontvieux</a>
 
-<a href="http://www.viseo.com">Viseo</a>
+<a href="https://github.com/jrd">Github</a>
 
 ---
 
@@ -17,7 +17,7 @@
 ## Caractéristiques de Git
 - Gérer les versions des sources
 - Raconter l'histoire du logiciel
-- Résoudre les problèmes complèxes avec un outil complet
+- Résoudre les problèmes complexes avec un outil complet
 - Gérer plusieurs dépôts
 - Travail déconnecté
 - Gestion intrinsèque des branches et tags
@@ -1790,7 +1790,7 @@ Très utile quand :
 ---
 
 ## Stash
-- Le **stash** est une sorte d'étagère ou de pile (**FILO**)
+- Le **stash** est une sorte d'étagère ou de pile (**LIFO**)
 - On peut **empiler** des changements pour réutilisation future
 - On peut **nommer** les changements enregistrés de manière à mieux les identifier plus tard
 - Même si c'est une FILO, on peut **accéder à chacun** des éléments
@@ -1813,7 +1813,7 @@ Utile quand :
 ## Conseils
 - La stratégie **merge** par défaut sur **pull** crée un historique spaghetti. Préférer **rebase** si maitrisé
 - Utiliser des **alias** pour les commandes courantes ou compliquées.
-- Utiliser <a href="http://www.git-prompt.sh/">un beau prompt</a>
+- Utiliser [un beau prompt](https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh)
 - Utiliser un gestionnaire de dépôts distants : GitHub, Gitlab, GitBlit, …
 - Créer des commits par **sémantique** (pour pouvoir les picorer si nécessaire)
 - Créer souvent des **branches**, une par **fonctionnalité** par exemple
@@ -1826,22 +1826,5 @@ Utile quand :
 
 ---
 
-## Conclusion
-- Concepts maitrisés
-- Démistification de git ou d'un DVCS
-- Autonomie
-- Vous ne saurez bientôt plus comment vous faisiez avant !
-
-Pour aller plus loin, la F.E.S. Git avancé :
-
-- Comprendre *.git*
-- Rebase interractif, Autosquash, Rerere, Bisect
-- Cherry-pick entre dépôts
-- Workflows conseillés
-- Git daemon et webui
-- Forks, Pull/Merge requests
-
----
-
 # Passons à la pratique…
 .fx: last-slide
diff --git a/supports/basic/slides_git_basic_embed.cfg b/supports/basic/slides_git_basic_embed.cfg
new file mode 100644 (file)
index 0000000..8c31609
--- /dev/null
@@ -0,0 +1,8 @@
+[landslide]
+source = slides_git_basic.md
+destination = slides_git_basic.html
+theme = ../blue
+embed = true
+relatives = true
+extensions = fenced_code,tables,dot,attr_list
+linenos = no
index fe670e7..070d614 100644 (file)
@@ -1,7 +1,7 @@
 [landslide]
 source = tp_git_basic.md
 destination = tp_git_basic.html
-theme = ../viseo
+theme = ../blue
 embed = false
 relatives = true
 extensions = fenced_code,tables,attr_list
index 702e4f3..22be711 100644 (file)
@@ -5,7 +5,7 @@
 
 <a href="mailto:cyrille@enialis.net">Cyrille Pontvieux</a>
 
-<a href="http://www.viseo.com">Viseo</a>
+<a href="https://github.com/jrd">Github</a>
 
 ---
 
@@ -37,14 +37,14 @@ Les composants suivants sont requis :
 
 L'installation de ces composants sont détaillés par plateforme dans le fichier **INSTALL.html**
 
-- Aller dans le répertoire `tp/basic`
+- Aller dans le répertoire `stagiaire_git_basic/tp`
 - Installer les dépendances python :  
-`pip install --user -r requirements.txt`  
-(sans le `--user` sous Windows)
-- Ignorer les « erreurs » éventuelles
+`pip install --user -r requirements.txt`
+- Supprimer ou déplacer votre éventuelle config git :  
+`rm ~/.gitconfig`
 
 # Presenter Notes
-Un [Prompt Git](http://www.git-prompt.sh/) est disponible
+Un [Prompt Git](https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh) est disponible
 
 ---
 
@@ -95,7 +95,7 @@ Astuces :
 ## Recette de la tarte aux poireaux
 
 - Vider votre index : `git reset`
-- Créer le répertoire `src` dans l'index  
+- Créer le répertoire `src` et l'ajouter dans l'index  
 Que se passe-t-il ? Utiliser `git status`
 - Ajouter le fichier vide `.gitkeep` dans `src`
 - Ajouter le fichier `src/.gitkeep` dans l'index  
@@ -192,6 +192,7 @@ On va finalement commiter notre recette
 - Observer à nouveau `gitk` avec et sans l'option `--all` :
 `gitk`  
 `gitk --all`
+- Revenir sur `master`
 
 # Presenter Notes
 - Questions sur la branche, le dépôt git, l'index, le workspace et les fichiers non-suivis
@@ -295,6 +296,10 @@ On va finalement commiter notre recette
     - Se placer sur `master`
     - Lancer le merge :  
 `git merge tartes_sucrées`
+    - Pousser :  
+`git push`
+- L'autre binôme récupère le résultat :
+`git pull`
 - Constater le résultat sur `gitk`
 - Que s'est-il passé ?
 
@@ -341,6 +346,7 @@ $ git config --global --edit
 - Le supprimer avec `git clean` :
     - `git clean -n` *pour **voir** les fichiers à supprimer*
     - `git clean -f` *pour **supprimer** les fichiers*
+- Faire un `push` et `pull` pour vous synchroniser
 - Refaire l'opération de modification depuis l'autre poste :  
     - ajout de **smarties** d'un côté
     - ajout de **m&ms** de l'autre
@@ -352,22 +358,32 @@ $ git config --global --edit
 .fx: chapter
 
 ---
+## Préparation rebase
+- On ne va plus fonctionner en binôme pour cette partie.
+- Récupérer localement les branches :
+    - tartes_sucrées
+    - tartes_salées
+    - master
+- Supprimer votre `remote` :  
+`git remote rm origin`
+
+---
 
 ## Ne pas avoir peur de git rebase 1/2
 Le `git rebase` est **LA fonctionnalité** de git, avec les branches bien sûr.
 
-- Faire des développement en **//** sur `master` et sur la branche `tarte_salées`
+- Faire des `commit` en **//** sur `master` et sur la branche `tartes_salées`
 - Sur la branche `master`
     - Modifier la **tarte aux poireaux** en ajoutant de la **crème**. ⇒ Commiter
-- Sur la branche `tarte_salées`
+- Sur la branche `tartes_salées`
     - Modifier la **tarte aux poireaux** en ajoutant des **œufs**. ⇒ Commiter
     - Créer une **tarte aux concombres**. ⇒ Commiter
-- Regardez sur `gitk`, on est prêt à **rebaser** les 2 commits qui partent de la branche `tarte_salées`
+- Regardez sur `gitk`, on est prêt à **rebaser** les 2 commits qui partent de la branche `tartes_salées`
 
 ---
 
 ## Ne pas avoir peur de git rebase 2/2
-- Se placer sur `tarte_salées` et la **rebaser** sur `master` :  
+- Se placer sur `tartes_salées` et la **rebaser** sur `master` :  
 `git rebase master`
 - **⇒ Conflits** sur la **tarte aux poireaux**
 - Regarder la console, git précise ce qu'il faut faire pour résoudre le conflit :
@@ -375,7 +391,14 @@ Le `git rebase` est **LA fonctionnalité** de git, avec les branches bien sûr.
     - **Continuer** le rebase avec :
 `git rebase --continue`
 - *C'est fait !*
-- Constater avec `gitk --all` que la **base** de la branche `tarte_salées` a été déplacée et que les commits de cette branche ont **tous changé de sha1**
+- Constater avec `gitk --all` que la **base** de la branche `tartes_salées` a été déplacée et que les commits de cette branche ont **tous changé de sha1**
+
+---
+
+## Merger nos branches
+
+- Merger la branche `tartes_salées` (en no-ff), précédemment rebasée, sur `master`.
+- Faire de même avec la branche `tartes_sucrées`, même si elle n'a pas été rebasée.
 
 ---
 
@@ -395,7 +418,7 @@ Le `git rebase` est **LA fonctionnalité** de git, avec les branches bien sûr.
 - **Hash** du commit à déplacer : `git log -n 1`
 - Se placer sur `master` et lancer le picorrage :  
 `git cherry-pick <coller le hash>`
-- Lancer `gitk --all`, et voir les **2 commits** de tarte au formage
+- Lancer `gitk --all`, et voir les **2 commits** de tarte au fromage
 
 # Presenter Notes
 - `git rev-parse HEAD` peut aussi être utilisé
diff --git a/supports/basic/tp_git_basic_embed.cfg b/supports/basic/tp_git_basic_embed.cfg
new file mode 100644 (file)
index 0000000..85f5848
--- /dev/null
@@ -0,0 +1,8 @@
+[landslide]
+source = tp_git_basic.md
+destination = tp_git_basic.html
+theme = ../blue
+embed = true
+relatives = true
+extensions = fenced_code,tables,attr_list
+linenos = no
similarity index 99%
rename from supports/viseo/css/theme.css
rename to supports/blue/css/theme.css
index fe7aed7..0aea4aa 100644 (file)
@@ -215,6 +215,8 @@ body, header {
 
 header:not(.first-slide):not(:only-child) {
   font-size: 55px;
+  text-overflow: ellipsis;
+  white-space: nowrap;
 }
 section {
   font-family: 'DejaVu Sans', 'Liberation Sans', 'Arial', sans-serif;
similarity index 96%
rename from supports/viseo/js/slides.js
rename to supports/blue/js/slides.js
index a89880d..cca3c3a 100644 (file)
@@ -1,13 +1,15 @@
 /* vim: set et st=4 sts=4 sw=4 tw=0:
  */
 /**
- * StyleFix 1.0.3 & PrefixFree 1.0.7
+ * StyleFix 1.0.3 & PrefixFree 1.0.10
+ * https://github.com/LeaVerou/prefixfree
  * @author Lea Verou
  * MIT license
  */
 /* jshint ignore:start */
-(function(){function k(a,b){return[].slice.call((b||document).querySelectorAll(a))}if(window.addEventListener){var e=window.StyleFix={link:function(a){try{if("stylesheet"!==a.rel||a.hasAttribute("data-noprefix"))return}catch(b){return}var c=a.href||a.getAttribute("data-href"),d=c.replace(/[^\/]+$/,""),h=(/^[a-z]{3,10}:/.exec(d)||[""])[0],l=(/^[a-z]{3,10}:\/\/[^\/]+/.exec(d)||[""])[0],g=/^([^?]*)\??/.exec(c)[1],m=a.parentNode,f=new XMLHttpRequest,n;f.onreadystatechange=function(){4===f.readyState&&
-n()};n=function(){var b=f.responseText;if(b&&a.parentNode&&(!f.status||400>f.status||600<f.status)){b=e.fix(b,!0,a);if(d)var b=b.replace(/url\(\s*?((?:"|')?)(.+?)\1\s*?\)/gi,function(b,a,c){return/^([a-z]{3,10}:|#)/i.test(c)?b:/^\/\//.test(c)?'u'+'rl("'+h+c+'")':/^\//.test(c)?'u'+'rl("'+l+c+'")':/^\?/.test(c)?'u'+'rl("'+g+c+'")':'u'+'rl("'+d+c+'")'}),c=d.replace(/([\\\^\$*+[\]?{}.=!:(|)])/g,"\\$1"),b=b.replace(RegExp("\\b(behavior:\\s*?url\\('?\"?)"+c,"gi"),"$1");c=document.createElement("style");c.textContent=
+if (window.location.protocol != "file:") {
+(function(){function k(a,b){return[].slice.call((b||document).querySelectorAll(a))}if(window.addEventListener){var e=window.StyleFix={link:function(a){var c=a.href||a.getAttribute("data-href");try{if(!c||"stylesheet"!==a.rel||a.hasAttribute("data-noprefix"))return}catch(b){return}var d=c.replace(/[^\/]+$/,""),h=(/^[a-z]{3,10}:/.exec(d)||[""])[0],l=(/^[a-z]{3,10}:\/\/[^\/]+/.exec(d)||[""])[0],g=/^([^?]*)\??/.exec(c)[1],m=a.parentNode,f=new XMLHttpRequest,n;f.onreadystatechange=function(){4===f.readyState&&
+n()};n=function(){var b=f.responseText;if(b&&a.parentNode&&(!f.status||400>f.status||600<f.status)){b=e.fix(b,!0,a);if(d)var b=b.replace(/url\(\s*?((?:"|')?)(.+?)\1\s*?\)/gi,function(b,a,c){return/^([a-z]{3,10}:|#)/i.test(c)?b:/^\/\//.test(c)?'url("'+h+c+'")':/^\//.test(c)?'url("'+l+c+'")':/^\?/.test(c)?'url("'+g+c+'")':'url("'+d+c+'")'}),c=d.replace(/([\\\^\$*+[\]?{}.=!:(|)])/g,"\\$1"),b=b.replace(RegExp("\\b(behavior:\\s*?url\\('?\"?)"+c,"gi"),"$1");c=document.createElement("style");c.textContent='/*# sourceURL='+a.getAttribute('href')+' */\n/*@ sourceURL='+a.getAttribute('href')+' */\n' +
 b;c.media=a.media;c.disabled=a.disabled;c.setAttribute("data-href",a.getAttribute("href"));m.insertBefore(c,a);m.removeChild(a);c.media=a.media}};try{f.open("GET",c),f.send(null)}catch(p){"undefined"!=typeof XDomainRequest&&(f=new XDomainRequest,f.onerror=f.onprogress=function(){},f.onload=n,f.open("GET",c),f.send(null))}a.setAttribute("data-inprogress","")},styleElement:function(a){if(!a.hasAttribute("data-noprefix")){var b=a.disabled;a.textContent=e.fix(a.textContent,!0,a);a.disabled=b}},styleAttribute:function(a){var b=
 a.getAttribute("style"),b=e.fix(b,!1,a);a.setAttribute("style",b)},process:function(){k('link[rel="stylesheet"]:not([data-inprogress])').forEach(StyleFix.link);k("style").forEach(StyleFix.styleElement);k("[style]").forEach(StyleFix.styleAttribute)},register:function(a,b){(e.fixers=e.fixers||[]).splice(void 0===b?e.fixers.length:b,0,a)},fix:function(a,b,c){for(var d=0;d<e.fixers.length;d++)a=e.fixers[d](a,b,c)||a;return a},camelCase:function(a){return a.replace(/-([a-z])/g,function(b,a){return a.toUpperCase()}).replace("-",
 "")},deCamelCase:function(a){return a.replace(/[A-Z]/g,function(b){return"-"+b.toLowerCase()})}};(function(){setTimeout(function(){k('link[rel="stylesheet"]').forEach(StyleFix.link)},10);document.addEventListener("DOMContentLoaded",StyleFix.process,!1)})()}})();
@@ -15,10 +17,11 @@ a.getAttribute("style"),b=e.fix(b,!1,a);a.setAttribute("style",b)},process:funct
 "$1"+h+"$2$3",b);b=e("properties","(^|\\{|\\s|;)","\\s*:","$1"+h+"$2:",b);if(a.properties.length){var l=RegExp("\\b("+a.properties.join("|")+")(?!:)","gi");b=e("valueProperties","\\b",":(.+?);",function(a){return a.replace(l,h+"$1")},b)}c&&(b=e("selectors","","\\b",a.prefixSelector,b),b=e("atrules","@","\\b","@"+h+"$1",b));b=b.replace(RegExp("-"+h,"g"),"-");return b=b.replace(/-\*-(?=[a-z]+)/gi,a.prefix)},property:function(b){return(0<=a.properties.indexOf(b)?a.prefix:"")+b},value:function(b,c){b=
 e("functions","(^|\\s|,)","\\s*\\(","$1"+a.prefix+"$2(",b);b=e("keywords","(^|\\s)","(\\s|$)","$1"+a.prefix+"$2$3",b);0<=a.valueProperties.indexOf(c)&&(b=e("properties","(^|\\s|,)","($|\\s|,)","$1"+a.prefix+"$2$3",b));return b},prefixSelector:function(b){return b.replace(/^:{1,2}/,function(b){return b+a.prefix})},prefixProperty:function(b,c){var d=a.prefix+b;return c?StyleFix.camelCase(d):d}};(function(){var b={},c=[],d=getComputedStyle(document.documentElement,null),h=document.createElement("div").style,
 l=function(a){if("-"===a.charAt(0)){c.push(a);a=a.split("-");var d=a[1];for(b[d]=++b[d]||1;3<a.length;)a.pop(),d=a.join("-"),StyleFix.camelCase(d)in h&&-1===c.indexOf(d)&&c.push(d)}};if(0<d.length)for(var g=0;g<d.length;g++)l(d[g]);else for(var e in d)l(StyleFix.deCamelCase(e));var g=0,f,k;for(k in b)d=b[k],g<d&&(f=k,g=d);a.prefix="-"+f+"-";a.Prefix=StyleFix.camelCase(a.prefix);a.properties=[];for(g=0;g<c.length;g++)e=c[g],0===e.indexOf(a.prefix)&&(f=e.slice(a.prefix.length),StyleFix.camelCase(f)in
-h||a.properties.push(f));!("Ms"!=a.Prefix||"transform"in h||"MsTransform"in h)&&"msTransform"in h&&a.properties.push("transform","transform-origin");a.properties.sort()})();(function(){function b(a,b){h[b]="";h[b]=a;return!!h[b]}var c={"linear-gradient":{property:"backgroundImage",params:"red, teal"},calc:{property:"width",params:"1px + 5%"},element:{property:"backgroundImage",params:"#foo"},"cross-fade":{property:"backgroundImage",params:"u"+"rl(a.png), u"+"rl(b.png), 50%"}};c["repeating-linear-gradient"]=
+h||a.properties.push(f));!("Ms"!=a.Prefix||"transform"in h||"MsTransform"in h)&&"msTransform"in h&&a.properties.push("transform","transform-origin");a.properties.sort()})();(function(){function b(a,b){h[b]="";h[b]=a;return!!h[b]}var c={"linear-gradient":{property:"backgroundImage",params:"red, teal"},calc:{property:"width",params:"1px + 5%"},element:{property:"backgroundImage",params:"#foo"},"cross-fade":{property:"backgroundImage",params:"url(a.png), url(b.png), 50%"}};c["repeating-linear-gradient"]=
 c["repeating-radial-gradient"]=c["radial-gradient"]=c["linear-gradient"];var d={initial:"color","zoom-in":"cursor","zoom-out":"cursor",box:"display",flexbox:"display","inline-flexbox":"display",flex:"display","inline-flex":"display",grid:"display","inline-grid":"display","max-content":"width","min-content":"width","fit-content":"width","fill-available":"width"};a.functions=[];a.keywords=[];var h=document.createElement("div").style,e;for(e in c){var g=c[e],k=g.property,g=e+"("+g.params+")";!b(g,k)&&
 b(a.prefix+g,k)&&a.functions.push(e)}for(var f in d)k=d[f],!b(f,k)&&b(a.prefix+f,k)&&a.keywords.push(f)})();(function(){function b(a){e.textContent=a+"{}";return!!e.sheet.cssRules.length}var c={":read-only":null,":read-write":null,":any-link":null,"::selection":null},d={keyframes:"name",viewport:null,document:'regexp(".")'};a.selectors=[];a.atrules=[];var e=k.appendChild(document.createElement("style")),l;for(l in c){var g=l+(c[l]?"("+c[l]+")":"");!b(g)&&b(a.prefixSelector(g))&&a.selectors.push(l)}for(var m in d)g=
 m+" "+(d[m]||""),!b("@"+g)&&b("@"+a.prefix+g)&&a.atrules.push(m);k.removeChild(e)})();a.valueProperties=["transition","transition-property"];k.className+=" "+a.prefix;StyleFix.register(a.prefixCSS)}})(document.documentElement);
+}
 /* jshint ignore:end */
 
 /* jshint -W083 */
diff --git a/tp/.gitignore b/tp/.gitignore
new file mode 100644 (file)
index 0000000..1b09506
--- /dev/null
@@ -0,0 +1 @@
+remotes/
diff --git a/tp/advanced/.gitignore b/tp/advanced/.gitignore
new file mode 100644 (file)
index 0000000..e84cfff
--- /dev/null
@@ -0,0 +1,2 @@
+*.html
+.~*
index 9894dee..558f04b 100755 (executable)
@@ -31,10 +31,12 @@ except:
 
 def convert(f):
     dest_name = p.splitext(p.basename(f))[0] + '.html'
-    str_in = open(f, 'r').read().decode('utf8')
-    str_out = tpl % md.markdown(str_in, extensions=['partial_gfm'])
-    print('generating %s' % dest_name)
-    open(p.join(dest_dir, dest_name), 'w').write(str_out.encode('utf8'))
+    with open(f, 'rb') as f_in:
+        str_in = f_in.read().decode('utf8')
+        str_out = tpl % md.markdown(str_in, extensions=['partial_gfm'])
+        print('generating %s' % dest_name)
+        with open(p.join(dest_dir, dest_name), 'wb') as f_out:
+            f_out.write(str_out.encode('utf8'))
 
 
 def deletehtml(f):
index 9894dee..558f04b 100755 (executable)
@@ -31,10 +31,12 @@ except:
 
 def convert(f):
     dest_name = p.splitext(p.basename(f))[0] + '.html'
-    str_in = open(f, 'r').read().decode('utf8')
-    str_out = tpl % md.markdown(str_in, extensions=['partial_gfm'])
-    print('generating %s' % dest_name)
-    open(p.join(dest_dir, dest_name), 'w').write(str_out.encode('utf8'))
+    with open(f, 'rb') as f_in:
+        str_in = f_in.read().decode('utf8')
+        str_out = tpl % md.markdown(str_in, extensions=['partial_gfm'])
+        print('generating %s' % dest_name)
+        with open(p.join(dest_dir, dest_name), 'wb') as f_out:
+            f_out.write(str_out.encode('utf8'))
 
 
 def deletehtml(f):
diff --git a/tp/basic/tarte_aux_poireaux.txt b/tp/basic/tarte_aux_poireaux.txt
new file mode 100644 (file)
index 0000000..a830d4d
--- /dev/null
@@ -0,0 +1 @@
+Ce fichier ne devrait pas s'appeler .txt
diff --git a/tp/create-remotes.sh b/tp/create-remotes.sh
new file mode 100755 (executable)
index 0000000..67d6bc1
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/sh
+set -e
+usage() {
+  echo "create-remotes.sh number-of-students base-name"
+}
+nb=$1
+name="$2"
+if [ "$nb" == "-h" ] || [ "$nb" == "--help" ]; then
+  usage
+  exit 0
+fi
+if [ -z "$name" ] || [ "$nb" -lt 1 ]; then
+  usage >&2
+  exit 1
+fi
+cd "$(dirname "$0")"
+mkdir -p remotes
+for i in $(seq $nb); do
+  git init --bare "remotes/${name}-${i}.git"
+  GIT_DIR="remotes/${name}-${i}.git" git config daemon.receivepack true
+  echo 'Git repository for training' > "remotes/${name}-${i}.git/description"
+done
diff --git a/tp/serve-remotes.sh b/tp/serve-remotes.sh
new file mode 100755 (executable)
index 0000000..7910666
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+set -e
+cd "$(dirname "$0")"
+if [ ! -d remotes ]; then
+  echo "Please use create-remotes.sh first" >&2
+  exit 1
+fi
+cd remotes
+echo "Repositories:"
+for dir in *; do [ -d "$dir" ] && echo "  $dir"; done
+git daemon --base-path=. --reuseaddr --export-all