Git-tfs : Utilisation de Git avec un serveur TFS

Publié le 3/11/2012, par Philippe Miossec dans Valtech | 1 Commentaire

Le contrôleur de code source TFS est bien souvent utilisé en entreprise.

Le contrôleur de code source Git apporte pourtant une plus grande souplesse d’utilisation et de nombreux avantages par rapport à le gestion de code source de TFS.

Nous allons donc voir comment nous pouvons utiliser Git en local tout en utilisant TFS côté serveur et ainsi en tirer de nombreux avantages.

1.Installation des outils nécessaires

  • Installation de GitExtension(et Git)→ Utilisation d’OpenSsh (facultatif)→ Décocher l’option GitGUI (facultatif)→ Options par défaut de Git sauf : “Checkout as-is, commit as-is”
  • Installation de p4merge , Telechargement(besoin d’un outil de 3way-merge!)→ Lors de la sélection des composants à installer, TOUT décocher sauf “Visual Merge Tool (P4Merge)”.
  • Installation de notepad++ (besoin d’un éditeur de texte multi-instances!!)
  • Copie des fichiers de Git-tfs dans le répertoire de Git. Pour le moment, la gestion des branches par git-tfs que j’ai développé n’étant pas encore dans la version officielle 0.15 de git-tfs (pull request en attente de validation sur GitHub), on utilisera plutôt une version personnelle de git-tfs La version officielle stable 0.16 gère maintenant les branches TFS!
  • Verifier que le répertoire ‘bin’ de Git est dans le path ainsi que celui des outils p4merge et notepad++.

Avant-propos : Pour consulter l’aide d’une commande git :

git commit -h //aide de la ligne de commande
git help commit //aide html complete de la commande (page man)

2.Configuration de Git & GitExtension

3 moyens…

  • Edition directement du fichier .gitconfig (situé dans le répertoire utilisateur)

Bootstrap : Télécharger l’archive et copiez le contenu dans votre répertoire utilisateur puis…→ Edition du fichier .gitconfig (mettre vos informations personnelles!)→ Utilisation d’un .gitignore global (si vous ne voulez pas archiver un fichier .gitignore dans TFS) => Copie du .gitignore_global( ou celui de GitHub )

  • Par ligne de commande

Les configurations nécessaires pour faire fonctionner Git:

git config --global user.name "Ton Nom"
git config --global user.email ton_mail@valtech.fr

Les configurations nécessaires pour faire fonctionner Git sous Windows!:

git config --global core.ignorecase true
git config --global core.autocrlf false

Consultation de la liste des configurations :

git config -l
git config --global -l
git config --local -l
  • Depuis GitExtension

Au lancement de GitExtension, vérifier que le checkup est bon!Ou configurer en conséquence…Menu “Settings”→“Settings…”→Onglet “Global Settings”Editor :

notepad++ -multiInst -notabbar

MergeTool : p4merge

MergeTool Path :

C:/Program Files (x86)/p4merge/p4merge.exe

MergeTool command :

"C:/Program Files (x86)/p4merge/p4merge.exe" "$BASE" "$LOCAL" "$REMOTE" "$MERGED"

Difftool : p4merge

Difftool Path :

C:/Program Files (x86)/p4merge/p4merge.exe

Difftool command :

"C:/Program Files (x86)/p4merge/p4merge.exe" "$LOCAL" "$REMOTE"

3.Rappels sur Git!

Git est :

  • un gestionnaire de contenu (et non de différence!)
  • stocké sous la forme d’un graphe acyclique d’objets ou DAG
  • accessible avec des références
Exemple de graphe acyclique --historique du dépot--
Exemple de graphe acyclique représentant l’historique du dépot

Toute manipulation de Git ne fait que manipuler ce graphe… (Ne jamais l’oublier et essayer de visualiser cela!!)

…en ne faisant qu’ajouter des commits!

4.Présentation de GitExtension

Interface de GitExtension montrant le DAG d’historique du dépot

GitExtension est une interface très performante à Git qui permet :

  • Consultation du graphe de commits (diff)
  • Zone de staging , ajout de fichiers, de lignes
  • Message de commits, templates, workitems, commit local, amend
  • Stash, Merge, Rebase
  • Fetch, Fetch et Rebase, Commit
  • Historique (blame)

5.Utilisation de Git-TFS:

_Note :

  • On pourra tester toutes les commandes git-tfs indiquées en utilisant le projet “valtechgittfs” disponible sur Codeplex Pour cela, on pourra utiliser le compte utilisateur ‘vtccds’ (mot de passe:vtccds)_
  • Attention : Lors de l’interaction avec le serveur TFSde Codeplex, le login à fournir est de la forme (sans les crochets!): [LoginCodePlex]_cp@sndLe mot de passe reste celui du compte Codeplex.

5.1. Clonage du dépôt TFS

Commande de clone (dans le répertoire courant) du dépot TFS avec historique (conseillé! mais –très– long…):

git tfs clone http://monServeurTfs:8080/tfs/DepotTfs $/MonProjet/NomDuTronc .

exemple:

git tfs clone https://tfs.codeplex.com:443/tfs/TFS16 $/valtechgittfs/trunk . --username=vtccds_cp@snd --password=vtccds

Note : Attention à ne cloner que le répertoire correspondant à la branche principale du projet (le tronc) et non pas tout le dépot entier!

Commande de clone (dans le répertoire courant) du dépot TFS sans historique (dernier changeset):

git tfs quick-clone http://monServeurTfs:8080/tfs/DepotTfs $/MonProjet/NomDuTronc .

exemple:

git tfs quick-clone https://tfs.codeplex.com:443/tfs/TFS16 $/valtechgittfs/trunk . --username=vtccds_cp@snd --password=vtccds

Convient pour un développement ponctuel ou lorsqu’on n’a pas besoin de l’historique…

Note :

  • le clone ne doit pas être fait dans un répertoire mappé avec TFS (workspace).
  • on peut partager le dépot cloné juste par copie (ou par clonage git!) à un autre développeur.

5.2. Récupération des commits de TFS (sans merge ni rebase dans branche master)

git tfs fetch

5.3. Création des commits locaux

Lors des commits locaux dans Git, l’association de Workitems se fait par l’ajout des meta-données suivantes dans la description du commit

git-tfs-work-item: 2198 associate //Pour associer un workitem
git-tfs-work-item: 2198 resolve //Pour clore le workitem

5.4. Report des commits locaux sur le serveur TFS

Méthode facile mais déconseillée :

git tfs ct

Cette commande ouvre la fenêtre de commit de TFS (message + association de workitems) mais crée un commit de merge (moche et peut y avoir des conflits de merge au moment du commit :( )

Méthode conseillée :

git tfs rcheckin

Cette commande ré-applique les commits sur le serveur TFS. Cependant, nécessite d’être à jour par rapport aux commits sur TFS et d’avoir “rebasé” ses commits locaux.

Nécessite également de ne pas avoir de modifications dans l’espace de travail :(

git stash save //pour mettre les modifications de côté
//Commit...
git stash pop //pour récupérer les modifications mises de côté

Worklow utilisé en découlant :

git tfs fetch ==>récupération de derniers commits du serveur
git stash save ==>mise de côté des modifications non commitées
git rebase tfs/default =>réapplication des commits locaux sur la dernière version de TFS (merges possibles!)
git tfs rcheckin => réapplication des commits sur TFS
git stash pop => réapplication des modifications non commitées

Ajout d’alias pour automatiser ce workflow:

Pour synchroniser ses modifications avec la dernière version de TFS:

git config --global alias.tfsrebase '!sh -c "git tfs fetch && git stash save && git rebase tfs/default && git stash pop"'

→Utilisation: git tfsrebase

Pour commiter sur TFS:

git config --global alias.tfscommit '!sh -c "git tfs fetch && git stash save && git rebase tfs/default && git tfs rcheckin && git stash pop"'

→Utilisation: git tfscommit

5.5.Scripts GitExtension:

Il peut être pratique de créer dans GitExtension les scripts décrit ci-dessous; ensuite disponibles par un clic droit dans le Browser de GitExtension.

Pour cela, allez dans le menu “Settings”→“Settings…”→Onglet “Scripts” et ajoutez un ligne où on remplira les 3 champs requis par les valeurs de chaque ligne :

Name Cmd. Arguments
Tfs(Tronc)> Fetch git tfs fetch
Tfs(Tronc)> Fetch and Rebase git tfsrebase
Tfs(Tronc)> Commit git tfscommit

5.6.Gestion d’une branche de TFS:

Notes préalable :

  • La création d’une branche doit toujours être effectuée avec TFS. Dès sa création, on peut ensuite la récupérer avec git-tfs et travailler avec.
  • Rien n’empêche le développeur de créer des branches locales avec Git mais si une branche doit être partagée par tous les développeurs, alors la branche doit être créé préalablement sur TFS.

Récupération d’une branche TFS

Solution déconseillée :

  • Créer un nouveau dépot Git avec la seconde branche (cf clone vu précédemment)
  • Inconvénients : on ne peut pas backporter des corrections et voir les différences entre les branches!

Solution Plus convenable:

Utiliser la customisée de git-tfs contenant la commande “init-branch” :

git tfs init-branch $/MyProject/MyTFSBranch //Pour récupérer une branche spécifique
git tfs init-branch --all //Pour récupérer toutes les branches existantes
ex : git tfs init-branch $/valtechgittfs/branche1

Récupération des commits d’une branche:

git tfs fetch -i branche1

Commiter sur une branche TFS:

git tfs rcheckin -i branche1

Ajout d’alias pour automatiser le workflow précédent avec des branches:

Pour synchroniser ses modifications avec la dernière version de la branche sur TFS:

Création de l’alias git :

git config --global alias.tfsrebasebranch '!sh -c "git tfs fetch -i $1 && git stash save && git rebase tfs/$1 && git stash pop"'

Utilisation: git tfsrebasebranch branche1

Pour commiter sur la brance sur TFS:

Création de l’alias git :

git config --global alias.tfscommitbranch '!sh -c "git tfs fetch -i $1 && git stash save && git rebase tfs/$1 && git tfs -i $1 rcheckin && git stash pop"'

Utilisation: git tfscommitbranch branche1

5.7.Scripts GitExtension (suite):

Menu “Settings”→“Settings…”→Onglet “Scripts” et ajoutez un ligne où on remplira les 3 champs requis :

Name Cmd. Arguments
Tfs(Branche)> Fetch sh -c "git tfs fetch -i $(echo {sRemoteBranch} | sed 's/tfs\///')"
Tfs(Branche)> Fetch and rebase sh -c "git tfsrebasebranch $(echo {sRemoteBranch} | sed 's/tfs\///')"
Tfs(Branche)> Commit sh -c "git tfscommitbranch $(echo {sRemoteBranch} | sed 's/tfs\///')"

Note: Pour les utiliser, bien faire attention à cliquer sur la ligne du commit où se trouve la branche distante ‘tfs/maBranche’ (en vert, dans GitExtension)

5.8.Travailler avec les shelvesets

Liste de ses commits réservés

git tfs shelve-list

Ceux d’un autre utilisateur:

git tfs shelve-list -u LOGIN_UTILISATEUR

Créer une branche à partir d’un shelveset:

git tfs unshelve MonShelveset MaBranche

Créer un commit réservé de la branche courante:

git tfs shelve MonShelveset

Avantage de la branche Git sur le shelveset TFS :

  • on peut faire plusieurs commits
  • on connait le commit parent et voit exactement les modifications faites (là ou TFS présente seulement un état de fichier et on ne sait pas comment il serait mergé!)
  • mergeable plus facilement (moins sensible au modifications)

6.Utilisation de Git

  • Règle de Base : Ne JAMAIS modifier des commits déjà partagés!!!!!!
  • Mise de coté des fichiers modifiés de l’espace de travail (fonctionne comme une pile)
git stash save //pour mettre de côté
git stash pop //pour récupérer le dernier stash mis de côté
  • Reset d’une branche à un certain commit (Mixed/Hard)
  • Merge / Rebase

Le merge :

  1. crée un commit supplémentaire pour réunir les 2 branches.
  2. Il permet de matérialiser l’introduction d’une fonctionnalité dans une branche.
  3. Cette opération peut être réalisée avec des fichiers modifiés dans l’espace de travail.
le DAG après un merge : le commit C6 est un commit de merge

Le rebase :

  1. réapplique les commit d’une branche sur un commit.
  2. Il permet d’avoir un historique linéaire.
  3. Cette opération ne peut être réalisée avec des fichiers modifiés dans l’espace de travail (nécessité de faire un stash auparavant).
le DAG après un rebase : le commit C3 est réappliqué sur la branche master…
  • J’ai commité dans le tronc alors que je voulais faire une branche
  • un bug à résoudre rapidement alors que je suis en plein développement
  • Modification des commits existants (pour par ex. rajouter l’association de workitems!)
git rebase -i HEAD~n (avec 'n' à remplacer par le nombre de commit qu'on veut réécrire)

Attention : Ne pas enfreindre la règle de base!!!

  • Historique des opérations (et réparation des erreurs!) :
git reflog => voire l'historique des modification
git branch MaBranche d995afd => creation d'une branche sur un commit (en indiquant son sha1)
  • Astuce: Git ne fait qu’ajouter des commits et n’en détruie AUCUN! (sauf lors du passage du Garbage Collector tous les 30 jours pour effacer ceux non utilisés).Donc avant de faire une opération dont vous n’avez pas l’habitude, vous avez juste à créer une branche là où vous êtes qui vous servira de sauvegarde!Et à l’effacer quand vous avez réussi…
  • Trouver un commit fautif : Bisect !

7. Aperçu de Git-TF

  • Par défaut, création d’un seul commit de merge (utiliser l’option ––deep pour réappliquer les commits locaux sur le serveur TFS) et perte des messages de commit (sauf le dernier)
  • Association des workitems dans la ligne de commande (donc pas de possibilité d’utiliser depuis une GUI :( )et même association de workitems pour TOUS les commits (si utilisation de l’option ––deep. Et apparement il y aurait un bug :( )
  • Pas de gestion des branches (un clone, donc un dépot par branche)
  • C’est du Java

8. Retour d’expérience

Avantages:

  • Connaissance à tout instant de quelle version on utilise localement
  • Branches et commits locaux (expérimentation, retour en arrières, meilleur développement, baby steps,…)
  • Meilleur connaissance des modifications des autres utilisateurs (visualisation de l’historique + diffs)
  • BEAUCOUP plus grande souplesse de développement et de commit (commit de parties de fichiers!)
  • Remplacement du shelving par les branches ( et on peut faire plusieurs commits)
  • Commit de Revert
  • Bisect : trouver une régression facilement en testant les commits successivement par dichotomie
  • Cherry Picking (prendre un commit intérressant d’une branche et l’appliquer sur la branche actuelle)
  • Meilleur Historique
  • Plus de mode connecté/déconnecté de TFS :D
  • Backport de commit entre branches plus facile
  • Visual Studio est plus rapide car il n’a pas à contacter le serveur TFS pour extraire les fichiers en modifications (ainsi que beaucoup d’autres actions qui sont faites maintenant localement : blame, diff, …)

Inconvénient:

  • Ticket d’entrée légèrement plus important (il faut comprendre/visualiser les manipulations du DAG)
  • Rechargement des fichiers et projets plus souvent que sous TFS (à cause de la glue Git-tfs qui créé les commits sur TFS, les récupère et fait un rebase dessus. Non présent sur un dépot distant Git qui ne fait qu’envoyer les commits sur le dépot distant…)
  • (?) Visual Studio exclue régulièrement des fichiers App.config & Dev.config de la Solution….

9. Conclusion

Beaucoup d’avantages, quelques petits désagréments

TFS est une solution d’archivage, Git est un outil servant à faciliter un développement

PS :

  • Vous avez toutes les infos pour utiliser Git-tfs mais il vous reste à apprivoiser Git…
  • Documentation
  • Un petit tutoriel assez marrant pour apprendre les commandes de base de git (et voir comment elles sont mieux pensées que celles de TFS ;) )

(c) Image de GitExtension par le site de GitExtension : http://code.google.com/p/gitextensions/
(c) Images de DAG Git par http://git-scm.com/

One Response to “Git-tfs : Utilisation de Git avec un serveur TFS”

  1. GitStack says:

    Bonjour,

    Merci pour ce rappel sur Git, son installation et toutes ces astuces qui seront contentés les internautes intéressés par Git.

    Nous confirmons que la plupart des points sur Git sont des avantages même si certains points à améliorer subsistent (comme toute technologie).


    L’équipe GitStack

Leave a Reply