Table of Contents
A l'origine était BitKeeper , un logiciel de versionning utilisé par la communauté opensource pour géré le développement du noyau Linux. Dès le début le choix de cet outil fût très contreversé jusqu'en 2005 lorsque la société BitMover annonça qu'elle ne fournirai plus de version gratuite de BitKeeper à la communauté.
La réaction ne ne fit pas attendre, l'écriture de Git débuta sous l'impulsion de Linux Torvald. En réponse à la question "Pourquoi il avait appelé son logiciel 'git'" (équivalent de 'connard' en argot), Linus répondit « je ne suis qu'un égocentrique, donc j'appelle tous mes projets d'après ma propre personne. D'abord Linux, puis git. » :)
Les commandes pour débuter avec git s'apparentent beaucoup à celles d'autres outils de versionning. Pour initier un dépot Git:
$ git init
ou encore pour récuprer un dépot déjà existant:
git clone /var/lib/git/mondepot la_cible
ou encore avec un dépot distant:
git clone http://git.toto.org/trunk la_cible
Ajouter le fichier toto.sh au dépot:
$ git add toto.sh
Transférer le fichier dans le dépot:
$ git commit -m "Add toto.sh"
Mettre à jour son dépot local avec la dernière version du dépot distant:
$ git pull
Si nous avons un accès en écriture sur le dépot distant:
$ git push
Avec ses quelques commandes nous pouvons débuter notre projet, mais avant celà voyons de plus près ce que git nous offre comme possibilité pour la gestion des fusions de branches.
Débutons dans l'initialisation du projet 'MonApp' en créant un dépot git :
$ mkdir MonApp $ cd Monapp $ git init
Ajoutons le fichier
test.pl
à ce dépot:
#!/usr/bin/env perl print "Hello, world.\n"; __END__
La prise en compte de ce fichier dans le dépot s'effectue avec les commandes suivantes:
$ git add test.pl $ git commit -m 'initial import' Created initial commit 076deff: initial import 1 files changed, 5 insertions(+), 0 deletions(-) create mode 100644 test.pl
L'informaticien étant par nature allergique au travail, il
s'applique toujours à éviter les frappes claviers inutiles. (ls pour
liste, mv pour move ...). Git n'y déroge pas, pourquoi entrer 'git commit
....' alors qu'un 'git ci' ferait très bien l'affaire. Pour faire la
relation entre ces deux écriture nous utiliserons les alias du fichier
~/.gitconfig
:
[alias]
st = status
di = diff
co = checkout
ci = commit
br = branch
sta = stash
Nous souhaitons maintenant modifier notre fichier test.pl mais sans ruiner le travail déjà effectué. Pour cela nous allons créer une branche 'refactor' de notre dépot:
$ git co -b refactor Switched to a new branch "refactor"
Maintenant modifions le
fichier
test.pl
en y intégrant la fonction
say_hello
:
#!/usr/bin/env perl say_hello(); sub say_hello { print "Hello, world.\n"; } __END__
suit la transmission de cette modif:
$ git ci -a -m 'factor print into a subroutine' Created commit e2fa717: factor print into a subroutine 1 files changed, 6 insertions(+), 2 deletions(-)
J'ai une idée pour une nouvelle fonctionnalité, je vais donc faire une nouvelle branche mais avant de l'utiliser je souahite modifier à nouveau mon fichier test.pl :
$ git branch new-ui
Puisque nous sommes toujours dans la branche 'refactor' remplaçons cet affreux 'print' :
#!/usr/bin/env perl use 5.010; say_hello(); sub say_hello { say "Hello, world."; } __END__
( Perl en 5.10 fourni say équivalent à un print + '\n' )
$ git ci -a -m 'use say instead of print' Created commit b000780: use say instead of print 1 files changed, 2 insertions(+), 1 deletions(-)
OK notre travail est sauvegardé, basculons dans notre branche 'new-ui' :
$ git co new-ui Switched to branch "new-ui"
Ajoutons une super fonctionnalité, l'affichage triple de hello world.
#!/usr/bin/env perl say_hello(); say_hello(); say_hello(); sub say_hello { print "Hello, world.\n"; } __END__
Et on transmet:
$ git ci -a -m 'say hello three times' Created commit 25291e8: say hello three times 1 files changed, 2 insertions(+), 0 deletions(-)
Malheureusement la direction n'a pas encore approuvée le changement de la branche UI et la version de Perl sur les serveurs de production n'est pas en 5.10 :(
Alors nous revenons à la version 'Master' et y ajoutons la documentation:
$ git co master Switched to branch "master"
Nous éditons notre fichier
test.pl
:
#!/usr/bin/env perl print "Hello, world.\n"; __END__ =head1 NAME test.pl - say hello to the world =head1 SYNOPSIS perl test.pl
Et on transfert :
$ git ci -a -m 'add docs' Created commit febc2de: add docs 1 files changed, 11 insertions(+), 0 deletions(-)
Après quelques temps nous recevons un mail de l'équipe UI qui aime beaucoup notre "say hello 3 times". Nous fusionnons alors cette branche avec la Master:
$ git pull . new-ui Auto-merged test.pl Merge made by recursive. test.pl | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-)
Le fichier test.pl devient alors:
#!/usr/bin/env perl say_hello(); say_hello(); say_hello(); sub say_hello { print "Hello, world.\n"; } __END__ =head1 NAME test.pl - say hello to the world =head1 SYNOPSIS perl test.pl
Pour vérifier changement de la branche :
$ git log
commit ab7c934d4c031cf0be0d57b6490a1c023e53a948
Merge: febc2de... 25291e8...
Author: dab <dab@tux1.(none)>
Date: Mon Dec 22 13:23:50 2008 +0100
Merge branch 'new-ui'
commit febc2dea2da7cf02e69cd9d2e9c38acffff293e4
Author: dab <dab@tux1.(none)>
Date: Mon Dec 22 13:20:43 2008 +0100
add docs
commit 25291e84f52140fc8cd1280bbdaadcc1bbae1fca
Author: dab <dab@tux1.(none)>
Date: Mon Dec 22 12:15:27 2008 +0100
say hello three times
commit e2fa717f4932872dbc014002ebce7e54b1feae53
Author: dab <dab@tux1.(none)>
Date: Mon Dec 22 12:00:12 2008 +0100
factor print into a subroutine
commit 6664c997140700d8cfe8ead8f587aab4bbbdb9f3
Author: dab <dab@tux1.(none)>
Date: Mon Dec 22 11:43:22 2008 +0100
initial import
Nos serveurs de production sont enfin passés en version 5.10 de Perl. Le problème est que notre branche UI que nous avons fusionnée avec Master contient déjà des modifications de la branche 'refactor' :( Est-ce que git appliquera deux fois les changements ?
$ git pull . refactor Auto-merged test.pl Merge made by recursive. test.pl | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
Comme prévu, il a travaillé parfaitement, voyons voir les changements:
#!/usr/bin/env perl use 5.010; say_hello(); say_hello(); say_hello(); sub say_hello { say "Hello, world."; } __END__ =head1 NAME test.pl - say hello to the world =head1 SYNOPSIS perl test.pl
Même si nous avons fusionné les branches dans le Master nous pouvons toujours travailler avec.
$ git co new-ui $ git rebase master
'rebase' fusionne la branche master dans la branche courante, cette dernière est alors à jour avec la branche master.
Nous allons maintenant voir comment fusionner deux branches dans une seule. Pour cela nous basculons sur la branche Master et créons la nouvelle branche doc-refactor.
$ git co master Switched to branch "master" $ git co -b doc-refactor Switched to a new branch "doc-refactor"
Ajoutons un peu de documentation à notre script
test.pl
:
__END__ =head1 NAME test.pl - say hello to the world =head1 SYNOPSIS perl test.pl =head1 HISTORY As of version 0.01, C<test.pl> now prints "Hello, world." three times, for maximum enjoyment.
$ git ci -a -m 'explain the 3x feature' Created commit 2da7522: explain the 3x feature 1 files changed, 6 insertions(+), 0 deletions(-)
Pendant ce temps un bug vient juste d'être découvert. Un utilisateur attend trop longtemps lors de l'affichage de la virgule de 'Hello, World'. Nous devons donc retirer la virgule. La correction de ce bug peut prendre plusieurs jours, nous allons donc créer une nouvelle branche sur laquelle nous ferons la correction :
$ git branch comma-bug-fix master $ git co comma-bug-fix ... correction du bug ... $ git ci -a -m 'fix the comma bug' Created commit 99d401a: fix the comma bug 1 files changed, 1 insertions(+), 1 deletions(-)
Après divers vérifications nous pouvons fusionner avec la branche master:
$ git co master $ git pull . comma-bug-fix doc-refactor Trying simple merge with 99d401a4295cd98f3d621a9c2de4829abdff877c Trying simple merge with 2da7522bf98964a227dd0c188ca66d35c9d02a70 Simple merge did not work, trying automatic merge. Auto-merging test.pl Merge made by octopus. test.pl | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-)
Finalement nous pouvons lister et supprimer les branches qui nous sont devenues inutiles :
$ git branch comma-bug-fix doc-refactor * master new-ui refactor $ git branch -d refactor new-ui comma-bug-fix doc-refactor Deleted branch refactor. Deleted branch new-ui. Deleted branch comma-bug-fix. Deleted branch doc-refactor.
Git s'interface avec les autres gestionnaires de versionning. Pour s'en convaincre voyons comment git travaille avec les dépots subversion:
$ git clone svn://svn.toto.org/the_project -T trunk -b branches -t tags
Attention cette commande peut être très gourmande en ressources. en effet elle importe le projet 'the_project' ainsi que les branches et les tags. Toutes les modifications apportées au dépot subversion du projet sont intégrer au nouveau dépot git. (git log pour s'en convaincre).
A ce niveau soit l'on modifie notre dépot distant pour qu'il devienne un dépot git ou encore on continue à travailler en svn :
$ git-svn rebase $ git-svn dcommit
Pour recevoir ou transmettre les modifications.
Il est aussi possible de récuprer un dépot CVS:
git-cvsimport -d:pserver:anonymous@cvs.toto.org:/the_project la_cible
' git-gui ' est une interface tk8 permettant de visualiser un dépot local. On se place simplement dans le répertoire du projet et on exécute 'git-gui'.
'
gitweb
' se présente comme un
script cgi à porter sur un serveur Web. Par défaut le script
/usr/lib/cgi-bin/gitweb.cgi
regarde dans le
répertoire
/var/cache/git/
( configurable dans
/etc/gitweb.conf
). Pour y intégrer un nouveau dépot
il suffit d'y créer un lien symbolique :
ln -s /home/gaston/monprojet/.git /var/cache/git/monprojet.git
Et ensuite de se rendre sur http://localhost/cgi-bin/gitweb.cgi



Commentaires: