Git

dVCS != VCS

  • dépôt local != dépôt distant
  • upstream / origin
  • local = sans connexion internet : add, commit, historique...
  • brancher facilement
  • remiser (stash) ou "mettre sur étagère" (shelf) facilement
  • ré-écriture facile de l'historique

git != svn

  • git checkout != svn checkout
  • git add ~= svn add
  • git commit != svn commit
  • git push ~~= svn commit
  • git fetch ~~= svn update
  • git pull ~~= svn update
  • git merge ~= svn merge
  • git rebase n'existe pas en SVN
  • git reset n'existe pas en SVN
  • git revert !!!= svn revert
  • git cherry-pick n'existe pas en SVN (émulation avec merge)
  • git log ~= svn log
  • git diff ~~= svn diff

git workflow != svn workflow

GUI vs SHELL

L'interface graphique,
Say le mal,

mais Shell le bien !

Bash ou Zsh ?

(Pfff, quelle question !)

  • La terminologie (Console, Terminal, Shell, CLI)

  • La complétion

  • Le prompt

Les entrailles de git

  • VCS ?
  • dVCS ?
  • BDD ?
  • Où les données sont-elles stockées ?
  • Quelles données ?

Les entrailles de git

Terminologie :

  • blob, tree, commit, tag
  • ref
  • commit message
  • hash (SHA-1)
  • répertoire de travail (working directory/tree)
  • index (staging area)

Les objets stockés dans .git

$ git init test
Initialized empty Git repository in /tmp/test/.git/
$ cd test
$ find .git/objects
.git/objects
.git/objects/info
.git/objects/pack
$ echo 'Hello git!' | git hash-object --stdin
7a860024518c83a85d6e0292e3c3d749b509173e
$ echo 'Hello git!' | git hash-object -w --stdin
7a860024518c83a85d6e0292e3c3d749b509173e
$ git cat-file -t 7a860024518c83a85d6e0292e3c3d749b509173e
blob

$ git cat-file -s 7a860024518c83a85d6e0292e3c3d749b509173e
11

$ git cat-file -p 7a860024518c83a85d6e0292e3c3d749b509173e
Hello git!

Les objets stockés dans .git

$ ls .git/objects/*
.git/objects/7a:
860024518c83a85d6e0292e3c3d749b509173e

.git/objects/info:

.git/objects/pack:

Les objets stockés dans .git

$ git cat-file -p 796c1
tree cbe0780272b6cf0e141079b7e245f3eabac29a06
author Stanislas Ormières <stanislas.ormieres@smartfocus.com> 1436364788 +0200
committer Stanislas Ormières <stanislas.ormieres@smartfocus.com> 1436364788 +0200

First Commit

$ git cat-file -p cbe07
100644 blob 557db03de997c86a4a028e1ebd3a1ceb225be238	README.md
040000 tree db78f3594ec0683f5d857ef731df0d860f14f2b2	new_dir

$ git cat-file -p 557db
Hello World

$ git cat-file -p db78f
100644 blob 557db03de997c86a4a028e1ebd3a1ceb225be238	README.md

$ tree
.
├── new_dir
│   └── README.md
└── README.md

Cycle typique

modification -> add -> commit -> checkout (merge, rebase…)

Terminologie

  • Repository = database of the objects
  • Modified (état du répertoire de travail courant)
  • Staged (état du prochain commit)

Les 3 états du dépôt

  • Clean (état du commit courant)
  • Modified (état du répertoire de travail courant)
  • Staged (état du prochain commit)

Clean

Modified

Staged

Modification

Staging (add)

Commit

Clean

Modified

Staged

Modification

Staging (add)

Commit

reset/co

&& add

Unstaging (reset)

checkout

Terminologie et concepts

Terminologie

Branch

 

Une "branche" dans Git :

  • Conceptuellement : un pointeur mouvant vers la tête d'une ligne de développement, une branche master par défaut existe toujours.
  • Physiquement : un fichier de 41 caractères

Conséquences :

  • très peu couteux d'en créer, d'en effacer, de modifier le nom...
  • très facile à merger

Terminologie

heads, HEAD

 

  • chaque branche dans Git a une tête (head), qui est le pointeur vers le dernier commit de sa ligne de développement ;

 

  • HEAD est le pointeur vers le commit récupéré (checkout) de la branche courante : il n'y a qu'un HEAD par dépôt git ;

 

  • lorsque la HEAD ne pointe pas vers une tête de branche (head), on dit qu'on est sur une tête détachée (detached HEAD).

Commit often, push... less often

  1. tous les commits sont dans la base de données de git
  2. on peut récupérer n'importe quel commit (cf plus loin)...
  3. ...même s'ils sont orphelins (cf plus loin)... (en tout cas s'ils n'ont pas été pris par le ramasse-miettes  - GC)
  4. tous les commits peuvent être remaniés et réordonnés (ré-écriture de l'historique)
  1. un commit a toujours au moins un parent (sauf le premier commit  - root commit) identifié par un hash SHA-1
  2. une ré-écriture d'historique implique un changement du hash du ou des derniers commits
  3. si un changement de hash intervient avant le dernier commit publié, les clones du dépôt ne pourront retrouver le commit parent de leurs commits à eux
  • ce qui a été publié (git push sur une branche publique) ne doit pas voir son historique ré-écrit (sauf si une seule personne travaille dessus)...
  • ...car tous ceux qui travaillent sur un clone du même dépôt qui a cette branche ne pourront plus synchroniser cette branche avec le dépôt distant

Commit often, push... less often

  • git commit --amend
  • git rebase -i <SHA-1>
  • git commit --fixup/squash <old SHA-1> && git rebase -i --autosquash <older SHA-1>
  • git reset <old SHA-1> && git cherry-pick <SHA-1> / git commit

Pourquoi et comment

récrire l'historique

  • merge
  • rebase
  • fast-forward

Stratégies de gestion de branches

Merge

Rebase

Stratégies de gestion de branches

Stratégies de gestion de branches

Merge

Stratégies de gestion de branches

Rebase après fusion

Stratégies de gestion de branches

Fusion après fusion

  • Difficile de s'y retrouver
  • Difficile de retrouver l'apparition d'un bug

Fusion en avance rapide (fast forward merge)

  • Perte d'information des branches
  • Quel commit concerne quelle feature ou bugfix ?

Fusion en avance rapide + écrasement
(squash + fast forward merge)

  • Perte d'information des commits
  • Difficile de retrouver l'apparition d'un bug
  • voir le graph --graph
  • voir les branches --decorate=short|full
  • les commits en une ligne --oneline
  • chercher dans les les lignes modifiées commits -S 
  • voir les patch -p
  • ne pas afficher les différences concernant les espaces blancs -w
  • aller plus loin : --word-diff=<regex>

Options de log

Les dépôts distants

Terminologie

  • upstream, origin, remote, refspec
  • les différents types de branches
  • tag simple

  • tag annoté

Travailler avec les dépôts distants

  • Réviser merge et rebase et s'en servir avec les branches distantes
  • savoir utiliser plusieurs dépôts distants
  • merge/pull request
  • les différents flow connus (au moins git flow et github flow)

Travail de précision

  • ajouter des hunks à l'index
  • editer des hunks
  • rebaser
  • autosquash (déjà-vu)
  • reset
  • reflog
  • savoir récupérer n'importe quel commit