-
1. Démarrage rapide
-
2. Les bases de Git
-
3. Les branches avec Git
-
4. Git sur le serveur
- 4.1 Protocoles
- 4.2 Installation de Git sur un serveur
- 4.3 Génération des clés publiques SSH
- 4.4 Mise en place du serveur
- 4.5 Démon (Daemon) Git
- 4.6 HTTP intelligent
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Git hébergé
- 4.10 Résumé
-
5. Git distribué
-
6. GitHub
-
7. Utilitaires Git
- 7.1 Sélection des versions
- 7.2 Indexation interactive
- 7.3 Remisage et nettoyage
- 7.4 Signer votre travail
- 7.5 Recherche
- 7.6 Réécrire l’historique
- 7.7 Reset démystifié
- 7.8 Fusion avancée
- 7.9 Rerere
- 7.10 Déboguer avec Git
- 7.11 Sous-modules
- 7.12 Empaquetage (bundling)
- 7.13 Replace
- 7.14 Stockage des identifiants
- 7.15 Résumé
-
8. Personnalisation de Git
- 8.1 Configuration de Git
- 8.2 Attributs Git
- 8.3 Crochets Git
- 8.4 Exemple de politique gérée par Git
- 8.5 Résumé
-
9. Git et les autres systèmes
- 9.1 Git comme client
- 9.2 Migration vers Git
- 9.3 Résumé
-
10. Les tripes de Git
- 10.1 Plomberie et porcelaine
- 10.2 Les objets de Git
- 10.3 Références Git
- 10.4 Fichiers groupés
- 10.5 La refspec
- 10.6 Les protocoles de transfert
- 10.7 Maintenance et récupération de données
- 10.8 Les variables d’environnement
- 10.9 Résumé
-
A1. Annexe A: Git dans d’autres environnements
- A1.1 Interfaces graphiques
- A1.2 Git dans Visual Studio
- A1.3 Git dans Visual Studio Code
- A1.4 Git dans IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Git dans Sublime Text
- A1.6 Git dans Bash
- A1.7 Git dans Zsh
- A1.8 Git dans PowerShell
- A1.9 Résumé
-
A2. Annexe B: Embarquer Git dans vos applications
- A2.1 Git en ligne de commande
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Commandes Git
- A3.1 Installation et configuration
- A3.2 Obtention et création des projets
- A3.3 Capture d’instantané basique
- A3.4 Création de branches et fusion
- A3.5 Partage et mise à jour de projets
- A3.6 Inspection et comparaison
- A3.7 Débogage
- A3.8 Patchs
- A3.9 Courriel
- A3.10 Systèmes externes
- A3.11 Administration
- A3.12 Commandes de plomberie
7.9 Utilitaires Git - Rerere
Rerere
La fonctionalité git rerere
est une fonction un peu cachée.
Le nom vient de l’anglais reuse recorded resolution (« ré utiliser les ré solutions en re gistrées ») et comme son nom l’indique, cela permet de demander à Git de se souvenir comment vous avez résolu un conflit sur une section de diff de manière que la prochaine fois qu’il rencontre le même conflit, il le résolve automatiquement pour vous.
Il existe pas mal de scénarios pour lesquels cette fonctionalité peut se montrer efficace.
Un exemple mentionné dans la documentation cite le cas d’une branche au long cours qui finira par fusionner proprement mais ne souhaite pas montrer des fusions intermédiaires.
Avec rerere
activé, vous pouvez fusionner de temps en temps, résoudre les conflits, puis sauvegarder la fusion.
Si vous faites ceci en continu, alors la dernière fusion devrait être assez facile parce que rerere
peut quasiment tout faire automatiquement pour vous.
La même tactique peut être utilisée si vous souhaitez rebaser plusieurs fois une branche tout en ne souhaitant pas avoir à gérer les mêmes conflits de rebasage à chaque fois. Ou si vous voulez prendre la branche que vous avez fusionnée et si vous avez eu à corriger des conflits, puis décidez de la rebaser pour finir - vous souhaitez sûrement ne pas avoir à recorriger les mêmes conflits.
Une autre situation similaire apparaît quand vous fusionnez ensemble de temps en temps une série de branches thématiques évolutives dans un sommet testable, comme le projet Git lui-même le fait souvent. Si les tests échouent, vous pouvez rembobiner vos fusions et les rejouer en écartant la branche qui a provoqué l’erreur sans devoir résoudre à nouveau tous les conflits.
Pour activer la fonctionnalité rerere
, vous devez simplement lancer le paramétrage :
$ git config --global rerere.enabled true
Vous pouvez aussi l’activer en créant le répertoire .git/rr-cache
dans un dépôt spécifique, mais l’activation par ligne de commande reste plus claire et permet d’activer la fonction globalement.
Voyons maintenant un exemple similaire au précédent. Supposons que nous avons un fichier qui contient ceci :
#! /usr/bin/env ruby
def hello
puts 'hello world'
end
Dans une branche, nous changeons « hello » en « hola », puis dans une autre branche nous changeons « world » en « mundo », comme précédemment.
Quand nous fusionnons les deux branches ensemble, nous obtenons un conflit de fusion :
$ git merge i18n-world
Fusion automatique de hello.rb
CONFLIT (contenu): Conflit de fusion dans hello.rb
Recorded preimage for 'hello.rb'
La fusion automatique a échoué ; réglez les conflits et validez le résultat.
Vous devriez avoir noté la présence d’un nouvelle ligne Recorded preimage for FILE
(« Enregistrement de la pré-image pour FICHIER »).
À part ce détail, cela ressemble à un conflit de fusion tout à fait normal.
À ce stade, rerere
peut déjà nous dire un certain nombre de choses.
Normalement, vous lanceriez un git status
pour voir l’état actuel des conflits.
$ git status
# On branch master
# Unmerged paths:
# (use "git reset HEAD <file>..." to unstage)
# (use "git add <file>..." to mark resolution)
#
# both modified: hello.rb
#
Cependant, git rerere
vous indiquera aussi les conflits pour lesquels il a enregistré la pré-image grâce à git rerere status
:
$ git rerere status
hello.rb
Et git rerere diff
montrera l’état actuel de la résolution ‑ quel était le conflit de départ et comment vous l’avez résolu.
$ git rerere diff
--- a/hello.rb
+++ b/hello.rb
@@ -1,11 +1,11 @@
#! /usr/bin/env ruby
def hello
-<<<<<<<
- puts 'hello mundo'
-=======
+<<<<<<< HEAD
puts 'hola world'
->>>>>>>
+=======
+ puts 'hello mundo'
+>>>>>>> i18n-world
end
En complément (et bien que ça n’ait pas vraiment à voir avec rerere
), vous pouvez utiliser ls-files -u
pour voir les fichiers en conflit ainsi que les versions précédentes, à droite et à gauche :
$ git ls-files -u
100644 39804c942a9c1f2c03dc7c5ebcd7f3e3a6b97519 1 hello.rb
100644 a440db6e8d1fd76ad438a49025a9ad9ce746f581 2 hello.rb
100644 54336ba847c3758ab604876419607e9443848474 3 hello.rb
Maintenant, vous pouvez le résoudre pour que la ligne de code soit simplement puts 'hola mundo'
et vous pouvez relancer la commande rerere diff
pour visualiser ce que rerere va mémoriser :
$ git rerere diff
--- a/hello.rb
+++ b/hello.rb
@@ -1,11 +1,7 @@
#! /usr/bin/env ruby
def hello
-<<<<<<<
- puts 'hello mundo'
-=======
- puts 'hola world'
->>>>>>>
+ puts 'hola mundo'
end
Cela indique simplement que quand Git voit un conflit de section dans un fichier hello.rb
qui contient « hello mundo » d’un côté et « hola world » de l’autre, il doit résoudre ce conflit en « hola mundo ».
Maintenant, nous pouvons le marquer comme résolu et le valider :
$ git add hello.rb
$ git commit
Recorded resolution for 'hello.rb'.
[master 68e16e5] Merge branch 'i18n'
Vous pouvez voir qu’il a « enregistré la résolution pour FICHIER » (Recorded resolution for FILE).
Maintenant, défaisons la fusion et rebasons plutôt la branche sur la branche master.
Nous pouvons déplacer notre branche en arrière en utilisant reset
comme vu dans Reset démystifié.
$ git reset --hard HEAD^
HEAD is now at ad63f15 i18n the hello
Notre fusion est défaite. Rebasons notre branche thématique.
$ git checkout i18n-world
Basculement sur la branche 'i18n-world'
$ git rebase master
Premièrement, rembobinons head pour rejouer votre travail par-dessus...
Application : i18n world
Utilisation de l'information de l'index pour reconstruire un arbre de base...
M hello.rb
Retour à un patch de la base et fusion à 3 points...
Fusion automatique de hello.rb
CONFLIT (contenu) : Conflit de fusion dans hello.rb
Resolved 'hello.rb' using previous resolution.
Échec d'intégration des modifications.
Le patch a échoué à 0001 i18n world
Ici, nous avons obtenu le conflit de fusion auquel nous nous attendions, mais des lignes supplémentaires sont apparues, en particulier Resolved FILE using previous resolution
(FICHIER résolu en utilisant une résolution précédente).
Si nous inspectons le fichier hello.rb
, il ne contient pas de marqueur de conflit.
$ cat hello.rb
#! /usr/bin/env ruby
def hello
puts 'hola mundo'
end
git diff
nous montrera comment le conflit a été re-résolu automatiquement :
$ git diff
diff --cc hello.rb
index a440db6,54336ba..0000000
--- a/hello.rb
+++ b/hello.rb
@@@ -1,7 -1,7 +1,7 @@@
#! /usr/bin/env ruby
def hello
- puts 'hola world'
- puts 'hello mundo'
++ puts 'hola mundo'
end
Vous pouvez aussi recréer l’état de conflit du fichier avec la commande checkout
:
$ git checkout --conflict=merge hello.rb
$ cat hello.rb
#! /usr/bin/env ruby
def hello
<<<<<<< ours
puts 'hola world'
======
puts 'hello mundo'
>>>>>>> theirs
end
Nous avons vu un exemple de ceci dans Fusion avancée.
Pour le moment, re-résolvons-le en relançant rerere
:
$ git rerere
Resolved 'hello.rb' using previous resolution.
$ cat hello.rb
#! /usr/bin/env ruby
def hello
puts 'hola mundo'
end
Nous avons re-résolu le conflit du fichier automatiquement en utilisant la résolution mémorisée par rerere
.
Vous pouvez le valider avec add
et terminer de rebaser.
$ git add hello.rb
$ git rebase --continue
Application: i18n one word
Dans les cas où vous souhaitez réaliser de nombreuses fusions successives d’une branche thématique ou si vous souhaitez la synchroniser souvent avec master
sans devoir gérer des tas de conflits de fusion, ou encore si vous rebasez souvent, vous pouvez activer rerere
qui vous simplifiera la vie.