Geneanet • 24–25 octobre 2013
Git TotalFormation intra-entreprise chez Geneanet
Delicious Insights
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 2
§ Christophe Porteneuve§ Git + github depuis 2008
§ Open-source (Rails, Prototype, Sprockets, etc.)§ Privé / Corporate (~100 projets)
§ Co-fondateur et CTO, Delicious Insights§ Créateur des formations Git Attitude et JS Attitude
$ whoami
10 octobre 2011 3
La gestion de versions : pourquoi, comment ?
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 4
§ On veut toujours pouvoir revenir en arrière…§ Parce qu’on s’est trompé§ Parce qu’on veut comparer§ Parce qu’on veut sauvegarder§ …
§ On veut pouvoir travailler à plusieurs…§ sans se marcher dessus§ sans devoir tout consolider manuellement§ sans se bloquer les uns les autres§ en réseau… ou hors-ligne !
Pourquoi gérer des versions ?Parce que sinon c’est la chienlit…
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 5
À la base : des sauvegardes locales…et souvent manuelles ! Ou RCS, PVCS, Time Machine…
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 6
Puis vinrent les gestions centraliséesCVS, Subversion (SVN), ClearCase, VSS, Perforce, TFS, RTC…
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 7
Et enfin les gestions distribuéesDarcs, DCVS, Git, Mercurial, Bazaar, Fossil…
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 8
Principaux avantages du décentraliséC’est le top, mais ‘faut dire pourquoi…
§ Pas de criticité d'une seule machine (point de défaillance / SPF).§ Les contributeurs peuvent travailler déconnectés du « serveur ».§ On peut participer à un projet sans nécessiter les permissions par un
responsable du projet (les droits de commit/soumission peuvent donc être donnés après avoir démontré son travail et non pas avant) ; inestimable pour la contribution aux projets open-source.
§ La plupart des opérations sont (beaucoup) plus rapides, car locales !§ On peut faire du travail « privé » : des brouillons, des essais… sans
risque de gêner les collaborateurs.§ Rien n’empêche de garder un dépôt de référence, avalisé, sur lequel
seuls certains peuvent écrire.
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 9
Quelques concepts génériquesTout métier a son jargon
§ Commit / Révision / VersionSérie de modifications faisant l’objet d’une soumission unique, idéalement thématique et atomique. Reçoit un identifiant unique.
§ HeadDernier commit en date dans l’historique de référence actuel
§ Tag / LabelÉtiquette sémantique apposée sur un commit (ex. « v1.0 »). Un tag n’est pas censé être repositionné après coup.
§ DépôtEnsemble de révisions pour un même projet, local ou distant (sur un serveur), avec les méta-données associées.
§ BrancheHistorique thématique (série de révisions). Un même dépôt peut avoir plein de branches, comme un arbre.
§ Tronc / MasterLa branche de référence d’un dépôt
§ FusionRéconciliation des travaux de plusieurs branches pour un résultat consolidé
§ ConflitSituation empêchant une fusion automatique ; se résout manuellement
§ Working Directory/Tree/CopyL’état actuel sur le disque des dossiers et fichiers
git help glossary
10 octobre 2011 10
Configuration aux p’tits oignons
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 11
§ Installer un Git à jour correctement§ http://bit.ly/prepgit
§ Une configuration globale (pour votre profil utilisateur, tous dépôts confondus) bien pratique§ https://gist.github.com/470582§ Passons-la en revue ensemble…
§ Un ajustement de configuration de shell (Linux / OSX / fenêtre de commande msysgit)§ https://gist.github.com/473838§ Examinons le pourquoi du comment ensemble…
§ Quelques essais pour s’assurer que tout est au point
Vos besoinsPetit quiz rapide
10 octobre 2011 12
Concepts fondamentaux
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 13
Les zones« Où » est votre fichier
working directory stage git directory
(repository)
add commit
reset [--mixed]
checkout / reset --hard
Super ressource interactive : http://ndpsoftware.com/git-cheatsheet.html
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 14
Le cycle de vie du fichierDans quel(s) état(s) est votre fichier
modified staged unmodified
add
reset [--mixed]
untracked
commit
rm --cached
modifier le fichier
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 15
§ git add = prendre une photo, stocker dans l’index / le stage
§ git commit = prendre les photos du stage et en faire un commit (metadonnées + tree + blobs)
§ On peut donc avoir un même fichier dans deux zones (stage et WD) mais avec un état différent (staged, forcément, mais aussi dirty/changed) : il suffit de le modifier entre le add et le commit
Le stage / l’indexSouriez pour la photo
10 octobre 2011 16
Créer un dépôt
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 17
§ Soit on est les initiateurs du dépôt…1. git init2. Création éventuelle des .gitignore 3. git add .4. git commit -am "Import initial"
§ Soit on récupère un dépôt distant existant§ git clone git@monserveur:chemin/du/depot.git (R/W)§ git clone git://github.com:rails/rails.git (R/O)§ git clone http://lalose.net/depotpourri (R/O)
bientôt obsolète…
Vos besoinsPetit quiz rapide
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 18
git add . — ahem…git add -u : parce que tu avais oublié git rmgit add -A : combo classique + -u (WD + index)git add -f : même si le fichier est ignorégit add -i : pour ne prendre que des morceaux !git add -p : histoire d’accélérer le -i
git addTout est dans la granularité
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 19
git commit -m : le message à la voléegit commit -a : chopper tout ce qui est déjà tracké
§ Attention, pas les untracked !
git commit -am : la combogit commit … -- chemin… : juste certains fichiers
§ Et donc on ignore le stage sur ce coup
git commit -t template : gabarit de message
git commitDu plus long au plus court
Envie de voir sous le capot ?git help core-tutorial / git help tutorial-2
git help repository-layout
10 octobre 2011 20
Examiner en détail le WT, l’index, le dépôt…
Ah la vache c’estque tu as de bons
yeux dis donc
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 21
§ Permet de voir immédiatement§ Les fichiers non versionnés (untracked)§ Les fichiers modifiés non validés (modified)§ Les modifications validées (staged)§ Certains cas spéciaux (both modified : conflit de fusion…)
§ Fournit des indications utiles aux débutants§ Pour valider une modification§ Pour « dévalider » une modification validée§ etc.
§ On en a la version courte dans le prompt conseillé
git status« Bon j’en suis où là ?! »
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 22
git diff --stagedgit diff --stat/numstat/shortstat/dirstat[=…]git diff -wgit diff --word-diff/word-diff-regex=…§ Syntaxes d’intervalle§ Limitation à certains chemins
git diffMille et un formats
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 23
git log --stat/numstat/shortstat/dirstat[=…]§ Stats rapides sur l’impact du log sur le dépôt§ dirstat en particulier est sympa pour du 10,000-ft
git log --graph§ Histoire de visualiser les branches, fusions…
git log -p§ Afficher les diffs à la volée. Conserve le graphe !
git log --author=… : filtrer par auteurgit log --grep -E -i … : filtrer sur les messagesgit log -S / -G : filtrage sur les diffs (texte ou regex)
git logTellement plus d’infos
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 24
§ Affiche une entité Git (commit, tree, blob) de manière appropriée
§ git show commit§ Message + diff
§ git show blob§ Contenu du blob (fichier à une révision spécifique)§ Pratique en combo avec la syntax commit:path
§ git show tag§ Objet référencé (révision en général)
§ …
git showPour y voir clair
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 25
§ Très large gamme de possibilités§ git help rev-parse
§ sha/abbrev-sha : classique^, ^^, ^^^… ~n : parent, grand-parent, etc. (main line)^n : nième parent (pertinent sur merges seulement){date-spec} : top utile pour log/diff§ :0:path / :1:path / :2:path / :3:path
§ Le stage, l’ancêtre commun, le parent main line, le parent fusionné
§ @{n}, @{-n}§ Tout ça en suffixe d’une autre ref : combinable, donc…
Les syntaxes de révisionSoyons précis
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 26
§ HEAD§ La tête de la branche courante
§ ORIG_HEAD§ La version plus lisible de HEAD@{1}.
§ Précédente position de HEAD§ MERGE_HEAD, REBASE_HEAD
§ Révision en cours de fusion/rebase
§ FETCH_HEAD§ Révision distante qui a fait l’objet du dernier fetch (généralement la
tête de la branche distante)
Les révisions symboliquesÇa veut toujours dire la même chose
10 octobre 2011 27
Soucis classiques et solutions optimales
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 28
git commit --amend§ En fait un reset --soft HEAD^ suivi d’un commit classique…
git commit --amend -C HEAD (alias « git oops »)§ Récupérer le message d’origine, tel quel§ Ni vu ni connu, on croirait que t’avais tout bon du 1er coup
J’ai oublié un truc dans le commitEt c’est même pas la première fois
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 29
git reset§ Le couteau suisse de Git§ Une des commandes les plus méconnues pourtant :-(
git rm --cached§ Si ça n’a jamais été committé jusqu’ici§ Ou pour déversionner un fichier tout en le gardant dans le WD
J’ai stagé un truc que j’aurais pas dûUne erreur est si vite arrivée
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 30
§ Si ça vient d’arriver, il suffit de revenir en arrière avec un reset et de refaire le bon commit§ On combinera avec profit rm --cached et --amend…§ …ou simplement un reset --soft manuel
J’ai committé un truc en tropJe me méfie jamais assez de git add .
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 31
§ Tout dépend du niveau de confidentialité…§ Fichier confidentiel qui ne doit en fait figurer nulle part
dans l’historique : il va falloir réécrire l’histoire§ Le plus « simple » est un filter-branchgit filter-branch --index-filter \ 'rm --cached --ignore-unmatch SECRET.txt'§ Sinon une modif du commit fautif et un rebase par-dessus…§ Dans tous les cas, on flingue les SHA, il faudra faire quelques
forçages sur les pushes, fetches/pulls, etc.
§ Fichier non sensible, il faut juste le virer…§ Commit dédié, rien de spécial
J’ai committé un truc en trop (y’a un bail)Je sais j’aurais dû le voir avant
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 32
§ On était parti pour du chirurgical et puis on s’est laissé entraîner
§ Tirer parti du git add -p§ Retirer du stage « trop enthousiaste » avec git reset
ou git rm --cached (pour du non versionné jusqu’ici)§ Faire une série de commits atomiques
Ça va faire un commit fourre-tout…Je me suis plus senti j’ai tout patché
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 33
§ Déjà, le caler une bonne fois :git config --global user.namegit config --global user.email
§ Ensuite, recaler le commit qu’on vient de faire :git commit --amend --reset-author
§ Si on ne l’a pas encore fait, qu’on doit aller super vite et qu’on n’a pas le temps de faire la config globale là tout de suite :git commit --author= 'John Smith <[email protected]> 'git commit --author=john # Recherche dans l’histo du motif
J’ai oublié de configurer mon nom…Qui c’est qu’a pas bien configuré le serveur de prod ?
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 34
§ Virtuellement impossible§ git reflog§ Enregistre la séquence complète des positions
successives du HEAD (très pratique lorsqu’on se plante dans ses reset…)
§ « Strictement local » (tout commit y figurant qui n’est pas dans l’historique pushé reste local)
§ Purgé quand ?§ Au moment d’un GC (manuel ou auto)§ Selon les réglages gc.reflogExpire et gc.reflogExpireUnreachable
Eh ben voilà, ayé, j’ai paumé le commit !Je savais bien qu’à force de faire ces reset et trucs-machins là, j’allais me flinguer…
10 octobre 2011
Gérer l’imprévu (« ah non, pas maintenant !…»)
35
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 36
§ Le stash !§ Au-delà d’un simple stash / stash apply
§ stash save : message explicite, conserver le stage…§ stash pop --index§ stash branch
§ Également utile pour contourner une prudence parfois conservatrice§ Refus de merge (donc pull) en raison de fichiers modifiés (staged
ou dirty) également concernés par la fusion, alors qu’on sait pertinemment qu’on n’aura pas de conflit
§ stash + merge + stash pop --index !
Mais je suis en plein dans un truc là !Et c’est tout cassé, je vais pas en faire un commit…
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 37
§ Annuler le merge :-/§ Mais on n’est pas obligé de planter les modifs locales résiduelles
avec un git reset --hard :§ git reset --merge
§ Et si c’est un rebase…§ git rebase --abort
§ Et si je peux pas annuler le merge ?!§ Un peu chaud : cloner ailleurs, faire le commit + push…§ …puis finir son merge, et faire un git pull --rebase
(probablement) avant de pouvoir faire son push
C’est-à-dire que là je suis en plein merge…Donc sérieux le WT est dans un état plutôt bancal
10 octobre 2011 38
Branches et fusions : concepts, trucs & astuces
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 39
§ C’est un historique parallèle aux autres, qu’on peut faire évoluer, donc, sans gêner les autres
§ Grande liberté de manœuvre§ Nécessitera à terme une réconciliation entre branches :
on parle de fusion§ Divers workflows possibles ; dans un contexte produit
classique, ce modèle de chez nvie est pas mal…§ Git a le cheap branching : c’est instantané et ne coûte
pratiquement rien en mémoire/disque, alors ne surtout pas se priver !§ On amorce une tâche non triviale (< 5mn) : hop une branche !
Les branches, qu’est-ce que c’est au juste ?Avec Git, ce sont de simples étiquettes que le HEAD fait bouger…
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 40
§ Liste les branches§ locales par défaut (-l)§ distantes (-r)§ toutes (-a)
§ Crée une branche locale§ git branch la-branche [base, HEAD par défaut]
§ Supprime une branche locale§ git branch -d la-branche§ git branch -D la-branche (si non fusionnée)
git branchVous aussi vous êtes dans la branche
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 41
§ Changer de branche (la refléter sur le WD)§ Mais pas que des têtes de branche
§ N’importe quelle révision
§ Mais pas que le WD§ Un ou plusieurs fichiers spécifiques
§ Raccourcis de création de branche§ git checkout -b new_branch
§ Et en cas de WD conflictuel…§ git checkout -m / -p
git checkoutVous aussi vous êtes dans la branche
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 42
git branchVous aussi vous êtes dans la branche
f30ab34ac298ca9
HEAD
master
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 42
git branchVous aussi vous êtes dans la branche
f30ab34ac298ca9
HEAD
master
git branch fastapi
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 43
git checkoutRevoyons la scène au ralenti
f30ab34ac298ca9
HEAD
master
fastapi
git branch fastapi
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 43
git checkoutRevoyons la scène au ralenti
f30ab34ac298ca9
HEAD
master
fastapi
git checkout fastapi
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 44
git commitTu me fais tourner la tête
f30ab34ac298ca9
HEAD
master
fastapi
git checkout fastapi
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 44
git commitTu me fais tourner la tête
f30ab34ac298ca9
HEAD
master
fastapi
git commit -a …
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 45
git checkoutRevenons en arrière un instant
f30ab34ac298ca9
HEAD
master
fastapi
c2b9e
git commit -a …
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 45
git checkoutRevenons en arrière un instant
f30ab34ac298ca9
HEAD
master
fastapi
c2b9e
git checkout master
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 46
git commitLa divergence est née
f30ab34ac298ca9
HEAD
master
fastapi
c2b9e
git checkout master
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 46
git commitLa divergence est née
f30ab34ac298ca9
HEAD
master
fastapi
c2b9e
git commit -a …
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 47
git commitEt voilà deux historiques à réconcilier à terme
f30ab34ac298ca9
HEAD
master
fastapi
c2b9e
git commit -a …
87ab2
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 48
§ Trop facile ! Une branche, c’est juste une étiquettegit branch gros-taf-finalementgit reset --soft HEAD~3git checkout gros-taf-finalement
J’aurais dû faire une branche, en fait…Finalement ça va prendre plus de temps que prévu ce truc…
HEAD~3
HEAD~2
HEAD~1
WDmasterHEAD
masterHEAD~3
HEAD~2
HEAD~1
WDgros-…HEAD
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 49
§ Comme tout le monde§ Ça vient pas mal des vieux VCS (Subversion, etc.)
§ Et pas mal aussi d’un vrai manque de formation
§ Mais en fait, tout est question de méthodologie§ Bien comprendre les étapes§ Bien connaître les (nombreux) outils à disposition§ Commencer par y voir clair§ Résoudre les conflits un par un
Tu as peur de fusionnerSi si, avoue
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 50
§ Un WD « in good order »§ En gros, sans fichier modifié/staged concerné par la fusion
§ De préférence, des commits atomiques (réduit la surface d’impact de chacun)
§ Quand est-on en situation de fast forward ?§ Quelques astuces sur git merge :
§ --squash§ --log / -m§ --ff-only§ -s strategy -X strategy-option (ours, theirs…)
Pour faire une bonne fusion, il faut…Recette officielle de Mamie Nova
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 51
Bien avoir le résultat en têteVersion merge commit
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 52
Bien avoir le résultat en têteVersion fast-forward
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 53
§ Opère une fusion classique§ Si pas fast-forward, crée un commit (à 2 parents)
§ Message assez basique§ git merge -p peut donner un message plus utile§ On peut bien sûr préciser le message (-m …)
§ Nombreux usages avancés possibles§ Pas de commit auto (vérification manuelle avant)§ Squash commits§ Stratégies de fusion, etc.§ Hors du cadre de cette formation, mais git help merge !
git mergeFusions & Acquisitions pour le tout-venant
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 54
§ git status§ Qu’est-ce qui s’est bien passé, et qu’est-ce qui a planté ?
§ Le contenu du fichier§ Les marqueurs >>> / <<< / ||| (mode diff3)
§ git merge / git mergetool§ git log --merge -p fichier
§ Détails des commits non partagés + touchant le fichier planté
§ git show :1:… / :2:… / :3:…§ Affiche la version intégrale d’un fichier planté, dans sa version pré-
divergence, main line ou à fusionner (plus de contexte !)
Quand ça veut pas, ça veut pasMais il suffit de garder la tête froide
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 55
§ Édition manuelle dans l’éditeur§ Moi j’aime bien…§ Parfois la seule solution (lorsqu’on crée un résultat qui n’est pas le
choix de l’un ou l’autre mais un mix spécifique)
§ Assistance par outil§ git mergetool
§ Config merge.tool (jetons un œil à p4merge !), mergetool.*§ Plein de déjà pris en charge, on en trouve pour tous les OS et EDI§ On peut configurer ses outils propres
§ Ne pas oublier le add !
Et quand on a compris, on fait quoi ?Fusionner, fichier par fichier
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 56
§ Le rebase est là pour modifier tout ou partie de l’historique d’une révision (généralement une tête de branche) en la faisant repartir sur une autre base (rebase)
§ Changement de sens : on merge vers soi, mais on rebase une autre
§ Deux grands scenarii :§ Soigner / restructurer l’historique (on verra tout ça plus loin)§ Éviter les merge commits en leur préférant la consolidation des
commits individuels dans une même branche
Merge vs. RebaseRien à voir
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 57
Bien avoir le résultat en têteVersion rebase
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 58
§ git rebase nouvelle-base [branche-concernée]§ Par défaut ça concerne le HEAD
§ Rejoue chaque commit sur la nouvelle base, ce qui revient conceptuellement à les fusionner un par un§ Donc risques de conflit, comme pour une fusion classique§ Auquel cas on s’arrête en cours de route et c’est à vous de jouer
§ Si résolution d’un conflit sur un des commits rebasés :§ git rebase --continue § git rebase --abort§ git rebase --skip
git rebasePartir sur de nouvelles bases
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 59
§ Chaque commit d’origine en produit un nouveau§ Le SHA parent a changé, donc par ricochet, le commit lui-même, et
donc les suivants, etc.
§ Dans la pratique, un peu malin : évite les « doublons », qui produiraient en fait des commits vides§ Quand on rebase une modif A sur une base qui contient déjà, quel
qu’en soit le cheminement, cette même modif A
Merge vs. RebaseOn réécrit quand même l’histoire…
10 octobre 2011 60
Soigner son historique
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 61
§ On s’y prend à plusieurs fois pour finaliser un correctif§ Pour avoir le fix, il faut tout récupérer. Pas de cherry-pick simple :(
§ On a fait des commits fourre-tout§ Le problème inverse : trop de sujets dans un même commit
§ On mélange les sujets, on entrelace des commits sans rapport§ Ça oblige une récupération thématique à procéder par commits
individuels, plutôt qu’avec un intervalle bien défini
§ On a bâclé les messages de commit§ On a fait des branches inutilement tard
§ Alors que leur contenu est indépendant des derniers commits
Les raisons d’un historique pourriTu es coupable et tu le sais
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 62
§ Faciliter la lecture du log§ Plus court, dénué de commits superflus / réciproques / etc.§ Mieux ordonné§ Thèmes mieux regroupés
§ Faciliter la récupération ciblée de commits§ Cherry-picking§ Merge / rebase d’intervalle continu§ Récupération de branche sans dépendance historique superflue
§ Réduction des risques de conflits hors-sujet
§ Passer pour un super-héros§ « Ce type réussit tout du premier coup, et dans l’ordre ! »
Pourquoi soigner son historique ?Parce qu’on aimerait ne pas se faire haïr des collègues, tiens !
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 63
§ Un couteau suisse incroyable !§ Simple comme une édition de fichier, ligne par ligne
§ Virer des commits§ Réordonner des commits§ Fusionner des commits§ Découper des commits
§ Sans doute le moins simple, puisqu’on incruste des commits classiques avant un git rebase --continue
§ Reformuler des messages de commit§ Bref, tout ce qu’on peut souhaiter :-)
Rebase interactif : Léon, nettoyeurTu as fait ça n’importe comment mais ça va pas se voir…
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 64
§ On précise l’ensemble des points concernés :§ La tête à rebaser, la base sur laquelle repartir…§ …mais aussi le premier commit à rebaser (qui par défaut est
l’ancêtre commun)
git rebase --onto master stats client
Découpler des devs orthogonauxLe rebase tri-partite, parce que tu le vaux bien
C1 C2 C3 master
C5 C6 stats C8
C1
client
C2 C3
C5 C6
master
stats
C8’ client’
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 65
§ Les tutos et glossaires Git intégrés§ git help tutorial§ git help workflows§ git help glossary§ git help cli
§ Une tonne de ressources au top§ http://git-scm.com/documentation
§ Git en bref§ http://gitref.org/§ http://git-scm.com/docs/everyday (« Everyday Git »)
§ Re-pratiquer de zéro, différemment§ http://gitimmersion.com/
Quelques ressources en plus…Directement dans ton Git
10 octobre 2011 66
Collaborer à l’aide de dépôts distants
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 67
§ Les vieilles habitudes ont la vie dure : souvent un seul dépôt distant (celui de référence)§ Très vrai en entreprise§ Beaucoup moins dans l’open-source
§ On peut parfaitement en avoir plusieurs, chacun pouvant être en lecture seule (R/O) ou lecture-écriture (R/W), et tous n’ayant pas forcément les mêmes révisions, branches, tags, etc.§ Un par collaborateur majeur, par exemple§ Un par équipe interne§ etc.
Un… ou plusieurs ! dépôts distantsQuand y’en a pour un, y’en a pour dix
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 68
§ remote = dépôt distant§ git remote gère ces définitions pour chaque dépôt local
§ git remote§ git remote add name url
§ ex. git remote add origin [email protected]:tdd/attitude.git§ git remote rename old new
git remoteAssocier le local à un/des distant(s)
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 69
§ user@ == ssh://user@ — git over SSH (port 22)§ Protocole Git R/W sécurisé par SSH. Le plus fréquent en collab’.
§ git:// — protocole Git (port 9418)§ Protocole Git R/O. Le plus fréquent en consultation.
§ http(s):// ou ftp(s):// — la lose internationale (port 80)§ Pour les pauvres hères empêtrés derrière un pare-feu trop dur…
§ filesystem — pratique pour les tests à l’arrache™§ Un simple chemin de fichier suffit !
§ rsync — parce qu’on est des h4xx0rs !§ Le principal protocole de mirroring/synchro distante. Peu employé
dans la réalité vis-à-vis de Git, mais bon…
Protocoles de dépôt distantPas tous égaux (ni en droits, ni en performance, ni en prise en charge)
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 70
Exploiter une branche distanteOn a les mêmes à la maison
$ git remote add origin …$ git fetch originremote: Counting objects: 22, done.remote: Compressing objects: 100% (17/17), done.remote: Total 22 (delta 9), reused 0 (delta 0)Unpacking objects: 100% (22/22), done.From … * [new branch] master -> origin/master * [new branch] foobar -> origin/foobvar$ git branch -a remotes/origin/master remotes/origin/foobar$ git branch -r origin/master origin/foobar$ git branch -t foobar origin/foobar
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 71
Exploiter une branche distanteEncore plus simple sur les Git récents
(master) $ git checkout foobarBranch foobar set up to track remote branch foobar from origin.Switched to a new branch 'foobar'(foobar) $
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 72
§ Récupère en local une copie de toutes les dernières révisions sur les branches trackées (à moins de préciser ce qu’on fetche).
§ N’altère pas les branches locales.§ Plus besoin du réseau après ! git fetch origin master (explicite) git fetch origin (les trackées de origin) git fetch (les trackées du remote par défaut) git fetch --all (les trackées de tous les remotes)
git fetch On met tout dans le sac on triera après
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 73
§ Techniquement, fetch + merge (trackée courante)§ Si on préfère le rebase, on fera un git pull --rebase§ Comme on peut, à la base, dissocier fetch et merge, on
a tendance à s’en servir quand on a peu de temps online devant soi…§ git fetch§ on se déconnecte (ex. on va prendre un train)§ git merge (au calme, offline…)
git pullUn petit raccourci classique
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 74
§ Synchronisation montante ; possible uniquement sur un remote R/W (user@ ou ssh://user@)
§ Automatique sur branches trackées, sinon il faut préciser. On peut restreindre à une seule trackée aussi.git push -u origin fastercsv (1er envoi + tracking)
git push origin (les trackées d’origin)
git push (les trackées de tous les remotes)
§ Pas forcé d’avoir le même nom…git push -u origin master:christophe-master
§ Utilisé pour supprimer des branches distantesgit push origin :branch-to-delete
git pushParce que partager c’est bien
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 75
Pourquoi préférer les pulls en rebase ?Parce qu’une fusion artificielle ça pollue l’historique
$ git pullCurrent branch master is up to date.
$ git pullCurrent branch master is up to date.
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 75
Pourquoi préférer les pulls en rebase ?Parce qu’une fusion artificielle ça pollue l’historique
$ git pullCurrent branch master is up to date.
$ git pullCurrent branch master is up to date.
$ git push… master -> master
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 75
Pourquoi préférer les pulls en rebase ?Parce qu’une fusion artificielle ça pollue l’historique
$ git pullCurrent branch master is up to date.
$ git pullCurrent branch master is up to date.
$ git push… master -> master
$ git pushTo /tmp/test-remote ! [rejected] master -> master (non-fast-forward)…
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 76
Pourquoi préférer les pulls en rebase ?Parce qu’une fusion artificielle ça pollue l’historique
$ git pullMerge made by the 'recursive' strategy.…
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 76
Pourquoi préférer les pulls en rebase ?Parce qu’une fusion artificielle ça pollue l’historique
$ git pullMerge made by the 'recursive' strategy.…
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 76
Pourquoi préférer les pulls en rebase ?Parce qu’une fusion artificielle ça pollue l’historique
$ git pullMerge made by the 'recursive' strategy.…
$ git lg* 1114592 - (HEAD, master) Merge branch 'master' of…|\| * a626f04 - (origin/master) …* | 0fcbc1a - …|/* 4991700 - …
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 76
Pourquoi préférer les pulls en rebase ?Parce qu’une fusion artificielle ça pollue l’historique
$ git pullMerge made by the 'recursive' strategy.…
$ git lg* 1114592 - (HEAD, master) Merge branch 'master' of…|\| * a626f04 - (origin/master) …* | 0fcbc1a - …|/* 4991700 - …TOXIQ
UE
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 77
Pourquoi préférer les pulls en rebase ?Parce qu’une fusion artificielle ça pollue l’historique
$ git pull --rebaseFirst, rewinding head to replay your work on top of it...Applying: …
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 77
Pourquoi préférer les pulls en rebase ?Parce qu’une fusion artificielle ça pollue l’historique
$ git pull --rebaseFirst, rewinding head to replay your work on top of it...Applying: …
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 77
Pourquoi préférer les pulls en rebase ?Parce qu’une fusion artificielle ça pollue l’historique
$ git pull --rebaseFirst, rewinding head to replay your work on top of it...Applying: …
$ git lg* 68bf59e - (HEAD, master) …* a626f04 - (origin/master) …* 4991700 - …
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 77
Pourquoi préférer les pulls en rebase ?Parce qu’une fusion artificielle ça pollue l’historique
$ git pull --rebaseFirst, rewinding head to replay your work on top of it...Applying: …
$ git lg* 68bf59e - (HEAD, master) …* a626f04 - (origin/master) …* 4991700 - …nicke
l
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 78
§ On utilise généralement les tags pour préciser un point événementiel dans un historique, le plus souvent une version précise quand on a une seule branche de production.§ Les tags de version sont généralement au format « vX.Y.Z »
§ Un tag n’est pas censé être bougé avec le temps, pour des raisons de QA / certification / validation principalement.§ En revanche, une branche de version (release/prod) évolue au fil
des bugfixes, hotfixes et security fixes.
§ git tag [-f] nom-du-tag§ git tag -l [pattern]
Les tagsMarquage de versions précises ou annotations événementielles
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 79
§ Il va falloir écraser de l’historique distant§ Attention : ça va gêner ceux qui l’ont déjà récupéré§ Méthodologie :
1. Se replacer, en local, sur un historique valable pour la branche2. Forcer le push avec git push -f3. Si nécessaire, recaler les tags concernés avec git tag -f et les
mettre à jour sur le remote avec git push --tags -f4. Pour les machines qui avaient déjà récupéré l’histo pourri : forcer
le pull avec git pull -f
Quand le dépôt distant est foireux…Quelqu’un a pushé des trucs moisis
10 octobre 2011 80
Cherry-picking etréutilisation de fusions manuelles
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 81
§ Parce qu’on n’est pas obligé de se farcir un historique pour récupérer juste un commit§ Typiquement un bugfix autonome, orthogonal
§ Trivial : git cherry-pick le-commit§ Conceptuellement, un rebase miniature (limité à un commit)
§ Comment sélectionner des commits cibles ?§ git cherry -v§ Dans le même univers :
§ git branch --contains§ git branch --merged / --no-merged
§ Fréquent pour porter un fix local sur l’upstream (ex. d’un fork vers le dépôt d’origine). Si sur Github, préférer une pull request :-)
Cherry pickingParce que diff/apply manuel ça va bien 2 minutes
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 82
§ REuse REcorded REsolution§ Flag global : rerere.enabled§ Enregistre les « empreintes » des résolutions
manuelles de conflits§ Les partage avec les autres via le remote§ Réutilisé automatiquement lors d’une fusion (merge ou
rebase, pas de jaloux)§ Permet notamment des workflows sympathiques de
« control merges » annulables mais profitables
RerereLes vrais amis résolvent leur conflit une bonne fois pour toutes
10 octobre 2011 83
Chasse aux bugs accélérée : le bisecting
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 84
§ Recherche dichotomique entre le dernier point que vous identifiez comme OK et le point KO (généralement le HEAD de master)§ On délimite l’historique à tester, et on y va à coup de « plus petit
plus grand », en quelque sorte§ Ne marche que si le bug n’a pas toujours été là !
§ Dichotomique donc en O(ln(2))…§ C’était il y a 30 commits : 5 tests au pire§ C’était il y a 1000 commits : 10 tests au pire ! \o/
Le principeEt révisons nos logarithmes de 2
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 85
§ git bisect start§ git bisect bad§ git bisect good le-dernier-sha-qui-allait-bien§ (pour chaque checkout auto, on teste, puis git bisect bad/good/skip)
§ git bisect reset
Au plus « lent » : 100% manuelParce qu’on a quand même un peu de temps
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 86
§ git bisect start commit-foireux dernier-bon-commit
§ Embraye directement sur la dichotomie et la boucle de tests interactive
§ En cas d’erreur ou d’interruption, on peut…§ Sauver le log (git bisect log > le-fichier-de-log)§ L’éditer si besoin§ Le rejouer automatiquement avec git bisect replay le-fichier
Pré-limiter depuis la ligne de commandeHistoire de gagner un peu de temps
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 87
§ git bisect run le-script§ N’importe quel fichier scriptable dans l’environnement
§ Shell, Ruby, Python, Node, PHP…§ Le script fait son test et renvoie 0 (good), 125 (skip) ou 1-127 (bad)
§ Et pour réduire encore la liste des candidats§ Limiter à certains fichiers (ne s’occupe que des commits qui les
concernent)
§ Ça peut aller très, très vite§ Sur un SATA classique, j’ai cherché à travers 1000 commits en
moins de 20 secondes !§ Sur un SSD, ça va encore beaucoup, beaucoup plus vite !
Automatiser à fond les ballonsParce qu’hors du scripting, point de salut
10 octobre 2011 88
Submodules vs. subtrees
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 89
§ Submodules§ Facile à mettre en place ;
peu de notions avancées§ Dépôts imbriqués§ Cycles de vie distinct : mise
à jour locale en deux temps§ Récupération de mise à jour
en deux temps§ Donc de nombreux pièges
dans l’emploi quotidien en termes de maintenance
§ Subtrees§ Un peu complexe à mettre
en place (notions avancées)§ Un seul dépôt par codebase
utilisatrice§ Donc, un cycle de vie
unique, mise à jour intégrée§ Récupération de mise à jour
intégré, normale, usuelle§ Maintenance explicite lors
d’un partage de mise à jour locale vers la version centrale, ou inversement
Petit comparatif rapideHistoire de bien cerner le sujet
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 90
§ Récupération initiale du dépôt§ …mais on oublie le git submodule init + git submodule update
§ Mise à jour locale§ …mais on est sur un detached head§ …ou simplement sur un head en retard sur le remote§ …mais on oublie le push du submodule : le dépôt parent s’y perd
§ Récupération de mise à jour§ …mais on oublie le git submodule update
Les pièges usuels des submodulesEt rien que pour ça, on devrait éviter…
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 91
§ En gros, une branche est dédiée au subtree, sans rien de commun avec les branches du projet principal !
§ git remote add remote-subtree git@l-hote:le-depot.git§ git fetch remote-subtree§ git checkout -t -b plugin remote-subtree/master§ git checkout master§ git read-tree --prefix=vendor/plugins/ -u plugin
Mettre en place des subtreesEt se tordre un peu le cerveau sur des concepts de dingues
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 92
§ git checkout plugin§ git pull§ git checkout master§ git merge --squash -s subtree --no-commit plugin
§ Sans créer pour autant, donc, un commit dédié au merge (et notamment, ne touche pas au HEAD ni au MERGE_HEAD)
Récupérer des mises à jour distantesMais explicitement, sans surprise
Formation Git Total • Delicious Insights, Paris Geneanet • 24–25 octobre 2013Christophe Porteneuve 93
§ Ben, l’inverse :§ git checkout plugin§ git merge -s subtree master§ git push
§ Et si on veut visualiser les différences ?§ (master) git diff-tree -p plugin§ (plugin) git diff-tree -p master§ (plugin/master) git diff-tree -p remote-subtree/master
Partager des upgrades d’un subtree localDéjà, parce que c’est possible
10 octobre 2011 94
Une dernière question…
10 octobre 2011 95
I DON’T ALWAYS ATTENDTRAINING SESSIONS
BUT WHEN I DO, I DO ITWITH ATTITUDE!