Ma recommandation (ou, "ce que je ferais si j'étais M. Orange") est de commencer par git fetch
. Maintenant j'ai ceci dans mon dépôt, qui est ce que Mr Blond avait après son rebasement et juste avant qu'il n'exécute "git push -f".
M1 - M2 - M3
\ \
\ \
A1 - A2 A1' - A2'
La seule différence importante, c'est que j'aurai mon propre label. A
pointant vers le rév A2, et l'étiquette distante remotes/origin/A
pointant vers A2' (M. Blond l'avait dans l'autre sens, l'étiquette locale A
pointant vers A2' et remotes/origin/A
en pointant vers A2).
Si j'ai travaillé sur ma copie de la branche nommée "A", je vais avoir ceci à la place :
M1 ---- M2 ---- M3
\ \
\ \
A1 - A2 - A3 A1' - A2'
(avec mon étiquette locale indiquant A3 plutôt que A2 ; ou A4 ou A5, etc., selon le nombre de modifications que j'ai appliquées). Maintenant, tout ce que j'ai à faire est de rebaser mon A3 (et A4 si nécessaire, etc) sur A2'. Un moyen direct évident :
$ git branch -a
master
* A
remotes/origin/master
remotes/origin/A
$ git branch new_A remotes/origin/A
$ git rebase -i new_A
et ensuite laisser tomber complètement les révisions A1 et A2, puisque les révisions modifiées sont dans new_A comme A1' et A2'. Ou bien :
$ git checkout -b new_A remotes/origin/A
$ git format-patch -k --stdout A3..A | git am -3 -k
(le git am -3 -k
est décrite dans le git-format-patch
page du manuel).
Il faut savoir ce que j'ai que M. Blond n'avait pas avant de faire son rebase
c'est-à-dire en identifiant A1, A2, A3, etc.
Si la deuxième approche est réussie, je me retrouve avec :
M1 ---- M2 ---- M3
\ \
\ \
A1 - A2 - A3 A1' - A2' - A3'
où le nom de ma branche new_A
pointe vers A3' (mon existant A
pointe toujours vers l'ancien A3). Si j'utilise la première approche et qu'elle réussit, je me retrouve avec la même chose, c'est juste que le nom de ma branche existante A
pointera maintenant vers A3' (et je n'ai pas de nom pour l'ancienne branche avec A1-A2-A3, même si elle est toujours dans mon repo ; pour la trouver, il faut passer par les reflogs ou autres).
(Si mon A3 a besoin d'être modifié pour devenir A3', la méthode interactive rebase et la méthode "git am" nécessiteront toutes deux un travail de ma part, bien sûr).
Bien sûr, il est également possible de simplement git merge
(comme dans la réponse de Gary Fixler), mais cela créera un commit de fusion ("M" sans numéro, ci-dessous) et gardera les revs A1 et A2 visibles, donnant :
M1 ---- M2 ---- M3
\ \
\ \
A1 - A2 - A3 A1' - A2' -- M
\_______________/
Si vous voulez préserver les originaux A1 et A2, c'est une bonne chose ; si vous voulez vous en débarrasser, c'est une mauvaise chose. Ainsi, "ce qu'il faut faire" dépend de "ce que vous voulez que le résultat soit".
Modification pour ajouter : je préfère la méthode format-patch car elle laisse mon ancien nom de branche A pendant que je m'assure que tout est bon. En supposant que tout fonctionne et que es Bien, voici les dernières étapes :
$ git branch -m A old_A
$ git branch -m new_A A
et ensuite, si l'ancienne version peut être entièrement abandonnée :
$ git branch -D old_A
ou, de manière équivalente, commencer par la branche delete, puis renommer new_A en A.
(Edit : voir aussi git rebase --onto
dans le but de rebaser A3, etc., sur la branche new_A).