Utilisation avancée des outils de rebase

DéfinitionRebaser (cas général)

Rabaser, c'est modifier son historique local et ses étiquettes, cela consiste notamment à :

  • Changer l'ordre des commits

  • Fusionner, déplacer, supprimer des commits

  • Déplacer les étiquettes

Cela sert à

  • Rattraper son retard avant de push tout en maintenant un historique plus propre qu'avec un merge en évitant un commit de fusion

  • Organiser et structurer son historique local pour le rendre plus intelligible avant un éventuel push

RemarqueRebaser (cas simple)

Rebaser pour rattraper son retard, c'est (dit de deux manières différentes) :

  • C'est placer l'ensemble de nos modifications locales APRES les modifications les plus récentes.

  • C'est prendre notre premier commit après divergence et en faire le fils du dernier commit sur la branche que l'on suit

FondamentalLe rebase interactif

L'outil le plus complet pour effectuer des rebase locaux, c'est le rebase interactif, il s'appelle avec la commande

1
git rebase -i portee_de_rebase

AttentionCommande dangereuse

Rabaser, c'est modifier son historique et donc potentiellement :

  • Perdre une partie des données

  • Créer des divergences avec le ou les dépôts distants

MéthodeDélimiter le commit de départ

Pour rebaser un historique, il est important de délimiter l'ensemble des commits que l'on souhaite rebaser. Pour cela, plusieurs manière de faire :

  • On peut utiliser le SHA du premier commit à partir duquel on peut rebaser

  • On peut désigner par rapport à HEAD la position du commit en utilisant HEAD~n, le commit un distance de n de HEAD

RemarqueQuelques éléments de syntaxe sur les étiquettes

  • etiquette^ signifie le parent du commit étiquette

  • etiquette^^ signifie le parent du parent du commit étiquette

  • étiquette~n désigne le commit précédant étiquette de n commits

  • etiquette1..etiquette2 désigne tous les commits entre etiquette1 et étiquette2

AttentionPortée du rebase

Le rebase commencera au commit immédiatement APRÈS le commit que vous sélectionnez avec la commande rebase.

Déroulement d'un rebase intéractif

Rebase va couper l'arborescence après le commit sélectionné, et c'est à vous de décider dans quel ordre commiter.

ExempleRebasing d'un code simple

Le code suivant propose de créer 4 commits :

  • Un commit initial (auquel il est déconseillé de toucher)

  • Deux commits liés au fichier a.txt

  • Un commit lié au fichier b.txt qui sépare les deux commits

1
 git init exemple_rebase
2
 cd exemple_rebase/
3
 touch readme.txt
4
 git add readme.txt
5
 git commit -m "ajout readme.txt"
6
 touch a.txt
7
 git add a.txt
8
 git commit -m "ajout a.txt"
9
 touch b.txt
10
 git add b.txt
11
 git commit -m "ajout b.txt"
12
 echo "fonctionnalité supplémentaire" >> a.txt
13
 git commit -am "ajout fonctionnalité A dans a.txt"
14
 git rebase -i HEAD^^^

Le git rebase présente la liste suivante

1
 pick 36a63c9 ajout a.txt
2
 pick 85888e6 ajout b.txt
3
 pick 5f69fea ajout fonctionnalité A dans a.txt

Si l'on souhaite regrouper les commits liés au fichier a, on peut modifier l'ordre des lignes et donc l'ordre dans lequel on va commiter

1
 pick 36a63c9 ajout a.txt
2
 pick 5f69fea ajout fonctionnalité A dans a.txt
3
 pick 85888e6 ajout b.txt

Mais on peut également considérer que les modifications sur a.txt sont une seule et même modification. Pour cela au lieu de rajouter notre commit en utilisant pick, on va le fusionner au précédent en utilisant squash

1
 pick 36a63c9 ajout a.txt
2
 squash 5f69fea ajout fonctionnalité A dans a.txt
3
 pick 85888e6 ajout b.txt

Opération pouvant être accomplies sur un commit

  • Pick : placer le commit à la suite du précédent

  • Reword : placer le commit à la suite du précédent mais ouvrir un éditeur pour modifier son message de commit

  • Edit : interrompt le rebase avant de commiter et c'est à l'utilisateur de le commiter lui-même

  • Squash : fusionne le commit avec le commit précédent

  • Fixup : comme squash mais le commit du message est effacé

  • plein d'autres fonctionnalités : drop, label, reset, merge

AttentionCommande toujours aussi dangereuse !

Si en manipulant la liste, vous oubliez de remettre un commit, il sera perdu définitivement (ou presque)