Git et «La branche« x »n'est pas complètement fusionnée» Erreur

294

Voici les commandes que j'ai utilisées depuis la branche master

git branch experiment
git checkout experiment

Ensuite, j'ai apporté des modifications à mes fichiers, validé les modifications et poussé la nouvelle branche vers GitHub.

git commit . -m 'changed files'
git push -u origin experiment

Plus tard, j'ai décidé de fusionner ma branche d'expérience dans la branche principale.

git checkout master
git merge experiment

Enfin, j'ai poussé les modifications vers GitHub.

git push -u origin master

Tout s'est bien passé jusqu'à ce que j'essaie de supprimer ma branche d'expérience en utilisant

git branch -d experiment

J'ai reçu le message d'erreur que error: The branch 'experiment' is not fully merged.je suis un peu nouveau sur git, et je ne sais pas combien de plus je pourrais éventuellement fusionner les deux branches. Qu'est-ce que j'oublie ici?

mellowsoon
la source
2
Est-ce que ce message vous aide? stackoverflow.com/questions/1710894/…
Chrisdigital
2
Cela arrive parfois quand j'ai fait ungit commit --amend
Arcolye
12
Aussi - Gardez à l'esprit que ce message apparaîtra après un squash: stackoverflow.com/q/41946475/109941
Jim G.
Je pense que le scénario le plus courant est, il vous suffit de retirer vos modifications récemment fusionnées avant de supprimer la branche localement.
RaisinBranCrunch

Réponses:

313

Remarque Le libellé a été modifié en réponse aux commentaires. Merci @slekse
Ce n'est pas une erreur, c'est un avertissement. Cela signifie que la branche que vous êtes sur le point de supprimer contient des validations qui ne sont pas accessibles depuis l'une de ses branches: sa branche en amont ou HEAD (révision actuellement extraite). En d'autres termes, lorsque vous risquez de perdre des commits¹.

En pratique, cela signifie que vous avez probablement modifié, rebasé ou filtré les commits et qu'ils ne semblent pas identiques.

Par conséquent, vous pouvez éviter l'avertissement en vérifiant une branche qui contient les validations que vous êtes sur le point de dé -référencer en supprimant cette autre branche.²

Vous voudrez vérifier que vous ne manquez en fait aucun commit essentiel:

git log --graph --left-right --cherry-pick --oneline master...experiment

Cela vous donnera une liste de tout non partagé entre les branches. Si vous êtes curieux, il pourrait y avoir une différence sans --cherry-picket cette différence pourrait bien être la raison de l'avertissement que vous obtenez:

--cherry-pick

Omettez tout commit qui introduit le même changement qu'un autre commit de "l'autre côté" lorsque l'ensemble des commits est limité avec une différence symétrique. Par exemple, si vous avez deux branches, A et B, une manière habituelle de répertorier toutes les validations d'un seul côté est avec - gauche-droite, comme l'exemple ci-dessus dans la description de cette option. Il montre cependant les commits qui ont été sélectionnés à partir de l'autre branche (par exemple, "3rd on b" peut être sélectionné à partir de la branche A). Avec cette option, ces paires de validations sont exclues de la sortie.


¹ ils ne sont vraiment récupérés qu'après un certain temps, par défaut. De plus, la git-branchcommande ne vérifie pas l'arborescence de révision de toutes les branches . L'avertissement est là pour éviter les erreurs évidentes.

² (Ma préférence ici est de forcer la suppression à la place, mais vous voudrez peut-être avoir une assurance supplémentaire).

sehe
la source
24
Merci. La phrase clé était "contient des commits qui ne sont accessibles depuis aucune autre tête de référence". Même si je n'avais plus besoin de la branche expérimentale, que je l'avais déjà fusionnée dans master et que je prévoyais de la supprimer de l'origine, git n'allait pas être content tant que je n'aurais pas poussé les modifications à expérimenter vers l'origine. Je suppose que cet avertissement était en quelque sorte un test de santé mentale.
mellowsoon
35
-1 "Cela signifie que la branche que vous êtes sur le point de supprimer contient des validations qui ne sont accessibles depuis aucune autre tête de référence." Ce n'est pas correct. L'avertissement signifie que la branche n'est accessible ni depuis son amont (si elle en a un), ni depuis la HEAD actuelle. Voir la page de manuel de git-branch.
sleske
3
@TachyonVortex Nice link. La commande git branch -vv a vraiment clarifié ce qui se passait pour moi.
Jason Massey
11
@sleske Merci pour le commentaire - cette réponse devrait vraiment être modifiée. Dommage qu'il soit très voté car la phrase explicative principale est incorrecte. J'ai juste eu ce problème et j'ai passé un temps ennuyeux à essayer de comprendre quel était le problème, et c'est juste que la branche de suivi à distance a été supprimée dans le cadre de la demande de tirage, et depuis que j'ai retiré les modifications du maître sur la branche locale. Le seul «problème» n'a pas été de trouver la branche de suivi à distance, qui a été supprimée (et j'essayais de supprimer la branche locale pour la même raison).
le
3
Oui, cela peut se produire simplement lorsque vous essayez de supprimer une branche locale si vous êtes sur une branche différente de celle sur laquelle vous étiez lorsque vous l'avez créée. "Les commits qui ne sont pas joignables à partir d'une autre référence" est incorrect et effrayant inutilement!
Amalgovinus
80

Comme l'a souligné Drew Taylor, la suppression de branche avec -d ne prend en compte que la TETE actuelle pour déterminer si la branche est "complètement fusionnée". Il se plaindra même si la succursale est fusionnée avec une autre succursale. Le message d'erreur pourrait certainement être plus clair à cet égard ... Vous pouvez soit extraire la branche fusionnée avant de la supprimer, soit simplement utiliser git branch -D. Le -D majuscule remplacera entièrement le chèque.

drwowe
la source
2
La partie sur HEAD actuel l'a corrigé pour moi. Mon maître était différent de la branche de fonctionnalité dont j'ai créé la branche conflictuelle: D
viki.omega9
1
Pour quelqu'un qui apprend git, le mot "courant" semble redondant avec "HEAD"? Il n'y a pas de TETE non courante - la TETE par définition est la branche courante . Suis-je en train de manquer quelque chose? Je suppose que vous pourriez dire "branche actuelle" ou "HEAD" mais pas "HEAD actuel".
Mark Lakata
Est - il possible de modifier / configurer ce (par exemple, l' ont toujours vérifier contre origin/master?) Je suppose que vérifier d' origin/masterabord pas trop onéreux, mais il se sent comme une sorte de flux bizarre - pourquoi dois - je vérifier origin/masterlocalement juste pour que vous vérifiiez que mes modifications y sont fusionnées?
Alec
15

J'ai essayé la réponse de sehe et cela n'a pas fonctionné.

Pour trouver les validations qui n'ont pas été fusionnées, utilisez simplement:

git log feature-branch ^master --no-merges
qwertzguy
la source
14

C'est ce qui m'est arrivé aujourd'hui, alors que je fusionnais ma toute première branche de fonctionnalité dans Master. Comme certains l'ont dit dans un thread ailleurs sur SO, l'astuce consistait à revenir à master avant d'essayer de supprimer la branche. Une fois de retour dans master, git était heureux de supprimer la branche sans aucun avertissement.

Drew Taylor
la source
7
Il ne semble pas que ce soit le problème spécifique ici, mais j'ai rencontré le problème que vous décrivez tout à l'heure, alors merci!
Daniel Buckmaster
4

Git vous avertit que vous risquez de perdre l'historique en supprimant cette branche. Même si cela ne supprimait pas immédiatement les validations, certaines ou toutes les validations de la branche deviendraient inaccessibles si elles ne faisaient pas partie d'une autre branche également.

Pour que la branche experimentsoit «complètement fusionnée» dans une autre branche, son commit de tip doit être un ancêtre du tip de l'autre branche, ce qui rend les commits dans experimentun sous-ensemble de l'autre branche. Cela permet de le supprimer en toute sécurité experiment, car toutes ses validations resteront dans l'historique du référentiel via l'autre branche. Il doit être «entièrement» fusionné, car il a peut-être déjà été fusionné plusieurs fois, mais des commits ont maintenant été ajoutés depuis la dernière fusion qui ne sont pas contenus dans l'autre branche.

Cependant, Git ne vérifie pas toutes les autres branches du référentiel; seulement deux:

  1. La branche actuelle (HEAD)
  2. La branche amont, s'il y en a une

La «branche amont» pour experiment, comme dans votre cas, l'est probablement origin/experiment. Si experimentest complètement fusionné dans la branche actuelle, Git le supprime sans aucune réclamation. Si ce n'est pas le cas, mais qu'il est complètement fusionné dans sa branche en amont, Git continue avec un avertissement ressemblant à:

warning: deleting branch 'experiment' that has been merged
to 'refs/remotes/origin/experiment', but not yet merged to
HEAD.
Deleted branch experiment (was xxxxxxxx).

xxxxxxxxindique un ID de validation. Être complètement fusionné dans son amont indique que les validations experimentont été poussées vers le référentiel d'origine, de sorte que même si vous les perdez ici, elles peuvent au moins être enregistrées ailleurs.

Puisque Git ne vérifie pas les autres branches, il peut être sûr de supprimer une branche car vous savez qu'elle est complètement fusionnée dans une autre; vous pouvez le faire avec l' -Doption comme indiqué, ou passer d'abord à cette branche et laisser Git confirmer le statut complètement fusionné pour vous.

troore
la source
1
La clé est "complètement fusionnée dans la branche actuelle ". J'avais une branche X 'de X complètement fusionnée dans X et j'avais déjà supprimé origine / X'. Mais avec Y vérifié, j'ai reçu cet avertissement. Quand j'ai vérifié, XI a pu supprimer X '. C'est plutôt stupide, je pense.
Lawrence Dol
2
Cette réponse est plagiée d'ici sans attribution chimera.labs.oreilly.com/books/1230000000561/…
Mark Lakata
3

pour voir les changements qui ne sont pas fusionnés, j'ai fait ceci:

git checkout experiment
git merge --no-commit master

git diff --cached

Remarque: cela montre les changements masterqui ne sont pas dans experiment.

N'oubliez pas de:

git merge --abort

Quand tu auras fini de regarder.

ThorSummoner
la source
@IgorGanapolsky Dunno exactement, bien que généralement man git-resetet les commandes de réinitialisation de git suffisent pour récupérer des problèmes d'état.
ThorSummoner
3

Solution la plus simple avec explication (solution à double vérification) (face au problème avant)

Le problème est:

1- Je ne peux pas supprimer une branche

2- Le terminal affiche toujours un message d'avertissement indiquant que certains commits ne sont pas encore approuvés

3- sachant que j'ai vérifié le master et la branche et qu'ils sont identiques (à jour)

Solution:

git checkout master
git merge branch_name
git checkout branch_name
git push
git checkout master
git branch -d branch_name

Explication:

lorsque votre branche est connectée à une branche distante en amont (sur Github, bitbucket ou autre), vous devez la fusionner (pousser) dans le maître et vous devez pousser les nouvelles modifications (validations) dans le référentiel distant (Github, bitbucket ou que ce soit) de la succursale,

ce que j'ai fait dans mon code, c'est que je suis passé à master, puis y fusionner la branche (pour vous assurer qu'ils sont identiques sur votre machine locale), puis je suis passé à nouveau à la branche et j'ai poussé les mises à jour ou les modifications dans la télécommande en ligne repo utilisant "git push".

après cela, je suis passé à nouveau au maître et j'ai essayé de supprimer la branche, et le problème (message d'avertissement) a disparu, et la branche a été supprimée avec succès

Elta3lab
la source
3

Vous pouvez simplement comprendre:

git log --cherry master ... expérimental

--cherry option est synonyme de --right-only --cherry-mark --no-merges

page de manuel git-log

il est utile de limiter la sortie aux validations de notre côté et de marquer celles qui ont été appliquées à l'autre côté d'une histoire fourchue avec git log --cherry upstream ... mybranch, similaire à git cherry upstream mybranch.

Pour info. --cherry-pickomet les validations équivalentes mais --cherry-marksne le fait pas. Il est utile de trouver une nouvelle base et de forcer des changements mis à jour entre la branche publique en amont et la collaboration

yongbin
la source
1

Je n'avais pas la branche en amont sur mon git local. J'avais créé une succursale locale à partir de master, git checkout -b mybranch. J'ai créé une branche avec l'interface graphique bitbucket sur le git en amont et j'ai poussé ma branche locale (mybranch) vers cette branche en amont. Une fois que j'ai fait un git fetch sur mon git local pour récupérer la branche en amont, je pouvais faire une git branch -d mybranch.

edW
la source
0

Je crois que le drapeau --forceest ce que vous recherchez vraiment. Utilisez simplement git branch -d --force <branch_name>pour supprimer la branche de force.

Sergey Samoylenko
la source