Git

De FunLab Documentation
Aller à : navigation, rechercher

Idées de base et usages

Git est un gestionnaire de version décentralisé :

Gestionnaire de version
conserve les versions successives des fichiers qu'il surveille ;
permet de comparer des versions plus ou moins anciennes d'un même fichier ;
peut contenir simultanément des états différents d'un projet entier (branches), de les comparer et de les mélanger.
Décentralisé
ne dépend pas d'un dépôt central comme CVS ou SVN ;
rend possible d'envoyer ses modifications à plusieurs autres dépôts.

Dans les faits, si centralisation il y a, elle se fait au niveau de l'organisation, pas du logiciel. Le meilleur exemple – et l'original – est le projet Linux qui possède un blessed repository (dépôt canonique) géré par Linus.

Étant décentralisé, git peut tout à fait fonctionner en local. Il peut servir dans une méthode de travail très simple où les nouveaux changements sont ajoutés les uns à la suite des autres dans une unique branche. Les dépôts peuvent êtres clonés dans le même système de fichier sans passer par le réseau, et en cas de besoin simple et ponctuel on peut simplement copier le dossier .git. Il est relativement facile de rendre l'organisation des dépôts de plus en plus complexe quand les besoins changent.

Techniquement, bien qu'il puisse enregistrer des binaires, git est fait pour versionner des fichiers en texte brut, comme du code source, des fichiers HTML et CSS, des documents LaTeX ou encore des fichiers de configuration<ref name="git_home">De nombreux utilisateurs de git l'utilisent pour versionner les fichiers de configuration de leur dossier personnel et conserver un ensemble cohérent et à jour entre plusieurs machines.</ref>. Git suit la philosophie UNIX en se basant sur le système de fichier pour fonctionner :

  • la zone d'action d'un dépôt est celle du dossier dans lequel il a été initialisé et ses sous-dossiers (sauf à mettre des liens symboliques, mais ça peut vite dégénérer) ;
  • tout ce que git enregistre est sous forme de fichiers texte (sauf dans le cas de binaires) ;
  • ces fichiers texte sont placés dans un dossier .git à la racine du dépôt, dossier qui a une organisation précise.

On peut ainsi tout à fait déplacer le dossier .git dans un dossier vide et avec une simple commande reconstituer l'ensemble du dépôt. Pratique quand on a tendance à effacer des fichiers importants par inattention. À noter que les fichiers contenant les données – donc les plus importants – sont en lecture seule ; cela peut être gênant quand on veut effacer un dépôt, mais cela peut vous sauver la vie si vous avez essayé d'effacer récursivement le mauvais dossier (voir plus loin pour la – très simple – procédure de récupération d'un dépôt cassé de cette façon).

Le minimum pour comprendre git

Cette partie sert à expliquer rapidement les grands concepts de git. Il ne s'agit ni d'un tutoriel, ni d'un « guide de survie », ni d'une explication de fond. Beaucoup de choses importantes sont laissées de côté.

Dépôt, dossier de travail et historique

Git travaille sur un dépôt (repository, abrégé en repo), autrement dit le dossier .git contenant l'ensemble des informations. Le dossier contenant le dépôt et les fichiers suivis est le dossier de travail (working directory, ou working tree). Le dossier de travail contient le projet dans un seul de ses états, tandis que le dépôt contient l'ensemble des états. Le dossier de travail est ce que l'on manipule habituellement, et peut contenir des fichiers non suivis par git.

Le dépôt contient l'historique, qui est constituée de plusieurs chaînes de commits, chaînes se rejoignant toutes sur le commit initial (sauf cas particuliers). Un commit est l'unité de base pour l'utilisateur : il contient l'état du dossier de travail à un moment précis – le moment du commit.

L'index

L'index (ou staging area) est un point très important à aborder, mais assez difficile à saisir pour les débutants pressés et pouvant faire croire à un logiciel complexe. L'index est un intermédiaire entre le dossier de travail et le commit. À la demande de l'utilisateur, il enregistre certaines modifications du dossier de travail. Lors du commit, seules les modifications enregistrées dans l'index font partie du commit. Cela permet de découper un grand ensemble de modifications en plusieurs commits. Ainsi, si on a modifié fichier1 et fichier2 dans le dossier de travail mais que l'on veut séparer dans l'historique les modifications apportées à chaque fichier car elles sont indépendantes, on fera

$ git add fichier1

pour enregistrer dans l'index les modifications apportées à fichier1, puis

$ git commit

pour faire un commit de ces modifications ne concernant que fichier1. Il est même possible avec l'option -e de sélectionner quelles lignes du fichier mettre dans l'index.

Déplacements entre commits et branches

Chaque commit est identifié par une chaîne de caractères unique (une somme sha-1) et enregistre des données sur la date et l'auteur du commit. Accéder à un commit se fait en indiquant les premiers caractères du commit, et est rendu accessible en modifiant l'état du dossier de travail. Par exemple en tapant

$ git checkout 2ae45fe

git modifie l'ensemble des fichiers qu'il suit pour correspondre à l'état du commit 2ae45fe. Il est possible de visionner les fichiers, de les modifier et même de faire un nouveau commit qui n'affectera pas les autres commits suivant 2ae45fe.

Une branche désigne une chaîne de commits. Techniquement, c'est fichier texte contenant l'identifiant d'un commit, identifiant qui est mis à jour à chaque fois qu'un nouveau commit est fait sur la branche. On peut voir une branche comme une étiquette marquant l'extrémité d'une chaîne de commits, étiquette qui se déplace à chaque nouveau commit. Par défaut, la branche principale s'appelle master, et c'est la première créée. Il est possible d'avoir plusieurs branches pointant sur des commits différents en même temps (c'est tout l'intérêt du logiciel), et pour y accéder il suffit de taper

$ git checkout <branche>

Une nouvelle branche est crée avec

$ git branch <nom>

à partir de n'importe quel commit, qu'il ait déjà une branche ou qu'il s'agisse d'un ancien commit.

Merge et usage des branches

Les branches peuvent être fusionnées (merge), c'est-à-dire que les commits vers lesquels elles pointent sont « mis en accord » en un unique commit (parfois il n'y a rien à faire, et la branche n°1 à fusionner se met simplement à pointer vers le dernier commit de la branche n°2 – git parle de fast-forward). Créer ce commit unifiant les deux (ou plus) branches peut être effectué par git automatiquement, ou peut exiger l'action de l'utilisateur lorsqu'il y a eu des modifications concurrentes sur les mêmes lignes dans les mêmes fichiers.

Les merges font que deux embranchements peuvent se rejoindre ; l'historique des commits dans git n'est pas forcément un simple arbre, mais est un objet plus complexe (un graphe orienté) où des commits peuvent avoir deux parents ou plus, et deux commits avoir un seul parent. Comme les branches ne sont que des fichiers textes contenant une ligne de quelques dizaines de caractères, les créer et les détruire est très rapide, et les méthodes de travail avec git en font un usage intensif. Il est courant dans les projets assez importants d'avoir tout le long de l'historique de multiples embranchements partant de la branche principale et y revenant. Bien souvent, il s'agit d'une personne qui a créé sur sa copie d'un projet une branche pour travailler sur quelque chose de précis et qui a ensuite demandé un merge de sa branche sur la branche principale. Pendant le temps que cette personne a travaillé, la branche principale a pu avancer, en intégrant par exemple des corrections de bugs ou d'autres branches d'autres personnes. Ceci permet un travail décentralisé et parallèle sur le même projet.

Collaboration entre dépôts

Git est capable de suivre les modifications faites dans un autre dépôt. Ce suivi se fait sur la base des branches : une branche locale suit une branche d'un autre dépôt, ou de plusieurs autres. Ces autres dépôts peuvent être aussi bien sur la même machine que sur le réseau local ou sur Internet. Avec entre autres sa commande status, git peut afficher combien de commits diffèrent avec les branches distantes. Sur demande de l'utilisateur, il peut récupérer les nouveaux commit distants (commande fetch) et, si souhaité, les appliquer au dossier courant en fusionnant les commits de l'utilisateur avec les nouveaux commits (commande pull). D'autre part, il est possible de pousser (push) ses propres commits locaux vers un autre dépôt (dépôt qui doit être initialisé nubare —, ce qui est en gros un dépôt sans dossier de travail). En revanche, il est possible de suivre aussi bien un dépôt nu qu'un dépôt de travail. La communication entre les différents dépôts peut se faire directement s'ils sont sur la même machine (même par intermittence, par exemple avec un dépôt canonique mis sur une clé USB) ou par un protocole réseau comme ssh, http(s) ou le protocole propre à git : git.

Sujets avancés

  • modifier l'historique avec rebase et filter-branch ;
  • avoir des sous-dépôts avec les sous-modules (submodules) et fusionner des dépôts avec les sous-arbres (subtrees) ;
  • mettre en place un serveur ;
  • modifier le comportement d'un dépôt avec les hooks ;
  • trouver d'où vient un bug avec bissect ;
  • toucher au fonctionnement de bas niveau, notamment pour récupérer des données.

Se lancer

Configuration des informations sur l'utilisateur

Git enregistre avec chaque commit la date et l'auteur ; il est donc nécessaire de configurer les informations de l'utilisateur pour faire un commit. Git veut juste un nom quelconque et une adresse email. Cette configuration peut être globale ou propre à un seul dépôt. Elle peut se faire avec l'interface fournie par git ou en éditant un fichier texte.

Configuration avec git

Configuration dans un seul dépôt
$ cd <dossier de travail>
$ git config user.name "<nom ou pseudo>"
$ git config user.email "<adresse email>"
Configuration globale
git config --global user.name "<nom ou pseudo>"
git config --global user.email "<adresse email>"
Fichier de configuration

On peut configurer git dépôt par dépôt ; le fichier de configuration est « .git/config ». Le fichier de configuration globale est « ~/.gitconfig ». Dans tous les cas, il suffit d'ajouter ou de modifier dans ces fichiers les lignes suivantes :

[user]
	name = <nom ou pseudo>
	email = <email>

Ces fichiers sont organisés par section ; « [user] » désigne celle concernant l'utilisateur.

Faire son premier commit et s'organiser

La commande pour créer un dépôt git dans le répertoire courant est

$ git init

Il est possible de donner en argument un chemin absolu ou relatif ; l'ensemble des dossiers parents manquants seront créés si nécessaire. Par exemple, si je veux créer un dépôt dans a/b/c, il suffit de lancer

$ git init a/b/c

Cela marche aussi avec clone.

Dans un dépôt vide, certaines commandes, comme git log retournent une erreur, ce qui est parfaitement normal : il faut un premier commit pour pouvoir commencer à explorer le logiciel. Comme l'indique git status dans un dépôt vide, il suffit de mettre un fichier en index

$ git add fichier

puis de faire un commit

$ git commit

Cela ouvre l'éditeur de texte par défaut de votre OS, ou celui configuré dans git (voir plus bas). La première ligne est un court résumé, le reste des explications plus détaillées. Il est possible de passer directement par la ligne de commande avec l'option -m :

$ git commit -m "<Titre du commit>" -m "<Explications supplémentaires>"

Un premier -m donne le titre du commit, qui doit rester court, et tous les -m supplémentaires font partie du paragraphe supplémentaire. On peut voir que le premier commit est bien passé avec

$ git log

Cette commande, comme d'autres sous git, ouvre un pager (probablement less sur votre système). Avec

$ git log --oneline

seul le résumé est affiché. Il existe de très nombreuses options de git log pour afficher l'historique de différentes manières.

Il est possible d'ignorer des fichiers ; ceux-ci ne seront alors pas affichés par la commande git status. Cependant, il est possible de mettre dans l'index des fichiers ignorés. Pour ignorer des fichiers on utilise habituellement un fichier .gitignore à la racine du dossier de travail. Un exemple commenté :

#Ceci est un commentaire
/dossier1
# / est la racine du dossier de travail, là où est le .gitignore
/*.html
#Tous les fichiers html dans la racine du dossier de travail sont ignorés, mais pas ceux dans /dossier2/
*.min.js
#Tous les fichiers se finissant par .min.js sont ignorés partout
/dossier2/**.txt
#Tours les txt sont ignorés dans toute l'arborescence de dossier2
!/dossier2/sousdossier1/*.txt
#On n'ignore pas en revanche les txt de /dossier2/sousdossier1/

git add n'accepte pas les dossiers, seulement les fichiers. Pour quand même enregistrer une arborescence vide, par exemple pour délimiter les grands modules de son projet, il est conventionnel — dans le sens où ce n'est pas une fonctionnalité de git — de mettre un fichier vide « .gitkeep » dans chaque dossier que l'on souhaite enregistrer. Le plus simple est d'utiliser touch :

$ touch dossier{1,2}/.gitkeep
$ git add dossier{1,2}/.gitkeep

(NB : « dossier{1,2}/.gitkeep » est transformé par bash en « dossier1/.gitkeep dossier2/.gitkeep ». Si vous avez activé l'option globstar avec « shopt -s globstar », vous pouvez encore plus simplement faire « git add **/.gitkeep ».)

Visualiser les logs et les différences

Un dossier de travail sale

Expliquer ce qu'est un état sale et parler de git stash

Travailler avec un dépôt distant

Configuration d'un dépot distant

j'ai créé deux comptes sur github, je les ai activés, puis sur "tuxun" j'ai créé un nouveau repository "gittest" via l'interface web…

Un "repo" ou dépot est une sorte de dossier en ligne contenant UN projet et toutes les versions de celui à un instant précis.

Par defaut la branche est "master", une branche est une version du projet à un instant précis, souvent issue de master…

retenez les identifiants pour la suite, "tuxun" est le mainteneur du dépot et "fakdid" un contributeur test. le dépot est donc https://github.com/tuxun

mettre a jour le contenu d'un depot distant

se placer dans le dépot local.

etape 1 et 2 sauf a partir de git add remote: on le fait sur le commun, apres avoir setté un autre user.

creez un nouveau fichier pour le projet puis git add fichier

git pull URLCOMMUNE

git push -u origin master

edit a file…

git commit -a

git push -u origin master

Cas utile:

récupérer un dossier sur Git :
git clone url_dossier_git destination_dossier
forker(cloner) un projet

le trouver sur github, cliquez sur fork.

git init
git config --global user.name "tuxun"
git config --global user.mail "monmail@gmail.truc"
git remote add origin https://github.com/tuxun/rtl8188eu.git
#sur dossier vide uniquement
git pull origin master
nano install.sh
git add install.sh
git commit
git push
test modif a plusieurs

(les utilisateurs de Windows auront peut etre besoin de ceci:http://www.philipp-winterberg.com/software/free_rar_extract_frog.php)

je vous prepare a truc a cloner comme master:

mkdir gittest
cd gittest
git config --global user.email "mailtuxun"
git config --global user.name "tuxun"
git init
git remote add origin https://github.com/tuxun/gittest.git
mkdir udoocase
cd udoocase
mkdir orig
wget [[udoocaseorig.tar.bz2]]
tar -xjvf udoocaseorig.tar.bz2
cd ../..
git add *
git commit -m "le dossier orig contient les sources du projet"
git push -u origin master

udoocaseorig.tar.bz2

En cours....

(Partie orpheline)

Attention, contient du texte copié-collé !

#Connecter le dépot distant
git remote add origin https://github.com/VOTRENOM/NOMDUPROJET.git
#verifier l'origin/la destination du repertoire courant
git remote -v
#envoyer les modifs:
git push ou merge selon les modifs... FIXME

Create a new repository on the command line

touch README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin https://github.com/tuxun/gittest.git
git push -u origin master

Push an existing repository from the command line

git remote add origin https://github.com/tuxun/gittest.git
git push -u origin master

Utiliser les services en ligne

Github

Bitbucket

Gitlab

Configuration et astuces

Quels logiciels pour les merges

Alias utiles

Mettre en cache les mots de passe

Run the command below to enable credential caching. After enabling credential caching any time you enter your password it will be cached for 1 hour (3600 seconds):( (https://confluence.atlassian.com/display/STASH/Permanently+authenticating+with+Git+repositories))

git config --global credential.helper 'cache --timeout 3600'

Ressources

Introductions rapides et mémos

Références

Anglais

Notes

<references/>