---
title: "Tutoriel git"
output:
    toc: true
---

* * * * *

## Introduction

### À qui s'adresse ce tutoriel ?
- Objectif du tutoriel : apprendre à utiliser le système git et le [serveur
  gogs](https://gogs.univ-littoral.fr) mis en place par le
[SCOSI](http://scosi.univ-littoral.fr/). 
- Pré-requis : utilisation basique d'un ordinateur (et notamment du clavier).
- Public visé : les développeurs au sens large (code latex, python, matlab, R,
  java...)

### Qu'est-ce-que git et gogs ?
- git : système de journalisation de code source décentralisé (alternative à
  mercurial, subversion, CVS...)
- gogs : service d'hébergement de code source utilisable avec git (alternative
  à github, bitbucket...)

### Dans quels cas utiliser git/gogs ?
git est conçu pour manipuler principalement des fichiers **au format texte**
(code source, code latex, fichier CSV...). Attention, les fichiers word, excel
et PDF ne sont pas des fichiers au format texte.

Quelques fonctionnalités de git :

- journalisation 
- sauvegarde distante 
- synchronisation 
- travail en équipe 
- projets publics ou privés :

### Dans quels cas ne pas utiliser git/gogs ?
- édition collaborative en temps-réel -> sharelatex
- partage de fichiers -> serveur ftp, http...
- fichiers dans un format non textuel (word, excel, PDF...) -> dropbox

### Concepts de base

#### Notion de "version" (commit)

Un "projet git" contient l'historique de toutes les modifications de chaque
fichier.  On appelle "commit" un état sauvegardé de ces modifications (une
version du projet en quelque sorte).

Généralement, on modifie le projet à partir de la version précédente et ansi de
suite; ce qui correspond à une succession de commits :

![](concepts_commits_1.svg)

Mais on peut également effectuer des modifications en parallèles. On appelle ça
des branches :

![](concepts_commits_2.svg)

On peut ensuite rassembler ces modifications en fusionnant les branches :

![](concepts_commits_3.svg)

#### Notion de dépôt (repository)

On appelle dépôt l'ensemble des fichiers de notre "projet git", c'est-à-dire
l'historique des commits.

Un dépôt peut être dupliqué sur différentes machines, pour synchroniser les
données ou pour travailler en équipe. 

Dans l'ancien temps des années 2000, on avait un dépôt principal distant que
l'on synchronisait ou modifiait via des copies locales partielles (subversion,
CVS...) :

<img src="concepts_depots_svn.svg" style="width:700px">

Aujourd'hui, on utilise plutôt un système de dépôts décentralisés (git,
mercurial...).  Avec ce système, tous les dépôts sont identiques et peuvent se
synchroniser entre eux :

<img src="concepts_depots_git.svg" style="width:700px">

Généralement, on garde tout de même un dépôt sur un serveur distant accessible
en permanence (serveur gogs, github...).


* * * * *

## Installation et configuration

Pour utiliser git, il vous faut une connexion internet et un client git.

### Installation sous Linux

La plupart des systèmes Linux modernes propose le client git dans leur système
de paquets. Par exemple, sur les Linux basés Debian, il suffit de lancer la
commande console :

```
sudo apt-get install git
```

Il existe également des clients graphiques : gitg, giggle, qgit, gitk, git-gui...

### Installation sous Windows ou Mac

Télécharger et installer le client [git pour
Windows](http://git-scm.com/download/win) ou le client [git pour
Mac](http://git-scm.com/download/mac).

### Configuration

Après avoir installé le client git, il faut configurer le nom et l'adresse
e-mail de l'utilisateur (à faire une seule). Par exemple, en tapant les
commandes consoles : 

```
$ git config --global user.name "Julien Dehos"
$ git config --global user.email dehos@nimpe.org
```

On peut également configurer l'éditeur de texte et le proxy que le client git
doit utiliser. Par exemple, en tapant les commandes consoles :

```
$ git config --global core.editor emacs
$ git config --global http.proxy http://user:pass@proxyhost:proxyport
```
ou alors en ajoutant des variables d'environnement (par exemple, dans le
`.bashrc`): 
```
export EDITOR=emacs
export http_proxy=http://user:pass@proxyhost:proxyport
```

### Obtenir de l'aide

Aide générale sur git :
```
$ git help 
```

Aide sur une commande git :
```
$ git help <commande git>
```

Voir également la section [références](#références).

### Exercice

Installez et configurez le client git sur votre machine.  Vérifiez que votre
client git peut accéder à l'extérieur, par exemple en récupérant le dépôt
distant `https://github.com/juliendehos/invinoveritas` :

![](installation_01.png)


* * * * *

## Dépôt local (journaliser un projet)

L'élément de base d'un projet git est le dépôt. Il s'agit simplement d'un
dossier classique que l'on demande à git de versionner.

### Initialiser un dépôt

Allez dans le dossier à versionner puis lancez la commande `git init`. 

![](depot_local_01.png)

Git créé alors un dossier `.git` pour y stocker ses metadonnées.  Si vous ne
voulez plus versionner votre dossier, il suffit de supprimer ce dossier.  Le
reste du temps, ne touchez pas à ce dossier si vous n'êtes pas absolument
sûr(e) de ce que vous faites.

### Afficher l'état d'un dépôt

La commande `git status` affiche l'état courant du dépôt : nouveaux fichiers,
fichiers modifiés, fichiers supprimés.  Cette commande est très sûre; elle ne
peut rien casser.  N'hésitez donc pas à la lancer pour voir où vous en êtes.

![](depot_local_02.png)

### Ajouter des fichiers dans le dépôt

Il faut indiquer explicitement les fichiers que git doit journaliser.  

Par exemple, imaginons qu'on ouvre un nouveau fichier `rapport_01.tex` dans
notre projet.

![](depot_local_03.png)

On y écrit du code latex.

![](depot_local_04.png)

Et on affiche l'état du dépôt.

![](depot_local_05.png)

Git nous indique que le fichier `rapport_01.tex` existe bien dans le dossier
(ainsi qu'un fichier de sauvegarde), mais qu'il ne fait pas partie du dépôt. 

Pour ajouter un fichier au dépôt, il faut utiliser la commande `git add`. 

![](depot_local_06.png)

Ceci indique que git doit prendre en compte le fichier lors des prochains
commits (journalisation), ce qu'on peut vérifier avec un `git status`.

![](depot_local_07.png)

### Valider les modifications (commit)

Après avoir ajouté, modifié ou supprimé des fichiers, on peut valider les
modifications, c'est-à-dire sauvegarder un état du projet (commit). Encore une
fois, seuls les fichiers qui ont été ajoutés au projet (avec `git add`) sont
pris en compte. 

La commande à lancer pour valider toutes les modifications est `git commit -a`.

![](depot_local_08.png)

Git lance alors l'éditeur de texte pour le message de commit.
Le message est pré-rempli avec des informations concernant le commit. Ces
informations vous permettent de vérifier que le commit correspond bien à ce que
vous voulez mais ne feront pas partie du message final.

Écrivez un message expliquant rapidement les modifications que vous êtes en
train de valider puis enregistrez et quittez. 

![](depot_local_09.png)

Git créé alors le nouveau commit, qui valide ici le fichier `rapport_01.tex`.

![](depot_local_10.png)

Vous pouvez le vérifier avec un `git status`.

![](depot_local_11.png)

### Fichiers autogénérés et .gitignore

Git est très pratique pour gérer des fichiers textes que l'on modifie
régulièrement. En revanche, il n'est pas adapté pour gérer des fichiers dans un
format non-textuel (images, données compressées, documents word...).  Si on
ajoute un tel fichier dans le dépôt alors à chaque modification, git stockera
une nouvelle copie complète (au lieu de stocker uniquement les lignes qui ont
changé), ce qui est inefficace.

D'autre part, il est inutile de versionner les fichiers autogénérés (créés
automatiquement lors de la compilation du code). Par exemple, si on compile le
code latex de notre projet : 

![](depot_local_12.png)

des fichiers intermédiaires sont créés et apparaissent lors des `git status` :

![](depot_local_13.png)

Pour les ignorer, il suffit d'ajouter un fichier `.gitignore` et d'y indiquer
les fichiers à ignorer.

![](depot_local_14.png)

Ainsi, il n'apparaissent plus lors des `git status`.

![](depot_local_15.png)

Il est de pratique courante d'ajouter le `.gitignore` au dépôt, ainsi qu'un
fichier `README.md` qui servira de page d'accueil (au format
[markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)).

![](depot_local_16.png)


### Renommer et supprimer des fichiers

La commande `git mv` permet de renommer un fichier versionné. Il ne faut pas
utiliser la commande système (`mv`) car dans ce cas git ne saura pas qu'il faut
renommer le fichier (il pensera que le fichier manque et essaiera de le
recréer).

![](depot_local_17.png)

De même, la commande `git rm` permet de supprimer un fichier versionné.

![](depot_local_18.png)


### Afficher l'historique des commits

Faisons d'abord une modification "commitée" puis une autre non commitée.

![](depot_local_19.png)

La commande `git log` permet d'afficher l'historique des commits.

![](depot_local_20.png)

On peut également le voir avec un client graphique graphique comme `gitg`.

![](depot_local_21.png)

Le "unstaged" correspond aux modifications courantes non commitées.

Pour représenter l'historique d'un dépôt, on utilise souvent un graphe où les
noeuds représentent les commits. On ajoute également l'étiquette "master", qui
indique le dernier commit principal, et l'étiquette "HEAD", qui indique l'état
courant du dépôt.

![](depot_local_log.svg)

Ainsi, un `git commit` créé un commit à partir de l'état pointé par HEAD
et fait pointer master (et HEAD) sur ce nouveau commit.

### Supprimer les modifications courantes

La commande `git checkout -- . ` supprime les modifications courantes. Le dépôt revient
alors dans l'état du dernier commit (master).

![](depot_local_checkout_01.svg)

### Revenir à un commit précédent (sans suppression)

La commande `git checkout 7b3...` permet de revenir au commit "7b3...". On passe 
ainsi dans un mode "détaché" (HEAD ne pointe plus sur un commit terminal).

![](depot_local_checkout_02.svg)

Au lieu d'utiliser le numéro de commit, on peut également utiliser les
étiquettes. Par exemple, `git checkout master` pour aller au dernier commit
principal ou `git checkout HEAD~1` pour aller au commit précédent le commit
courant.

### Marquer un commit

La commande `git tag` permet de nommer des commits pour, par exemple, fixer une
version ou pouvoir revenir plus facilement sur un commit particulier.

![](depot_local_22.png)

![](depot_local_checkout_03.svg)

### Supprimer des commits précédents

La commande `git reset 073...` revient au commit "073..." et annule tous les
commits suivant (jusqu'à l'ancien master). Les modifications correspondants à
ces commits sont conservées dans l'état courant (non commité).

![](depot_local_checkout_04.svg)

Autre possibilité : la commande `git reset --hard 073...` revient au commit
"073..." et annule tous les commits suivant **en supprimant les modifications
correspondantes**.

![](depot_local_checkout_05.svg)

### Résumé et méthode de travail

Résumé des commandes git précédentes :

---|---|
`git init` | initialise le dossier courant (nouveau dépôt git) |
`git status` | TODO |
`git add` | |
`git commit -a` | |
`git mv` | |
`git rm` | |
`git log` | |
`git checkout -- .` | |
`git checkout <commit/etiquette>` | |
`git tag` | |
`git reset` | |
`git reset --hard` | |

Quelques conseils de méthode de travail :

- privilégier les petits dépôts, correspondant à différents travaux, plutôt
  qu'un gros dépôt regroupant tous les travaux de l'année
- faire des commits réguliers et correspondant aux petites tâches successives 
- éviter de commiter un projet cassé (par exemple, du code qui ne compile pas)
- ne pas versionner les fichiers auto-générés

### Exercice


TODO



* * * * *

## Dépôt distant (sauvegarder un projet sur un serveur)

Git permet de synchroniser un dépôt local avec un dépôt distant (sur un
serveur).  Il existe des serveurs comme github qui permettent d'héberger
gratuitement des dépôts publics (visibles par tout le monde).

Le serveur gogs du SCOSI vous permet d'héberger des dépôts publics ou privés.
Il dispose d'une page web vous permettant de gérer vos projets. Pour cela,
allez à l'adresse
[https://gogs.univ-littoral.fr](https://gogs.univ-littoral.fr) et entrez vos
identifiants du portail ULCO :

![](depot_distant_01.png)

Une fois identifié, le site vous affiche une page d'accueil (derniers commits,
dépôts actifs...) :

![](depot_distant_02.png)

### Créer un dépôt sur un serveur git

Pour créer un nouveau dépôt distant, allez sur la page du serveur gogs et
cliquez "New Repository".

![](depot_distant_03.png)

Entrez le nom du dépôt distant à créer (évitez les espaces), puis cliquez
"Create Repository".

![](depot_distant_04.png)

Le dépôt distant est alors créé et une page vous indique comment le récupérer
localement. Attention, il y a une méthode plus simple que celle indiquée (cf
section suivante).

![](depot_distant_05.png)

### Créer un dépôt local à partir d'un dépôt distant

La commande `git clone ...` permet de récupérer un dépôt distant sur votre
machine (cf image ci-dessous). Pensez à mettre votre login après le "https://".

![](depot_distant_06.png)

### Ajouter un dépôt local à un dépôt distant

Si vous avez déjà créé et modifié un dépôt local, vous pouvez le synchroniser
avec un dépôt distant en utilisant les commandes `git remote add origin ...`
puis `git push -u origin master`. Sinon, utilisez plutôt la méthode de la
section précédente.

![](depot_distant_07.png)

### Récupérer les commits d'un dépôt distant

La commande `git pull` permet de récupérer les éventuelles modifications sur le
serveur et de les intégrer dans votre dépôt local.

![](depot_distant_08.png)

### Envoyer les commits locaux sur un dépôt distant

La commande `git push` permet d'envoyer vos commits locaux sur le serveur.

![](depot_distant_09.png)

Les commits/fichiers envoyés sur le serveur sont alors visibles sur la page web.

![](depot_distant_10.png)

Vous pouvez également toujours voir le contenu de votre dépôt avec un client
graphique.

![](depot_distant_11.png)

### Résoudre des conflits

Imaginez que vous avez modifié et commité un fichier, et que vous voulez
l'envoyer sur le serveur. Pour cela, il faut d'abord faire un `git pull` avant
le `git push` au cas où l'un de vos collaborateurs aurait envoyer une
modification sur le serveur entre temps. 

Si des modifications ont été faites en parallèle, git est souvent capable de
les fusionner mais parfois il n'arrive pas à résoudre le conflit et il vous
demande de le faire manuellement.

![](depot_distant_12.png)

Pour résoudre un conflit, il suffit d'ouvrir le fichier en cause et de
remplacez les zones marquées par le contenu que vous voulez obtenir. 
Il existe des outils graphiques comme `meld` qui peuvent vous y aider.

![](depot_distant_13.png)

Une fois les conflits édités, vous pouvez commiter et pusher vers le serveur.

![](depot_distant_14.png)

### Résumé et méthode de travail

Résumé des commandes git précédentes :

---|---|
`git clone` | récupère un dépôt distant |
`git pull` | récupère les modifications du dépôt distant et les intègre dans le dépôt local |
`git push` | envoie les commits du dépôt local sur le dépôt distant |

Quelques conseils de méthode de travail :

- utilisez la page
  [https://gogs.univ-littoral.fr](https://gogs.univ-littoral.fr) pour créer et
gérer vos dépôts distants.
- récupérez vos nouveaux dépôts distant avec `git clone`
- récupérez les modifications du serveur avec `git pull`
- faites un `git pull` avant d'envoyer vos nouveaux commits sur le serveur (`git push`)

### Exercice

TODO

* * * * *

## Branches (travailler en équipe)

TODO

### Afficher les branches 
git log --graph --all --oneline --decorate

### Créer une nouvelle branche locale

### Changer de branche

### Fusionner des branches

### Envoyer une branche sur un dépôt distant

### Afficher les branches distantes

### Terminer une branche locale

### Terminer une branche distante

### Supprimer un commit déjà pushé (DANGER !!!)
git reset --hard e6c8e8e
git push origin HEAD:master -f
git reset --hard e6c8e8e

![](branche_01.png)
![](branche_02.png)
![](branche_03.png)
![](branche_04.png)
![](branche_05.png)
![](branche_06.png)
![](branche_07.png)
![](branche_08.png)
![](branche_09.png)
![](branche_10.png)
![](branche_11.png)
![](branche_12.png)
![](branche_13.png)
![](branche_14.png)
![](branche_15.png)
![](branche_16.png)
![](branche_17.png)
![](branche_18.png)
![](branche_19.png)
![](branche_20.png)
![](branche_21.png)

### Résumé et méthode de travail

Résumé des commandes git précédentes :

---|---|
`git ` | |

Quelques conseils de méthode de travail :

- TODO


### Exercice

TODO

* * * * *

## Forks (collaborer avec d'autres projets)

TODO

### Forker un dépôt distant

### Envoyer un pull request

### Résumé et méthode de travail

Résumé des commandes git précédentes :

---|---|
`git ` | |

Quelques conseils de méthode de travail :

- TODO

### Exercice

TODO

* * * * *

## Références

- [https://www.atlassian.com/git/tutorials/](https://www.atlassian.com/git/tutorials/)
- [http://git-scm.com/book/fr/v2](http://git-scm.com/book/fr/v2)

* * * * *

Dernière mise à jour : 2016-03-05

