La commande git rebase
permet de réécrire l’histoire des
commits, par exemple pour la rendre plus lisible.
Pour éviter les soucis de compatibilité on évite de réécrire une histoire publique. On ne fait des rebase que sur des branches qui ne sont pas liées aux autres.
Classiquement quand on merge une branche test dans master on a un historique de commit comme dans la figure suivante
Si cette situation se reproduit de nombreuses fois sur de nombreuses branches le graphe des commits devient vite illisible. Pour faciliter la vision de l’historique du projet on peut modifier cet arbre.
Pour réussir facilement cette tâche, il suffit se positionner sur la branche test et on va faire comme si on avait commencé à développer test à partir de la dernière version de master
switch test
git git rebase master
A l’issue de cette opération, test est une succession de changements initiés depuis la dernière version de master. En fussionnant master et test, on va juste faire avancer master de quelques commits on n’aura as de commit de merge.
switch master
git git merge test
Le rebase permet de réécrire toute l’histoire des commits. Si l’on souhaite modifier les 5 derniers commits. Par exemple dans la branche rebase voici l’historique des 5 derniers commits.
@RMATHMPE20:~/git/finistR2022$ git log -n 5 --oneline
metienne-> rebase) Add git8 rebase merge illustration
423f7a1 (HEAD
3ebd174 Add git8 rebase illustration
a535bf1 Add git8 merge bifucation illustration
d3ae968 git rebase fast forward/master, master) Add build directory to .gitignore 2a0b55e (origin
Il m’a fallu 3 commits pour ajouter les images, je n’ai pas envie de garder cet historique inutile, je voudrais un seul commit qui inclut toutes les images. je peux utiliser rebase pour faire ceci. La commande suivante, demande rentrer dans un mode de rebase automatique à partir pour les 5 derniers commits.
--interactive HEAD~5 git rebase
On a alors accès aux derniers commits ouvert dans un éditeur de texte (attention ils sont dans l’ordre inverse, le plus récent en bas). Pour réécrire l’histoire il suffit de modifier le mot clé pick par une des propositions ci dessous.
pick 2a0b55e Add build directory to .gitignore
pick d3ae968 git rebase fast forward
pick a535bf1 Add git8 merge bifucation illustration
pick 3ebd174 Add git8 rebase illustration
pick 423f7a1 Add git8 rebase merge illustration
# Rebase cefde40..423f7a1 onto 3ebd174 (5 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
31 lines ]
[ Read ^G Get Help ^O Write Out ^W Where Is ^K Cut Text ^J Justify ^C Cur Pos
^X Exit ^R Read File ^\ Replace ^U Paste Text^T To Spell ^_ Go To Line
Pour ne faire qu’un seul commit de mes 3 ajouts de fichier, je vais
utiliser squash
pick 2a0b55e Add build directory to .gitignore
pick d3ae968 git rebase fast forward
pick a535bf1 Add git8 merge bifucation illustration
s 3ebd174 Add git8 rebase illustration
f 423f7a1 Add git8 rebase merge illustration
# Rebase cefde40..423f7a1 onto 3ebd174 (5 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
31 lines ]
[ Read ^G Get Help ^O Write Out ^W Where Is ^K Cut Text ^J Justify ^C Cur Pos
^X Exit ^R Read File ^\ Replace ^U Paste Text^T To Spell ^_ Go To Line
Ensuite, on peut modifier les messages de commit
# This is a combination of 3 commits.
# This is the 1st commit message:
Add git8 merge bifucation illustration
# This is the commit message #2:
Add git8 rebase illustration
# The commit message #3 will be skipped:
# Add git8 rebase merge illustration
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date: Tue Aug 23 11:32:14 2022 +0200
#
# interactive rebase in progress; onto cefde40
Si on sauve ce fichier et qu’on quitte, on a réécrit l’histoire
-> rebase)
commit 5d107f70b48a6344e8bd8c07eb0e4683b572b924 (HEAD : Marie-Pierre Etienne <marie-pierre.etienne@agrocampus-ouest.fr>
Author: Tue Aug 23 11:54:53 2022 +0200
Date
Git rebase interactive mode redaction
commit 339f67470bbc5aee4fe737eb049a61c4212a405b: Marie-Pierre Etienne <marie-pierre.etienne@agrocampus-ouest.fr>
Author: Tue Aug 23 11:32:14 2022 +0200
Date
Add git8 merge bifucation illustration
Add git8 rebase illustration
commit d3ae968e4961f636c55a67e4d630574798154f3c: Marie-Pierre Etienne <marie-pierre.etienne@agrocampus-ouest.fr>
Author: Tue Aug 23 11:27:54 2022 +0200
Date
git rebase fast forward
/master, master)
commit 2a0b55e1ebba204c94126d51b72bacd1f8f0e0d0 (origin: Marie-Pierre Etienne <marie-pierre.etienne@agrocampus-ouest.fr>
Author: Tue Aug 23 09:34:53 2022 +0200
Date
Add build directory to .gitignore
commit cefde40f7516ff8877bca4a6cebc910a14dd7d15: Marie-Pierre Etienne <marie-pierre.etienne@agrocampus-ouest.fr>
Author: Tue Aug 23 09:34:12 2022 +0200
Date
-pages branch Remove build directory automatically created on the gh
Bien sur en réécrivant l’histoire on modifie le passé. Comme dans retour vers le futur, modifier le passé va affecter toutes les personnes concernées par ce passé. On doit donc etre très prudent avec cette approche. On ne rebase jamais master !!!! On ne peut réécrire l’histoire que pour des branches simples qui n’ont pas d’enfant.
Un outil pratique (merci Cédric pour comprendre, visualiser tester les différentes commandes git )