Git ou le gestionnaire de version ultime

user_icon admin | icon2 Système | icon4 22/12/2008 13h50| Type doc: article| Type File: xml| icon3 2 Comments

Git ou le controle de version ultime


1. Intro

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. » :)

2. Débuter avec 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.

3. Les fusions

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.

4. Git et les autres

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

5. Visualiser un dépot git

' 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:

user_iconUlhume icon4 19/1/2009 - 23h5

Je vois que l'on explore les mêmes pistes :) J'ai découvert GIT en "bossant" avec les gars du pilote intel et j'avoue que le zinzin est assez impressionnant. Maintenant, j'ai pas trop envie de m'y pencher sinon je vais devoir maintenir deux outils de versionning ;-)


user_iconDab icon4 20/1/2009 - 17h53

Je dois avouer qu'actuellement j'utilise encore svn mais si je le compare a git je lui ferait deux reproches:

- Nécessité de créer le dépot à la mano

- Gestion des branches beaucoup moins souple

En plus y a tout un tas d'outils accompagnant ... le zinzin :) dont le fameux clone (svn vers git). Je crois bien que je vais tout de même franchir le pas



Add_a_comment

Validator_logo
Catapulse v0.06
( 0.079543 s)