Tutoriel Git
Mise en place
La première chose à faire avant d'utiliser git
est de le configurer.
Ceci n'est à faire qu'une seule fois.
Dans la ligne de commande, tapez le code suivant, ligne par ligne,
en remplaçant les #<XXXX>#
par des informations personnelles correspondantes:
git config --global user.name #<UN USERNAME>#
git config --global user.email #<VOTRE EMAIL EPFL>#
Ensuite, si vous aimez la couleur sur le terminal, vous pouvez ajouter :
git config --global color.diff auto
git config --global color.status auto
git config --global color.branch auto
Ajoutons quelques alias. Pour cela, créez/éditez un fichier ~/.gitconfig
(i.e. fichier nommé « .gitconfig » à la racine de votre répertoire personnel.
Sur les machines du CO, pensez à le recopier dans votre myfiles
).
Mettez y les lignes suivantes :
[alias]
lg = log --graph --abbrev-commit --decorate --date=relative --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all
glog = log --graph --decorate --oneline --all
unstage = reset HEAD --
last = log -1 HEAD
Concepts de base
Avant de se lancer dans l'utilisation de git
, il faut en comprendre le but et la logique :
-
le but est de travailler en commun sur du contenu partagé et, pour cela, archiver les différentes versions (
git
est un « gestionnaire de versions ») ; -
la logique est d'avoir trois niveaux :
- un dépôt commun de référence (appelé « repo » ou « server principal ») ;
- un dépôt local propre à chacun, servant de référence locale (que vous n'avez pas voir) ;
- un répertoire de travail local dans lequel on peut faire et défaire des choses sans conséquences tant qu'on ne les a pas validées au niveau 2 ; c'est ce répertoire que vous avez récupéré/allez récupérer avec
git clone
et dans lequel vous allez travailler (chacun(e)).
Le niveau 2 est en fait assez « abstrait » au sens où vous ne le voyez pas concrètement ; il est totalement géré par des commandes git
.
Pour faire passer quelque chose du niveau 1 aux niveaux 2 et 3 en même temps (c.-à-d. récupérer quelque chose mis à disposition par d'autres dans le server principal), on fait (toutes ces commandes dont détaillées ci-dessous ; ici on se concentre sur les concepts) :
git pull
Je vous conseille de le faire assez régulièrement et en tout cas systématiquement avant vos commit
/push
(expliqués ci-dessous).
Pour valider quelque chose de local, c.-à-d. passer du niveau 3 au niveau 2 uniquement :
-
soit, pour valider une nouvelle version d'un fichier déjà connu :
git commit -m "MESSAGE" FICHIER
veuillez à chaque fois mettre un message pertinent ;
p.ex., pour valider une nouvelle version du fichier
core.c
:git commit -m "correction du bug de calcul" core.c
-
soit, pour ajouter un nouveau fichier (tout ceci est repris en détails ci-dessous) :
git add FICHIER git commit -m "ajout de EXPLICATION"
p.ex. pour ajouter le nouveau fichier
io.c
:git add io.c git commit -m "ajout des entrées/sorties"
Note : pas besoin de remettre le nom du fichier au
commit
suivant un ou desadd
; cela permet en fait d'ajouter plusieurs fichiers d'un coup ; par exemple :git add io_core.c git add io_errors.c git add io.h git commit -m "ajout des entrées/sorties"
Pour publier en commun ses validations locales, c.-à-d. faire passer du niveau 2 au niveau 1 :
git push
Nous insistons donc sur le fait que pour publier à tous une modification locale, il faut bien faire DEUX choses :
git commit
puis
git push
Reprennons tout ceci (et plus) en détails.
Git garde tous les états successifs (snapshots)
Voyons le premier principe de git
: archiver le travail effectué.
Pour cela créez un répertoire et allez-y :
mkdir alice
cd alice
Ajoutez y un fichier :
echo "This is a README file" > README.md
puis archivez dans git
l'état courant de ce répertoire :
git add .
git commit -m "Initial commit: README"
-
git add
vous permet de proposer (sans que ce soit encore confirmé) un changement ;
ici nous avons mis tout le répertoire courant avec son nom court : «.
», mais on aurait aussi pu ne mettre qu'un fichier, par exemple :git add README.md
Nous vous DÉCONSEILLONS d'ailleurs de faire des
git add .
car cela ajoute souvent plein de mauvaises choses : tous les fichiers du répertoire courant, y compris des fichiers temporaires, brouillons, etc.Nous vous conseillons par ailleurs de faire un
git status
AVANT de faire vosgit commit
pour bien vérifier ce que vous ajoutez. -
git commit
confirme l'enregistrement (local) des changements proposés ;
il est fortement recommandé (si ce n'est obligatoire;-)
) de commenter ses changements en ajoutant un message aucommit
; c'est ce que nous avons fait avec l'option-m
.
Si quelque chose est modifié, Git peut vous le dire:
echo "A second line for the README" >> README.md
git status
On pourrait proposer d'ajouter cette nouvelle modification pour un commit
futur:
git add README.md
Cette façon de procéder en deux (puis trois, comme nous verrons tout à l'heure) étapes peut parraître fastidieuse, mais c'est une bonne protection contre les bêtises et un bon moyen de faire les choses petit à petit, une à une.
Une fois que vous êtes prêt à enregistrer (localement) vos modification, faites un commit
...
...sans oublier d'ajouter un commentaire pertinent avec -m
:
git commit -m "Adding a second line to the README file"
Avec Git, on peut voir tout le états enregistrés (snapshots) et même se déplacer de l'un à l'autre (mais c'est plus avancé et vous ne devriez pas en avoir besoin) :
git log
ou:
git lg # si vous avez défini l'alias plus haut...
Pour se déplacer (en guise ici d'illustration, mais ce n'est pas nécessaire de comprendre cette partie au niveau de ce cours) :
git checkout 5d340 # Mettez un numéro de commit approprié, ancien
cat README.md
Voyez que c'est une ancienne version. Revenons à l'état courant :
git checkout master
cat README.md
Vous avez maintenant compris la notion d'états archivés par Git (snapshots), et donc la différence entre le répertoire de travail courant et l'archive.
Le deuxième concept qu'il faut bien comprendre c'est les DEUX archives qui existent.
Git permet en effet de travailler à plusieurs (cf section suivante) et utilise pour cela deux archives différentes :
- une locale, que nous avons utilisée jusque maintenant
- une globale, sur le server Git choisi et où toutes les personnes travaillant sur un même projet vont regrouper leurs modifications.
Pour « pousser » vos changements enregistrés localement (avec des commit
) vers le server central, il faut faire :
git push
Je vous recommande grandement de faire au préalable un
git pull
avant chacun de vos
git push
Le pull
permet de synchroniser dans l'autre sens : aller chercher
les modifications enregistrées dans le server et les appliquer
localement.
Plus de détails dans la suite...
Git peut gérer différent états « concurrents »
Git est avant tout un outil de travail collaboratif que beaucoup de gens utilisent
justement pour travailler « en parallèle ». Il est donc prévu pour faciliter la
gestion de modifications « concurrentes » (ou en tout cas « parallèles » ;-)
).
Supposons que Alice a un collaborateur, Bob, sur son projet, et qu'il ait fait des modifications de son coté :
echo "Hey, this is a line added by Bob" >> README.md
git commit -m "Add greeting from Bob" README.md
pendant, qu'en parallèle, Alice continuait aussi à travailler :
sed -i 's/This is a README file/This is a README file with a twist/' README.md
git commit -am "Add a twist to the first line of the README"
Où en sommes nous ? Quels sont les états de Git ?
A partir du dernier état commun (dernier pull
des 2 cotés), il y a en fait
deux commit
bien séparés :
- un localement chez Bob (qui ne voit pas encore le nouveau d'Alice) ;
- et un localement chez Alice (qui ne voit pas encore le nouveau de Bob).
Jusque là, pas de confusion possible, donc.
Alice et Bob peuvent maintenant collaborer en partageant leurs contributions.
Supposons que Bob « pousse » le premier (pas besoin de pull
avant ici) :
git push
Quand Bob fait cela, le server central reçoit et enregistre la modification de Bob. Pas de problème ici.
Un git lg
du coté Bob montre que origin/master
(celui du server) et master
(celui local) sont
maintenant les mêmes.
Alice de son coté ne sait pas que le changement de Bob a été propagé au server central. Quand elle essaye de « pousser » ses modifications vers le server :
git push
elle rencontre un problème : un message lui dit que son push
a
échoué et qu'elle doit d'abord fetch
(= récupérer) les modifications
enregistrées sur le server central...
Ce qu'elle fait docilement :
git fetch
Avec un
git lg
de son coté, Alice voit qu'elle a maintenant deux commit
: un appelé
origin/master
, qui correspond à celui de Bob et un autre appelé
master
ou HEAD
qui correspond au sien.
Si Alice veut « pousser » ses modifications vers le server central, elle doit d'abord
fusionner/regrouper (= merge) ces 2 états différents. Si il n'y a pas de conflit (modifications
parrallèles non concurrentes), cela se fait simplement comme suit :
git merge
# Enter a commit message...
Elle peut vérifier l'état :
git lg
puis « maintenant » pousser ce nouvel état, résultant de la fusion des deux modifications :
git push
A partir de là, Alice et le server central sont synchronisés. Pour que Bob soit aussi synchronisé, il lui faut aussi faire un
git fetch
ou plus simplement un
git pull
Cette commande (git pull
) permet de faire un fetch
puis un merge
d'un seul coup.
Les « tags »
Un « tag » (étiquette) est simplement un nom donné à un état mémorisé (snapshot).
Contrairement aux années précédentes (pour ceux qui auraient connu), nous ne les utiliserons pas spécialement. Mais vous pouvez les utilisez, si vous le souhaiter, pour marquer une version particulière de votre projet, typiquement pour vous souvenir d'une version stable. Mais c'est un détail.
Pour donner une étiquette à l'état courant, il suffit simplement de faire :
git tag -a NOM_DU_TAG -m "message"
Par exemple, si vous voulez nommer l'état courrant « version1.1 », vous faites :
git tag -a version1.1 -m "Version 1.1 stable"
La commande
git tag
donne simplement la liste de tous vos « tags ».
Pour voir à quoi correspond un « tag » donné : git show NOM_DU_TAG
; par exemple :
git show version1.1
Pour pousser le tag vers GitHub, ajoutez --tags
au push:
git push --tags
Pour aller plus loin
Si vous souhaitez en apprendre plus sur Git et GitHub, vous pouvez aller voir ce tutoriel (en anglais).