VersionControlSystem/Distributed/Git

Un article de Agora2ia.

< VersionControlSystem | Distributed(Redirigé depuis Git)


Sommaire

Présentation

"Git est un système de gestion de versions décentralisé. C'est un logiciel libre créé par Linus Torvalds, le créateur du noyau Linux, et distribué sous la GNU GPL version 2." (Git - Wikipedia)

Il s'agit d'un GestionnaireDeVersionDecentralise ou DistributedVersionControlSystem (DVCS) comme Mercurial.

Il s'agit donc de cette nouvelle vague de GestionnaireDeVersion, qui permettent un fonctionnement :

  • "coupé" du serveur / repository central
  • et / ou collaboratif.


Il existe de nombreux site permettant d'héberger des dépôts Git : le plus connu est GitHub (github.com).


Deux modèles de collaboration

Fork & Pull

Utilisé le plus souvent sur les plus grands projets ou des projets open sources, les contributeurs travaillent sur leur version du repository, le fork, puis soummettent leurs modifications, le pull afin qu'un mainteneur les acceptent ou non.

Voir plus bas #Pull_Request, notamment pour notifier le mainteneur.


Shared Repository

Utilisé le plus souvent sur les projets internes ou les projets personnels, les contributeurs ont tous accès au repository pour directement y pousser leurs modifications.

Cela permet d'éviter une tâche de coordination.

Dans ce cas, l'utilisation de branches thématiques (par exemple une branche par issue / ticket / tâche / story...) est fortement recommandé.


Bonnes pratiques


Clients

Personnellement, j'utilise (gratuits) :


Ressources


Utilisation

Quelques liens

Installation

Pour installer sur sur Mac OS X, télécharger l'installeur sur http://code.google.com/p/git-osx-installer/


Use Cases

Générer une clef publique

Issu du Guide GitHub

  • Depuis le repertoire de l'utilisateur
    • cd .ssh
    • ssh-keygen -t rsa
      • Ne pas entrer de nom de fichier ('enter' directement)
      • Passphrase
      • Passphrase bis
  • ssh-add id_rsa (obligatoire ?)
  • Copier le contenu du fichier id_rsa.pub dans la page web github.com


Publier son répertoire de travail

Depuis le répertoire racine :

  • git init
  • git add .
  • git commit -m 'first commit'
  • git remote add origin git@github.com:myproject/myproject.git
  • git push origin master


Obtenir une version locale (de travail)

Dans la terminologie Git on parle de "clone" :

git clone git@github.com:myproject/myproject.git


Je ne sais pas si il est possible d'obtenir qu'une partie (un sous répertoire) de l'arborescence, comme c'est le cas par exemple avec Subversion en complétant l'URL du dépôt central avec le chemin du sous répertoire souhaité...


Remonter ses dernières modifications

Pour remonter vos modifications il faut :

  1. Ajouter les nouveaux fichiers
  2. Valider les changements (ajouts, suppressions et modifications)
  3. Remonter ces changements sur le dépôt central

Ce qui donne :

>cd ..
>git add .
>git commit -a -m 'New fixtures.'
>git push origin master

Il se peut que lors du git push vous receviez le message d'erreur suivant :

To git@github.com:myrepo/myproject.git
 ! [rejected]        master -> master (non-fast forward)
error: failed to push some refs to 'git@github.com:myrepo/myproject.git'

Cela signifie que votre copie de travail locale n'est pas à jour. Il suffit d'obtenir au préalable la dernière version via un git pull puis de relancer le git push.

Mais de toute façon, est-ce bien raisonnable de faire autrement que systématiquement faire un pull avant un push ?!...


Supprimer un répertoire du repository

Vous avez par exemple intialiser votre repo avec l'arborescence de votre projet initial, en oubliant d'ignorer le répertoire build. Depuis la racine de votre projet :

  1. git filter-branch --tree-filter 'rm -rf build' master
  2. git push origin master --force

Et bien souvent, il ne faudra pas oublier d'ajouter au .gitignore le répertoire en question pour éviter que cela se reproduise !


Poser un tag

Pour poser un tag anoté (avec le nom skippers-0.3):

  • git tag skippers-0.3
  • git push --tags

Pour voir la différence entre les divers types de tags :


Ignorer un répertoire

Pour ignorer tout chemin contenant le nom répertoire xcuserdata :

  1. Ouvrir le fichier .gitignore
  2. Y ajouter la ligne xcuserdata/
  3. Sauvegarder

L'instruction est alors déjà opérationnelle...

Mais ne pas oublier quand même de commiter !


Ajouter la couleur au terminal dans Mac OSX

  • git config --global color.ui true


Modifier le message du dernier commit (par encore pushé)

  • git commit --amend -m "New commit message"


Modifier le message du dernier commit (déjà pushé)

Voir http://stackoverflow.com/questions/8981194/changing-git-commit-message-after-push-given-that-no-one-pulled-from-remote

  • git commit --amend -m "New commit message"
  • git push --force


Créer une branche sur un tag

  • Créer une branche entity-jpa-branch à partir du tag JeeTuto-0.3 :
git branch entity-jpa-branch JeeTuto-0.3
  • Positionner la copie locale sur cette branche :
git checkout entity-jpa-branch
  • Ou utiliser l'option -b pour faire les deux d'un coup (création et activation) :
git checkout -b entity-jpa-branch


Supprimer tous les fichiers non tackés / revert

'Revert All Uncommitted Changes in Working Copy' :

git clean -fd


Faire une archive des sources

Equivalent du svn export.

Avec git, étant donné que l'arborescence projet contient l'intégralité de l'historique (dans des répertoires invisibles .git), si vous compressez directement l'arborescence, vous allez avoir une archive plus volumineuse que necessaire.

Il est donc conseillé d'exporter que les sources, et pour cela il y a deux possibilités :

  • Soit vous utilisez github, et vous avez posé un tag, et dans ce cas, depuis la page du projet vous pouvez télécharger les sources depuis le bouton code puis l'onglet tags
  • Soit vous pouvez utiliser la commande git archive :
    • git archive master | tar -x -C /somewhere/else
    • git archive master | bzip2 >source-tree.tar.bz2
    • git archive --format zip --output ../projectname-1.2.3.zip master
    • git help archive (pour plus de détails)


Commit / push avec un autre compte

Annulations


Annuler les modifications locales

  • git checkout -f
  • git pull


Annuler le dernier commit (par encore pushé)

  • git reset --soft HEAD^

Attention, le dernier caractère est important !!!


Branches

Généralités


Créer une branche sur un tag

Push a Branch

git push origin my_branch

Voir aussi : http://www.debianworld.org/Git-pousser-branche-depot-distant


Supprimer une branche

En local :

git branch -D my_branch

Sur le repository :

git push origin --delete my_branch


Branches thématiques

Workflow pour travailler et merger une branche de travail.

Le cas d'utilisation est le suivant : Nous travaillons sur un module, pour lequel il y a une branche. Et sur cette branche module, il y a une sous branche développement (du module). Ainsi, on travaille sur la branche développement, puis on l'intègre à la branche module, qui elle même est intégrée à la branche principale à la fin.

  • Créer la branche de développement :
    • git branch 1-ejb3-stateless-dev
  • Se positionner sur la branche de développement :
    • git checkout 1-ejb3-stateless-dev
    • git add / commit
  • Revenir sur la branche du module :
    • git checkout 1-ejb3-stateless
  • Merger la branche de développement vers la branche du module :
    • git merge 1-ejb3-stateless-dev
  • Si ça s'est bien passé on peut directement pousser les modifications sur le repository distant (et si il y a des problèmes, il faut les résoudre à la main puis faire un git add / commit avant) :
    • git push -u origin 1-ejb3-stateless
  • Si vous utilisez Maven, c'est peut-être maintenant qu'il faut mettre à jour la version des pom.xml (sinon c'est peut être le moment de poser un tag ?) :
    • mvn release:prepare -Dresume=false
  • Passer sur la branche principale :
    • git checkout master
  • Merger la branche de la branche du module vers la branche principale :
    • git merge 1-ejb3-stateless
  • Si ça s'est bien passé on peut directement pousser les modifications sur le repository distant (et si il y a des problèmes, il faut les résoudre à la main puis faire un git add / commit avant) :
    • git push


Fork


Pull Request

Cela peut se faire :

  • directement depuis Github (envoi un mail au mainteneur)
  • ou en ligne de commande :
git request-pull origin/master my_working_branch

Depuis Github il y a plusieurs notions à comprendre :

  • base repo (branch) est le repo (la branche) cible, le plus souvent celui (celle) à partir du quel (de laquelle) on a fait le fork initial. Changer ce dernier modifiera le mainteneur qui sera notifier.
  • head repo (branch) est le repo (la branche) que l'on souhaite pousser (le plus souvent la branche thématique sur laquelle on vient de travailler et commiter).


Fork

Comme indiqué au début (Fork & Pull), la pull request est surtout utilisée dans le modèle collaboratif Fork & Pull. Cela implique donc de commencer par un fork : voir #Fork


Validation des commits

git diff --check


Rebase

Dans le cas où la branche / pull request repose sur un ancien commit de la branche principale : il faut rebaser la branche sur le dernier commit avant de pouvoir faire l'intégration.

git checkout fonctionA
git rebase origin/master
git push –f macopie fonctionA