Utilisation avancée des outils de rebase
Définition : Rebaser (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
Remarque : Rebaser (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
Fondamental : Le rebase interactif
L'outil le plus complet pour effectuer des rebase locaux, c'est le rebase interactif, il s'appelle avec la commande
git rebase -i portee_de_rebase
Attention : Commande 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éthode : Dé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
Remarque : Quelques é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
Attention : Porté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.
Exemple : Rebasing 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
git init exemple_rebase
cd exemple_rebase/
touch readme.txt
git add readme.txt
git commit -m "ajout readme.txt"
touch a.txt
git add a.txt
git commit -m "ajout a.txt"
touch b.txt
git add b.txt
git commit -m "ajout b.txt"
echo "fonctionnalité supplémentaire" >> a.txt
git commit -am "ajout fonctionnalité A dans a.txt"
git rebase -i HEAD^^^
Le git rebase présente la liste suivante
pick 36a63c9 ajout a.txt
pick 85888e6 ajout b.txt
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
pick 36a63c9 ajout a.txt
pick 5f69fea ajout fonctionnalité A dans a.txt
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
pick 36a63c9 ajout a.txt
squash 5f69fea ajout fonctionnalité A dans a.txt
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
Attention : Commande toujours aussi dangereuse !
Si en manipulant la liste, vous oubliez de remettre un commit, il sera perdu définitivement (ou presque)