P22 - Qualité de développement

2 - Git branches & remotes

Adrien Krähenbühl IUT Robert Schuman

Résumé du 1er épisode

Retour sur HEAD et checkout

Git utilise un pointeur nommé HEAD pour indiquer où il se trouve dans le graphe des commits.

git checkout<commit-id>
  • Déplace le pointeur HEAD sur un commit donné en argument.
  • Met le répertoire de travail dans l’état du commit d’identifiant unique <commit-id> (calculé par la fonction de hachage SHA-1)

1. Départ

2. git commit -m "..."

3. git checkout 6d865ec

Les commandes du jour

Rappel : la doc est ici \(\rightarrow\) https://git-scm.com/docs

  • git branch : Crée, liste ou supprime des branches.
  • git switch : Permet de changer de branche.
  • git merge : Fusionne deux histoires (arbres de commits).
  • git clone : Clone un dépôt dans un nouveau répertoire.
  • git remote : Gérer les dépôts distants.
  • git push : Met à jour un dépôt distant avec les commits locaux.
  • git fetch : Télécharge les commits depuis un dépôt distant.
  • git pull = git fetch + git merge
  • git diff : Montre les différences entre commits et/ou fichiers.


Nous verrons également (en TP) le fichier .gitignore et l’outil meld.

Les branches

Git branch & switch

Une branche est simplement un commit nommé.

git branch[-d] <name>
  • Crée une branche <name> au niveau du commit pointé par HEAD.
  • L’option -d (delete) supprime la branche.
git switch<name>
  • Déplacer le pointeur HEAD vers la branche <name>.
  • switch est aux branches ce que checkout est aux commits

1. Départ.

2. git branch myBranch

3. git switch myBranch

4. git checkout 6d865ec

5. git branch otherBranch

6. git switch otherBranch

7. git switch myBranch

8. git branch -d otherBranch

Des histoires qui divergent

1. Départ.

2. Céation d’un nouveau fichier OtherClasse.java.

3. git add OtherClasse.java.

4. git commit -m "Ajout de la classe OtherClasse.java"

4. git commit -m "Ajout de la classe OtherClasse.java"

5. Modification du fichier OtherClasse.java.

6. git add OtherClasse.java.

7. git commit -m "Modification du fichier OtherClasse.java"

7. git commit -m "Modification du fichier OtherClasse.java"

À quoi servent les branches ?

Les branches permettent de travailler en parallèle
à partir d’une base de code commune.

Il est courant d’avoir une branche principale (main ou master) qui doit toujours contenir du code fonctionnel.

Les branches secondaires sont classiquement utilisées pour :

  • Développer une nouvelle fonctionalité
  • Corriger une erreur
  • Gérer des versions release, beta, alpha, etc; de son application

Règle essentielle d’un bon développement :
Ne jamais commiter directement sur la branche principale.

Git merge

git merge<branche>
Fusionne l’histoire de la <branche> avec le la branche pointée par HEAD.

1. Reprenons…

2. git switch myBranch

3. git merge otherBranch

3. git merge otherBranch

4. git branch -d otherBranch

Le “commit de fusion”

  • git merge crée un commit de fusion.
  • Un commit de fusion a deux parents, les deux commits pointés par les deux branches fusionnées.

Créer un “commit de fusion” est le comportement par défaut de Git mais il existe d’autres stratégies… que nous ne verrons pas.

Les conflits de fusion

Origine des conflits

La fusion peut échouer s’il y a un ou plusieurs fichiers en conflit.

$ git merge otherBranch
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.

Message d’erreur lors d’un conflit sur le fichier README.md

Un fichier est en conflit si :

  • les mêmes lignes ont été modifiées sur les deux branches
  • s’il a été modifié sur une branche et supprimé sur l’autre

depuis que les branches ont divergé.

Scénario de conflit

1. Départ.

Fichier README.md

P21 - P22

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

2. git branch otherBranch

README.md sur…

P21 - P22

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

myBranch

P21 - P22

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

otherbranch

3. git switch otherBranch

README.md sur…

P21 - P22

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

myBranch

P21 - P22

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

otherbranch

4. Modification de README.md

README.md sur…

P21 - P22

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

myBranch

P21 - Développement

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

otherbranch

5. git add README.md

README.md sur…

P21 - P22

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

myBranch

P21 - Développement

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

otherbranch

6. git commit -m "Titre P21 pour de README.md"

README.md sur…

P21 - P22

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

myBranch

P21 - Développement

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

otherbranch

7. git switch myBranch

README.md sur…

P21 - P22

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

myBranch

P21 - Développement

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

otherbranch

8. Modification de README.md

README.md sur…

P22 - Conception

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

myBranch

P21 - Développement

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

otherbranch

9. git add README.md

README.md sur…

P22 - Conception

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

myBranch

P21 - Développement

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

otherbranch

10. git commit -m "Titre P22 pour de README.md"

README.md sur…

P22 - Conception

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

myBranch

P21 - Développement

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

otherbranch

11. git merge otherBranch ?

README.md sur…

P22 - Conception

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

myBranch

P21 - Développement

- Raymond Schneider
- Adrien Krähenbühl
- Sanae Boutarfass
- Salwa Kobeissi

otherbranch

Résoudre un conflit

Git propose dans le répertoire de travail une version temporaire du fichier en conflit contrenant les deux versions :

<<<<<<< HEAD
P22 - Conception
=======
P21 - Développement
>>>>>>> otherBranch

...

à changer en

P22 - Conception

...

ou

P21 - Développement

...

C’est au développeur de régler le conflit.

Pour terminer la fusion, il doit :

  1. Éditer le fichier pour résoudre les zones de conflit
  2. Commiter les fichiers avec git add + git commit

Il peut sinon annuler la fusion avec git merge--abort.

Travailler avec plusieurs dépôts

Git clone

git clone<dépot> [<répertoire>]
  • Crée une copie (un clône) du <dépôt> dans le répertoire courant ou dans <répertoire> s’il est indiqué.
  • <dépôt> peut être l’URL d’un dépôt Git accessible via le réseau.

Un répertoire Base/ versionné avec Git :

$ ls -a Base/
.git  README.md

peut être cloné dans un autre répertoire Clone :

$ git clone Base Clone
Cloning into 'Clone'...
done.
$ git clone git@git.unistra.fr:p21.git Clone
Cloning into 'Clone'...
done.

qui sera une copie exacte de Base :

$ ls -a Clone/
.git  README.md

Git remote

Un dépôt distant (ou remote) est un dépôt suivi par le dépôt local.

git remote[-v]
Liste les dépôts distants suivis.
git remoteadd <nom> <dépôt>
Ajoute le dépôt distant <dépôt> en l’appelant <nom>.
$ git remote -v
origin  /home/.../Base/ (fetch)
origin  /home/.../Base/ (push)
$ git remote -v
origin  git@git.unistra.fr:p21.git (fetch)
origin  git@git.unistra.fr:p21.git (push)
  • L’utilisation de dépôts distants permet (entre autres) de travailler à plusieurs en laissant git gérer les fusions.
  • Un dépôt distant peut se trouver sur le même ordinateur, le mot “distant” s’oppose simplement au mot “local” du dépôt courant.

Scénario de clonage


1. Soit un dépôt distant


2. git clone git@git.unistra.fr:p21.git Base


2. git clone git@git.unistra.fr:p21.git Base


3. git commit -m "Travail en local"

Git push

git push<remote> <branch>
Synchronise (pousse) les modifications de la branche pointée par HEAD vers la <branch> du dépôt <remote>.
$ git push origin main
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 270 bytes | 270.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@git.unistra.fr:p21.git
    9e13dfb..e92d6f0  main -> main


Pousser des modifications locales vers un dépôt distant implique :

  1. de fusionner les changements locaux sur le dépôt distant,
  2. si la fusion réussie, de synchroniser localement la fusion.

Git fetch, merge et push

$ git pull origin main
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), 254 bytes | 254.00 KiB/s, done.
From git@git.unistra.fr:p21.git
* branch          main     -> FETCH_HEAD
ae9a8b2..a399689  main     -> origin/main
Updating ae9a8b2..a399689
Fast-forward
README.md | 1 +
1 file changed, 1 insertion(+)
git fetch[[<remote>] <branch>]
Ramène les modifications de la <branche> du dépôt <remote> vers le dépôt local. Attention, il n’y a pas de fusion locale.
git merge
Fusionne les modifications déjà “fetchées” avec la branche courante.

git pull = git fetch + git merge

Scénario de pull


1. Reprenons…


2a. Le dépôt distant évolue.


3a. git fetch origin main


4a. git merge origin main


2b. Le dépôt distant évolue.


3b. git pull origin main

Bonnes pratiques

  • Toujours puller avant de de pusher pour éviter les conflits et les reésoudre localement.
  • Toujours travailler sur une branche secondaire lorsqu’on travaille à plusieurs sur un même dépôt distant.
  • Committer régulièrement
  • Écrire des messages de commit explicites.