Comment puis-je écraser mes dernières validations X ensemble en une seule validation en utilisant Git?
Comment puis-je écraser mes dernières validations X ensemble en une seule validation en utilisant Git?
Réponses:
Utilisez git rebase -i <after-this-commit>
et remplacez "pick" sur le second commit et les suivants par "squash" ou "fixup", comme décrit dans le manuel .
Dans cet exemple, il <after-this-commit>
s'agit du hachage SHA1 ou de l'emplacement relatif de la tête de la branche actuelle à partir de laquelle les validations sont analysées pour la commande de rebase. Par exemple, si l'utilisateur souhaite afficher 5 validations à partir de la tête courante dans le passé, la commande est git rebase -i HEAD~5
.
<after-this-commit>
?
<after-this-commit>
est commit X + 1, c'est-à-dire le parent du commit le plus ancien que vous souhaitez écraser.
rebase -i
approche et reset --soft
is, rebase -i
me permet de conserver l'auteur du commit, tout en reset --soft
me permettant de recommencer. Parfois, j'ai besoin d'écraser les commits de demandes de tirage tout en conservant les informations sur l'auteur. Parfois, je dois réinitialiser le soft sur mes propres commits. Upvotes aux deux grandes réponses de toute façon.
Vous pouvez le faire assez facilement sans git rebase
ou git merge --squash
. Dans cet exemple, nous écraserons les 3 derniers commits.
Si vous souhaitez écrire le nouveau message de commit à partir de zéro, cela suffit:
git reset --soft HEAD~3 &&
git commit
Si vous souhaitez commencer à éditer le nouveau message de validation avec une concaténation des messages de validation existants (c'est-à-dire semblable à ce qu'une git rebase -i
liste d'instructions pick / squash / squash /… / squash vous lancerait), alors vous devez extraire ces messages et passer à git commit
:
git reset --soft HEAD~3 &&
git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"
Ces deux méthodes écrasent les trois dernières validations en une seule nouvelle validation de la même manière. La réinitialisation logicielle redirige simplement HEAD vers le dernier commit que vous ne voulez pas écraser. Ni l'index ni l'arborescence de travail ne sont touchés par la réinitialisation logicielle, laissant l'index dans l'état souhaité pour votre nouveau commit (c'est-à-dire qu'il a déjà toutes les modifications des commits que vous êtes sur le point de «jeter»).
git rebase --squash-recent
- être , ou même git commit --amend-many
.
branch@{upstream}
(ou juste @{upstream}
pour la branche actuelle; dans les deux cas, la dernière partie peut être abrégée en @{u}
; voir gitrevisions ). Cela peut différer de votre «dernier commit poussé» (par exemple, si quelqu'un d'autre a poussé quelque chose qui a construit au-dessus de votre dernier push et que vous l'avez récupéré), mais il semble que cela pourrait être proche de ce que vous voulez.
push -f
mais sinon c'était charmant, merci.
git push --force
ensuite pour que ça prenne le commit
Vous pouvez utiliser git merge --squash
pour cela, qui est légèrement plus élégant que git rebase -i
. Supposons que vous soyez maître et que vous vouliez écraser les 12 derniers commits en un seul.
AVERTISSEMENT: assurez-vous d'abord de valider votre travail - vérifiez qu'il git status
est propre (car git reset --hard
il supprimera les modifications par étapes et non par étapes)
Alors:
# Reset the current branch to the commit just before the last 12:
git reset --hard HEAD~12
# HEAD@{1} is where the branch was just before the previous command.
# This command sets the state of the index to be as it would just
# after a merge from that commit:
git merge --squash HEAD@{1}
# Commit those squashed changes. The commit message will be helpfully
# prepopulated with the commit messages of all the squashed commits:
git commit
La documentation degit merge
décrit l' --squash
option plus en détail.
Mise à jour: le seul véritable avantage de cette méthode par rapport à la plus simple git reset --soft HEAD~12 && git commit
suggérée par Chris Johnsen dans sa réponse est que vous obtenez le message de validation pré-rempli avec chaque message de validation que vous écrasez.
git rebase -i
, mais vous n'en donnez pas la raison. Provisoirement -1, car il me semble qu'en fait le contraire est vrai et c'est un hack; N'exécutez-vous pas plus de commandes que nécessaire juste pour forcer git merge
à faire l'une des choses git rebase
spécifiquement conçues pour?
git merge --squash
est également plus facile à utiliser dans un script. Essentiellement, le raisonnement était que vous n'avez pas besoin du tout d '"interactivité" git rebase -i
pour cela.
git merge --squash
est moins susceptible de produire des conflits de fusion face aux mouvements / suppressions / renommages par rapport au rebasage, surtout si vous fusionnez à partir d'une branche locale. (Avertissement: basé sur une seule expérience, corrigez-moi si ce n'est pas vrai dans le cas général!)
HEAD@{1}
juste du bon côté, par exemple lorsque votre flux de travail est interrompu pendant une heure par une panne de courant, etc.
Je recommande d'éviter git reset
autant que possible - en particulier pour les novices Git. À moins que vous n'ayez vraiment besoin d'automatiser un processus basé sur un certain nombre de validations, il existe une méthode moins exotique ...
git merge --squash (working branch name)
git commit
Le message de validation sera prérempli en fonction du squash.
gitk
pour étiqueter la ligne de code que vous écrasez et étiqueter également la base sur laquelle écraser. Dans le cas normal, ces deux étiquettes existent déjà, donc l'étape (1) peut être ignorée.
git branch your-feature && git reset --hard HEAD~N
le moyen le plus pratique. Cependant, cela implique à nouveau git reset, ce que cette réponse a tenté d'éviter.
Sur la base de la réponse de Chris Johnsen ,
Ajouter un alias global "squash" depuis bash: (ou Git Bash sous Windows)
git config --global alias.squash '!f(){ git reset --soft HEAD~${1} && git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"; };f'
... ou à l'aide de l'invite de commandes de Windows:
git config --global alias.squash "!f(){ git reset --soft HEAD~${1} && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; };f"
Votre ~/.gitconfig
devrait maintenant contenir cet alias:
[alias]
squash = "!f(){ git reset --soft HEAD~${1} && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; };f"
Usage:
git squash N
... qui écrase automatiquement les derniers N
commits, inclus.
Remarque: Le message de validation résultant est une combinaison de toutes les validations écrasées, dans l'ordre. Si vous n'êtes pas satisfait de cela, vous pouvez toujours git commit --amend
le modifier manuellement. (Ou, modifiez l'alias en fonction de vos goûts.)
git squash -m "New summary."
et N
déterminer automatiquement le nombre de commits non poussés.
git commit --amend
pour modifier davantage le message, mais cet alias vous permet de prendre un bon départ sur ce qui devrait être dans le message de validation.
Grâce à ce billet de blog pratique, j'ai trouvé que vous pouvez utiliser cette commande pour écraser les 3 derniers commits:
git rebase -i HEAD~3
C'est pratique car cela fonctionne même lorsque vous êtes sur une succursale locale sans informations de suivi / repo à distance.
La commande ouvrira l'éditeur de rebase interactif qui vous permettra ensuite de réorganiser, écraser, reformuler, etc. comme d'habitude.
Utilisation de l'éditeur de rebase interactif:
L'éditeur de rebase interactif affiche les trois derniers commits. Cette contrainte a été déterminée par l' HEAD~3
exécution de la commande git rebase -i HEAD~3
.
Le commit le plus récent,, HEAD
est affiché en premier sur la ligne 1. Les lignes commençant par a #
sont des commentaires / documentation.
La documentation affichée est assez claire. Sur une ligne donnée, vous pouvez changer la commande de pick
en une commande de votre choix.
Je préfère utiliser la commande fixup
car cela "écrase" les modifications du commit dans le commit sur la ligne ci-dessus et rejette le message du commit.
Comme le commit sur la ligne 1 est HEAD
, dans la plupart des cas, vous laisseriez cela comme pick
. Vous ne pouvez pas utiliser squash
ou fixup
car il n'y a pas d'autre commit pour écraser le commit.
Vous pouvez également modifier l'ordre des validations. Cela vous permet d'annuler ou de corriger les commits qui ne sont pas adjacents chronologiquement.
Un exemple pratique au quotidien
J'ai récemment validé une nouvelle fonctionnalité. Depuis lors, j'ai commis deux corrections de bugs. Mais maintenant, j'ai découvert un bug (ou peut-être juste une faute d'orthographe) dans la nouvelle fonctionnalité que j'ai validée. Comme c'est ennuyeux! Je ne veux pas qu'un nouveau commit pollue mon historique de commit!
La première chose que je fais est de corriger l'erreur et de faire un nouveau commit avec le commentaire squash this into my new feature!
.
Je lance ensuite git log
ou gitk
et j'obtiens le commit SHA de la nouvelle fonctionnalité (dans ce cas1ff9460
).
Ensuite, je lance l'éditeur de rebase interactif avec git rebase -i 1ff9460~
. le~
après la validation SHA indique l'éditeur d'inclure cette validation dans l'éditeur.
Ensuite, je déplace la validation contenant le correctif ( fe7f1e0
) sous la validation de la fonctionnalité et je change pick
enfixup
.
À la fermeture de l'éditeur, le correctif sera écrasé dans la validation de la fonctionnalité et mon historique de validation sera joli et propre!
Cela fonctionne bien lorsque toutes les validations sont locales, mais si vous essayez de modifier les validations déjà poussées vers la télécommande, vous pouvez vraiment causer des problèmes aux autres développeurs qui ont extrait la même branche!
pick
en ligne 1. Si vous choisissez squash
ou fixup
pour le commit sur la ligne 1, git affichera un message disant "erreur: ne peut pas" réparer "sans un commit précédent". Ensuite, il vous donnera la possibilité de le corriger: "Vous pouvez résoudre ce problème avec 'git rebase --edit-todo' puis exécuter 'git rebase --continue'." ou vous pouvez simplement abandonner et recommencer: "Ou vous pouvez abandonner le rebase avec 'git rebase --abort'.".
Si vous utilisez TortoiseGit, vous pouvez la fonction Combine to one commit
:
Show Log
Combine to one commit
dans le menu contextuelCette fonction exécute automatiquement toutes les étapes git simples nécessaires. Malheureusement, uniquement disponible pour Windows.
Pour ce faire, vous pouvez utiliser la commande git suivante.
git rebase -i HEAD~n
n (= 4 ici) est le numéro du dernier commit. Ensuite, vous avez les options suivantes,
pick 01d1124 Message....
pick 6340aaa Message....
pick ebfd367 Message....
pick 30e0ccb Message....
Mettre à jour comme ci-dessous pick
un commit et squash
les autres dans le plus récent,
p 01d1124 Message....
s 6340aaa Message....
s ebfd367 Message....
s 30e0ccb Message....
Pour plus de détails, cliquez sur le lien
Basé sur cet article j'ai trouvé cette méthode plus facile pour mon cas d'utilisation.
Ma branche «dev» devançait «origin / dev» de 96 commits (donc ces commits n'étaient pas encore poussés vers la télécommande).
Je voulais écraser ces commits en un seul avant de pousser le changement. Je préfère réinitialiser la branche à l'état «origine / dev» (cela laissera toutes les modifications des 96 validations non mises en scène), puis valider les modifications à la fois:
git reset origin/dev
git add --all
git commit -m 'my commit message'
Dans la branche sur laquelle vous souhaitez combiner les validations, exécutez:
git rebase -i HEAD~(n number of commits back to review)
exemple:
git rebase -i HEAD~1
Cela ouvrira l'éditeur de texte et vous devez changer le 'pick' devant chaque commit avec 'squash' si vous souhaitez que ces commits soient fusionnés ensemble. De la documentation:
Par exemple, si vous cherchez à fusionner toutes les validations en une seule, la «sélection» est la première validation que vous avez effectuée et toutes les futures (placées sous la première) doivent être définies sur «squash». Si vous utilisez vim, utilisez : x en mode insertion pour enregistrer et quitter l'éditeur.
Puis pour continuer le rebase:
git rebase --continue
Pour en savoir plus à ce sujet et sur d'autres façons de réécrire votre historique de validation, consultez cet article utile
--continue
et vim :x
.
git add
la bonne configuration dans vos fichiers que vous utilisez git rebase --continue
pour passer à la prochaine validation et commencer à fusionner. :x
est une commande qui enregistrera les modifications du fichier lors de l'utilisation de vim voir ceci
Anomies réponse est bonne, mais je ne me sentais pas en sécurité à ce sujet, j'ai donc décidé d'ajouter quelques captures d'écran.
Voyez où vous en êtes git log
. Plus important encore, trouvez le hachage de validation du premier commit que vous ne voulez pas écraser. Donc seulement:
Exécutez git rebase -i [your hash]
, dans mon cas:
$ git rebase -i 2d23ea524936e612fae1ac63c95b705db44d937d
Dans mon cas, je veux tout écraser sur le commit qui était le premier dans le temps. L'ordre est du premier au dernier, donc exactement dans l'autre sens que dans git log
. Dans mon cas, je veux:
Si vous avez sélectionné un seul commit et écrasé le reste, vous pouvez ajuster un message de commit:
C'est ça. Une fois que vous avez enregistré ceci ( :wq
), vous avez terminé. Jetez-y un œil avec git log
.
git log
1) Identifier le hachage court de validation
# git log --pretty=oneline --abbrev-commit
abcd1234 Update to Fix for issue B
cdababcd Fix issue B
deab3412 Fix issue A
....
Ici même git log --oneline
pouvez également utiliser pour obtenir un hachage court.
2) Si vous voulez écraser (fusionner) les deux derniers commit
# git rebase -i deab3412
3) Cela ouvre un nano
éditeur pour la fusion. Et ça ressemble à ci-dessous
....
pick cdababcd Fix issue B
pick abcd1234 Update to Fix for issue B
....
4) renommer le mot pick
pour squash
lequel est présent avant abcd1234
. Après avoir renommé, il devrait être comme ci-dessous.
....
pick cdababcd Fix issue B
squash abcd1234 Update to Fix for issue B
....
5) Maintenant, enregistrez et fermez l' nano
éditeur. Appuyez sur ctrl + o
et appuyez sur Enter
pour enregistrer. Et puis appuyez surctrl + x
pour quitter l'éditeur.
6) Ensuite nano
éditeur s'ouvre à nouveau pour mettre à jour les commentaires, si nécessaire, mettez-le à jour.
7) Maintenant, il est écrasé avec succès, vous pouvez le vérifier en vérifiant les journaux.
# git log --pretty=oneline --abbrev-commit
1122abcd Fix issue B
deab3412 Fix issue A
....
8) Maintenant, poussez pour repo. Remarque pour ajouter un +
signe avant le nom de la branche. Cela signifie une poussée forcée.
# git push origin +master
Remarque: Ceci est basé sur l'utilisation de git sur ubuntu
shell. Si vous utilisez différents systèmes d'exploitation ( Windows
ou Mac
), les commandes ci-dessus sont les mêmes, sauf l'éditeur. Vous pourriez obtenir un éditeur différent.
git add <files>
--fixup
option et le OLDCOMMIT
devrait être sur lequel nous devons fusionner (écraser) ce commit.git commit --fixup=OLDCOMMIT
Maintenant, cela crée un nouveau commit au-dessus de HEAD avec fixup1 <OLDCOMMIT_MSG>
.
OLDCOMMIT
.git rebase --interactive --autosquash OLDCOMMIT^
Ici ^
signifie le précédent commit OLDCOMMIT
. Cette rebase
commande ouvre une fenêtre interactive sur un éditeur (vim ou nano) sur lequel nous n'avons pas besoin de faire quoi que ce soit juste enregistrer et sortir est suffisant. Parce que l'option transmise à ceci déplacera automatiquement le dernier commit à côté de l'ancien commit et changera l'opération en fixup
(équivalent à squash). Ensuite, le rebase continue et se termine.
--amend
peuvent être utilisés avec git-commit
. # git log --pretty=oneline --abbrev-commit
cdababcd Fix issue B
deab3412 Fix issue A
....
# git add <files> # New changes
# git commit --amend
# git log --pretty=oneline --abbrev-commit
1d4ab2e1 Fix issue B
deab3412 Fix issue A
....
--amend
Fusionne ici les nouvelles modifications au dernier commit cdababcd
et génère un nouvel ID de commit1d4ab2e1
Pour écraser les 10 derniers commits en 1 seul commit:
git reset --soft HEAD~10 && git commit -m "squashed commit"
Si vous souhaitez également mettre à jour la branche distante avec la validation écrasée:
git push -f
Si vous êtes sur une branche distante (appelée feature-branch
) clonée à partir d'un référentiel doré ( golden_repo_name
), voici la technique pour écraser vos commits en une seule:
Commander le repo doré
git checkout golden_repo_name
Créez-en une nouvelle branche (repo doré) comme suit
git checkout -b dev-branch
Fusion de squash avec votre succursale locale que vous avez déjà
git merge --squash feature-branch
Validez vos modifications (ce sera la seule validation qui va dans dev-branch)
git commit -m "My feature complete"
Poussez la branche vers votre référentiel local
git push origin dev-branch
Ce qui peut être vraiment pratique:
trouvez le hachage de validation que vous souhaitez écraser, par exempled43e15
.
Maintenant, utilisez
git reset d43e15
git commit -am 'new commit name'
C'est super bavard, mais d'une manière plutôt cool, donc je vais juste le jeter dans le ring:
GIT_EDITOR='f() { if [ "$(basename $1)" = "git-rebase-todo" ]; then sed -i "2,\$s/pick/squash/" $1; else vim $1; fi }; f' git rebase -i foo~5 foo
Traduction: fournir un nouvel "éditeur" pour git qui, si le nom de fichier à éditer est git-rebase-todo
(l'invite de rebase interactive) change tout sauf le premier "pick" en "squash", et génère autrement vim - de sorte que lorsque vous y êtes invité pour modifier le message de validation écrasé, vous obtenez vim. (Et évidemment, j'écrasais les cinq derniers commits sur branch foo, mais vous pouvez changer cela comme bon vous semble.)
Je ferais probablement ce que Mark Longair a suggéré .
Si vous voulez écraser chaque commit en un seul commit (par exemple lorsque vous publiez un projet publiquement pour la première fois), essayez:
git checkout --orphan <new-branch>
git commit
Je pense que la façon la plus simple de le faire est de créer une nouvelle branche hors de master et de faire une fusion - squash de la branche de fonctionnalité.
git checkout master
git checkout -b feature_branch_squashed
git merge --squash feature_branch
Ensuite, vous avez toutes les modifications prêtes à être validées.
One-liner simple qui fonctionne toujours, étant donné que vous êtes actuellement sur la branche que vous souhaitez écraser, master est la branche dont il est issu et le dernier commit contient le message de commit et l'auteur que vous souhaitez utiliser:
git reset --soft $(git merge-base HEAD master) && git commit --reuse-message=HEAD@{1}
si par exemple vous voulez écraser les 3 dernières validations en une seule validation dans une branche (référentiel distant) dans par exemple: https://bitbucket.org
Ce que j'ai fait c'est
(MASTER)
Fleetwood Mac Fritz
║ ║
Add Danny Lindsey Stevie
Kirwan Buckingham Nicks
║ ╚═══╦══════╝
Add Christine ║
Perfect Buckingham
║ Nicks
LA1974══════════╝
║
║
Bill <══════ YOU ARE EDITING HERE
Clinton (CHECKED OUT, CURRENT WORKING DIRECTORY)
Dans cette histoire très abrégée du référentiel https://github.com/fleetwood-mac/band-history , vous avez ouvert une pull request pour fusionner le Bill Clinton commit dans l'original (MASTER
commit Fleetwood Mac ).
Vous avez ouvert une demande de pull et sur GitHub vous voyez ceci:
Quatre commits:
Penser que personne ne se soucierait jamais de lire l'historique complet du référentiel. (Il y a en fait un dépôt, cliquez sur le lien ci-dessus!) Vous décidez d'écraser ces commits. Alors tu vas courir git reset --soft HEAD~4 && git commit
. Alors vousgit push --force
sur GitHub pour nettoyer votre PR.
Et que se passe-t-il? Vous venez de faire un seul commit qui va de Fritz à Bill Clinton. Parce que vous avez oublié qu'hier vous travailliez sur la version Buckingham Nicks de ce projet. Et git log
ne correspond pas à ce que vous voyez sur GitHub.
git checkout
lesgit reset --soft
quegit commit
que funes directement à partir du de la àgit rebase -i HEAD^^
où le nombre de ^ est X
(dans ce cas, écrasez les deux derniers commits)
En plus d'autres excellentes réponses, j'aimerais ajouter comment git rebase -i
me confond toujours avec l'ordre de validation - du plus ancien au plus récent ou vice versa? Voici donc mon workflow:
git rebase -i HEAD~[N]
, où N est le nombre de validations que je veux rejoindre, en commençant par la plus récente . Cela git rebase -i HEAD~5
signifierait donc "écraser les 5 derniers commits en un nouveau";Qu'en est-il d'une réponse à la question liée à un flux de travail comme celui-ci?
merge --squash
après le PR, mais l'équipe a pensé que cela ralentirait le processus.)Je n'ai pas vu de flux de travail comme celui-ci sur cette page. (Cela peut être mes yeux.) Si je comprends rebase
bien, plusieurs fusions nécessiteraient plusieurs résolutions de conflits . Je ne veux même pas y penser!
Donc, cela semble fonctionner pour nous.
git pull master
git checkout -b new-branch
git checkout -b new-branch-temp
git checkout new-branch
git merge --squash new-branch-temp
// met tous les changements en scènegit commit 'one message to rule them all'
git push
Je trouve qu'une solution plus générique ne consiste pas à spécifier les «N» commits, mais plutôt la branche / commit-id que vous souhaitez écraser au-dessus. C'est moins sujet aux erreurs que de compter les validations jusqu'à une validation spécifique - spécifiez simplement la balise directement, ou si vous voulez vraiment compter, vous pouvez spécifier HEAD ~ N.
Dans mon flux de travail, je démarre une branche, et mon premier commit sur cette branche résume l'objectif (c'est-à-dire que c'est généralement ce que je vais pousser comme message «final» pour la fonctionnalité dans le référentiel public.) Donc, quand j'ai terminé, tout Je veux faire est git squash master
revenir au premier message et puis je suis prêt à pousser.
J'utilise l'alias:
squash = !EDITOR="\"_() { sed -n 's/^pick //p' \"\\$1\"; sed -i .tmp '2,\\$s/^pick/f/' \"\\$1\"; }; _\"" git rebase -i
Cela videra l'historique écrasé avant de le faire - cela vous donne une chance de récupérer en récupérant un ancien ID de validation de la console si vous souhaitez revenir. (Les utilisateurs de Solaris notent qu'il utilise l' -i
option sed GNU , les utilisateurs Mac et Linux devraient être d'accord avec cela.)
git squash master
lorsque nous sommes contrôlés sur l'esclave. que se passera-t-il? cacherons-nous le conflit?
En question, il pourrait être ambigu ce que l'on entend par «dernier».
par exemple, git log --graph
sort les éléments suivants (simplifiés):
* commit H0
|
* merge
|\
| * commit B0
| |
| * commit B1
| |
* | commit H1
| |
* | commit H2
|/
|
Les dernières validations par le temps sont H0, merge, B0. Pour les écraser, vous devrez rebaser votre branche fusionnée lors de la validation H1.
Le problème est que H0 contient H1 et H2 (et généralement plus de validations avant fusion et après branchement) tandis que B0 n'en contient pas. Vous devez donc gérer les modifications de H0, fusion, H1, H2, B0 au moins.
Il est possible d'utiliser rebase mais de manière différente, puis dans d'autres réponses mentionnées:
rebase -i HEAD~2
Cela vous montrera les options de choix (comme mentionné dans d'autres réponses):
pick B1
pick B0
pick H0
Mettez la courge au lieu de choisir H0:
pick B1
pick B0
s H0
Après la sauvegarde et la sortie, le rebase appliquera les commits à son tour après H1. Cela signifie qu'il vous demandera de résoudre à nouveau les conflits (où HEAD sera H1 dans un premier temps, puis accumulera les validations au fur et à mesure de leur application).
Une fois le rebase terminé, vous pouvez choisir le message pour H0 et B0 écrasés:
* commit squashed H0 and B0
|
* commit B1
|
* commit H1
|
* commit H2
|
PS Si vous faites juste une réinitialisation sur BO: (par exemple, l'utilisation reset --mixed
est expliquée plus en détail ici https://stackoverflow.com/a/18690845/2405850 ):
git reset --mixed hash_of_commit_B0
git add .
git commit -m 'some commit message'
puis vous vous écrasez dans les changements B0 de H0, H1, H2 (perdre complètement valide les changements après la ramification et avant la fusion.