que voulez-vous dire par divergence? rebasez-vous votre maître après l'avoir poussé?
hasen
13
Je reçois un message disant "Votre branche et 'origine / maître' ont divergé, # et ont respectivement 1 et 1 commit (s) différent (s)."
Frank
J'ai mis à jour ma réponse pour refléter ce message d'avertissement "divergé".
VonC
La réponse acceptée à une autre question peut également être utile pour résoudre certains cas où cela pourrait entrer en jeu (par exemple, vous essayez de déplacer votre maître, mais il a déjà été poussé): stackoverflow.com/questions/2862590/…
lindes
8
L'explication sur ce blog m'a aidé infiniment plus que n'importe quelle réponse ci-dessous: sebgoo.blogspot.com/2012/02/…
"Votre branche et 'origine / maître' ont divergé, # et ont respectivement 1 et 1 commit (s) différent (s)."
, vérifiez si vous devez mettre à jourorigin . Si originest à jour, certaines validations ont été transférées origindepuis un autre référentiel pendant que vous effectuez vos propres validations localement.
... o ---- o ---- A ---- B origin/master (upstream work)
\
C master (your work)
Vous avez basé le commit C sur le commit A car c'était le dernier travail que vous aviez récupéré en amont à l'époque.
Cependant, avant que vous n'essayiez de repousser à l'origine, quelqu'un d'autre a poussé la validation B.
L'historique du développement a divergé dans des chemins distincts.
Cela indique à Git d'intégrer les modifications de origin/masterdans votre travail et de créer un commit de fusion.
Le graphique de l'histoire ressemble maintenant à ceci:
... o ---- o ---- A ---- B origin/master (upstream work)
\ \
C ---- M master (your work)
La nouvelle fusion, commit M, a deux parents, chacun représentant un chemin de développement qui a conduit au contenu stocké dans ce commit.
Notez que l'historique derrière M est désormais non linéaire.
Rebase
Utilisez la commande git rebase:
$ git rebase origin/master
Cela indique à Git de rejouer la validation C (votre travail) comme si vous l'aviez basée sur la validation B au lieu de A. Les utilisateurs
CVS et Subversion rebasinent régulièrement leurs modifications locales au-dessus du travail en amont lorsqu'ils mettent à jour avant la validation.
Git ajoute simplement une séparation explicite entre les étapes de validation et de rebase.
Le graphique de l'histoire ressemble maintenant à ceci:
... o ---- o ---- A ---- B origin/master (upstream work)
\
C' master (your work)
Commit C 'est un nouveau commit créé par la commande git rebase.
Il diffère de C de deux manières:
Il a une histoire différente: B au lieu de A.
Son contenu explique les changements à la fois en B et en C; c'est la même chose que M dans l'exemple de fusion.
Notez que l'histoire derrière C 'est toujours linéaire.
Nous avons choisi (pour l'instant) de n'autoriser que l'histoire linéaire dans cmake.org/cmake.git.
Cette approche préserve le workflow basé sur CVS utilisé précédemment et peut faciliter la transition.
Une tentative de pousser C 'dans notre référentiel fonctionnera (en supposant que vous avez des autorisations et que personne n'a poussé pendant que vous rebasiez).
La commande git pull fournit un moyen raccourci pour récupérer à partir de l'origine et rebaser le travail local dessus:
$ git pull --rebase
Ceci combine les étapes de récupération et de rebase ci-dessus en une seule commande.
J'ai trouvé cela en recherchant le même problème, pouvez-vous expliquer pourquoi 'git reset --hard HEAD' n'a pas résolu le problème?
Neth
12
@Neth: car il ne s'agit pas de modifications par étapes (ie modifications présentes dans l'index mais pas encore validées), mais de validations locales (qui diffèrent des validations présentes sur la télécommande). git reset --hard HEADne ferait que supprimer toute modification non indexée commis locale, et ne ferait rien pour concilier les différences entre les locaux et distants commits . Seule une fusion ou un rebase rapprochera les deux ensembles de commits (le local et le distant).
VonC
4
Wow, merci pour cette réponse géniale. Nous avions accidentellement fait un "git pull" sans "--rebase", et "git rebase origin / master" était juste la solution!
mrooney
3
Que diriez-vous - je veux juste ignorer / vider mes modifications locales et être avec ma branche locale où se trouve la télécommande? En d'autres termes, je veux mastermontrer Bvotre exemple.
CygnusX1
23
@ CygnusX1 qui serait git reset --hard origin/mastercomme mentionné dans la réponse ci-dessous: stackoverflow.com/a/8476004/6309
VonC
726
J'ai eu cela et je suis mystifié de ce qui l'a causé, même après avoir lu les réponses ci-dessus. Ma solution était de faire
git reset --hard origin/master
Ensuite, cela réinitialise simplement ma copie (locale) de master (que je suppose vissée) au bon point, comme représenté par origine / master (distant).
AVERTISSEMENT : vous perdrez toutes les modifications non encore poussées origin/master.
oui, cela ressemble un peu à l'option des mannequins, mais s'il n'y a pas de réel danger et que vous êtes ici pour une solution rapide - cela fonctionne (pour moi de toute façon)
PandaWood
7
Cela nécessite d'être sur la branche principale avant ("git checkout master").
blueyed
Cela m'est arrivé une fois quand je suis arrivé le plus tard de l'origine, puis quelqu'un d'autre a fait une poussée forcée vers l'origine qui a fait revenir le commit d'origine d'origine. Donc ma branche locale avait le commit annulé, et quand j'ai essayé de retirer le dernier de l'origine, cela disait que je devais fusionner. Dans ce cas, il était logique de réinitialiser --hard origin / (branch) car le problème avait déjà été corrigé dans l'origine.
Landon Poch
96
Vous devriez probablement avertir les utilisateurs que cela leur fera perdre tous les changements non encore poussés à l'origine
Pedro Loureiro
6
@PedroLoureiro Les commits sont vraiment perdus, vous pouvez toujours trouver les commits avec git reflogou les voir dedans gitk --all. Mais pourtant, bien sûr, la réinitialisation matérielle est autre chose qu'un rebase.
sebkraemer
52
git pull --rebase origin/master
est une commande unique qui peut vous aider la plupart du temps.
Modifier: extrait les validations de l'origine / du masque et applique vos modifications à l'historique de branche nouvellement extrait.
veuillez mentionner ce que fait la commande, sinon les gens pourraient l'exécuter et finir par bousiller
Baz1nga
1
S'il n'y a pas de problème, vous devriez vous retrouver avec votre master contenant toutes les modifications origine / master et tous vos commits locaux seront rejoués par dessus. Ça me semble bien.
Philipp Claßen
7
Sauf lorsqu'il y a de réelles différences et que cela vous laisse dans un rebase avorté.
ffledgling
Cela génère une erreur: erreur: impossible de fusionner les modifications. Le patch a échoué à 0024 Modèles de demande et de réponse
IgorGanapolsky
32
Je me suis retrouvé dans cette situation lorsque j'ai essayé de rebaser une branche qui suivait une branche distante, et j'essayais de la rebaser sur master. Dans ce scénario, si vous essayez de rebaser, vous trouverez très probablement que votre branche a divergé et cela peut créer un gâchis qui n'est pas pour les git nubees!
Disons que vous êtes sur la branche my_remote_tracking_branch, qui a été branchée à partir de master
$ git status
# Sur la branche my_remote_tracking_branch
rien à valider (répertoire de travail propre)
Et maintenant, vous essayez de rebaser du maître en tant que:
git rebase master
ARRÊTEZ MAINTENANT et épargnez-vous des ennuis! Utilisez plutôt la fusion comme:
git merge master
Oui, vous vous retrouverez avec des commits supplémentaires sur votre branche. Mais à moins que vous ne souhaitiez des branches "non divergentes", ce sera un flux de travail beaucoup plus fluide que le rebasage. Voir ce blog pour une explication beaucoup plus détaillée.
D'un autre côté, si votre branche est uniquement une branche locale (c'est-à-dire qu'elle n'est pas encore envoyée à une télécommande), vous devez certainement faire un rebase (et votre branche ne divergera pas dans ce cas).
Maintenant , si vous lisez ceci parce que vous avez déjà êtes dans un scénario « divergé » en raison de ce changement de base, vous pouvez revenir à la dernière validation d'origine ( par exemple dans un état divergé non) en utilisant:
Une règle d'or consiste à utiliser rebasesi la branche que vous rebasez n'a pas été publiée (et utilisée par d'autres personnes). Sinon, utilisez merge. Si vous rebasez des branches déjà publiées (et utilisées), vous devez coordonner un complot pour réécrire l'historique de tous les développeurs qui ont utilisé votre branche.
Mikko Rantalainen
1
Malheureusement je n'ai pas lu ce message avant de faire le git rebase master...
Vitaly Isaev
Si je fais git rebase master alors que sur la branche 'foobar' alors techniquement foobar est divergé de origin / foobar jusqu'à ce que je fasse un git push -f, non?
git reset --hard origin/my_remote_tracking_branchest ce qui a vraiment fonctionné
roothahn
24
Dans mon cas, voici ce que j'ai fait pour provoquer le message divergé : je l'ai fait git pushmais j'ai ensuite git commit --amendajouté quelque chose au message de validation. Ensuite, j'ai également fait un autre commit.
Dans mon cas, cela signifiait simplement que l'origine / le maître était obsolète. Parce que je savais que personne d'autre ne touchait origine / maître, la correction était triviale: git push -f (où -fsignifie forcer)
+1 pour git push -fécraser les modifications précédemment validées et transmises à l'origine. Je suis également sûr que personne d'autre n'a touché le référentiel.
zacharydl
4
Commande très risquée. Veuillez écrire une brève information concernant le facteur de risque de la commande.
J4cK
1
@Trickster: J'avais déjà décrit le risque: "car je savais que personne d'autre ne touchait origine / maître". Je crois que, dans ce cas, ce n'est pas une commande risquée.
Darren Cook
1
Si quelqu'un commet sur master et qu'une personne exécute la commande git push -f alors c'est une commande à haut risque
J4cK
11
Dans mon cas, j'ai poussé les modifications vers origin/masterpuis j'ai réalisé que je n'aurais pas dû le faire :-( Cela a été compliqué par le fait que les modifications locales étaient dans un sous-arbre. Je suis donc retourné au dernier bon commit avant le "mauvais" local. changements (en utilisant SourceTree) puis j'ai reçu le "message de divergence".
Après avoir corrigé mon désordre localement (les détails ne sont pas importants ici), je voulais "remonter dans le temps" la origin/masterbranche distante afin qu'elle soit à nouveau synchronisée avec le local master. La solution dans mon cas était:
git push origin master -f
Notez l' -finterrupteur (force). Cela a supprimé les «mauvais changements» qui avaient été poussés origin/masterpar erreur et maintenant les branches locales et distantes sont synchronisées.
Veuillez garder à l'esprit qu'il s'agit d'une opération potentiellement destructrice. N'effectuez-la donc que si vous êtes sûr à 100% que "reculer" le maître distant à temps est OK.
Je sais qu'il y a beaucoup de réponses ici, mais je pense qu'il git reset --soft HEAD~1mérite une certaine attention, car cela vous permet de conserver les modifications dans le dernier commit local (non poussé) tout en résolvant l'état divergent. Je pense que c'est une solution plus polyvalente que de tirer avec rebase, car le commit local peut être revu et même déplacé vers une autre branche.
La clé utilise --soft, au lieu de la dure --hard. S'il y a plus d'un commit, une variation de HEAD~xdevrait fonctionner. Voici donc toutes les étapes qui ont résolu ma situation (j'ai eu 1 commit local et 8 commits dans la télécommande):
1)git reset --soft HEAD~1 pour annuler la validation locale. Pour les étapes suivantes, j'ai utilisé l'interface de SourceTree, mais je pense que les commandes suivantes devraient également fonctionner:
2)git stash pour cacher les modifications de 1). Maintenant, tous les changements sont sûrs et il n'y a plus de divergence.
3)git pull pour obtenir les modifications à distance.
4)git stash pop ou git stash applypour appliquer les dernières modifications cachées, suivies d'une nouvelle validation, si vous le souhaitez. Cette étape est facultative, avec 2) , lorsque vous souhaitez supprimer les modifications dans la validation locale. En outre, lorsque vous souhaitez vous engager dans une autre branche, cette étape doit être effectuée après le passage à la branche souhaitée.
Cela affichera les changements ou les différences entre les deux branches. Dans araxis (My favorite), il l'affiche dans un style de dossier différent. Affichage de chacun des fichiers modifiés. Je peux ensuite cliquer sur un fichier pour voir les détails des modifications dans le fichier.
Dans mon cas, cela a été causé par le fait de ne pas avoir engagé ma résolution de conflit.
Le problème est dû à l'exécution de la git pullcommande. Des changements d'origine ont entraîné des conflits avec mon référentiel local, que j'ai résolu. Cependant, je ne les ai pas commis. La solution à ce stade est de valider les modifications ( git commitle fichier résolu)
Si vous avez également modifié certains fichiers depuis la résolution du conflit, la git statuscommande affichera les modifications locales en tant que modifications locales non étagées et fusionnera la résolution en tant que modifications locales étagées. Cela peut être résolu correctement en validant les modifications de la fusion d'abord par git commit, puis en ajoutant et en validant les modifications non programmées comme d'habitude (par exemple par git commit -a).
J'ai eu le même message lorsque j'essayais de modifier le dernier message de validation, de validation déjà poussée, en utilisant: git commit --amend -m "New message"
Lorsque j'ai poussé les modifications en utilisant, git push --force-with-lease repo_name branch_name
il n'y avait aucun problème.
Réponses:
Vous pouvez revoir les différences avec:
avant de le tirer (fetch + merge) (voir aussi "Comment faire pour que git tire toujours depuis une branche spécifique?" )
Lorsque vous avez un message comme:
, vérifiez si vous devez mettre à jour
origin
. Siorigin
est à jour, certaines validations ont été transféréesorigin
depuis un autre référentiel pendant que vous effectuez vos propres validations localement.Vous avez basé le commit C sur le commit A car c'était le dernier travail que vous aviez récupéré en amont à l'époque.
Cependant, avant que vous n'essayiez de repousser à l'origine, quelqu'un d'autre a poussé la validation B.
L'historique du développement a divergé dans des chemins distincts.
Vous pouvez ensuite fusionner ou rebaser. Voir Pro Git: Git Branching - Rebasing pour plus de détails.
Fusionner
Utilisez la commande git merge:
Cela indique à Git d'intégrer les modifications de
origin/master
dans votre travail et de créer un commit de fusion.Le graphique de l'histoire ressemble maintenant à ceci:
La nouvelle fusion, commit M, a deux parents, chacun représentant un chemin de développement qui a conduit au contenu stocké dans ce commit.
Notez que l'historique derrière M est désormais non linéaire.
Rebase
Utilisez la commande git rebase:
Cela indique à Git de rejouer la validation C (votre travail) comme si vous l'aviez basée sur la validation B au lieu de A. Les utilisateurs
CVS et Subversion rebasinent régulièrement leurs modifications locales au-dessus du travail en amont lorsqu'ils mettent à jour avant la validation.
Git ajoute simplement une séparation explicite entre les étapes de validation et de rebase.
Le graphique de l'histoire ressemble maintenant à ceci:
Commit C 'est un nouveau commit créé par la commande git rebase.
Il diffère de C de deux manières:
Notez que l'histoire derrière C 'est toujours linéaire.
Nous avons choisi (pour l'instant) de n'autoriser que l'histoire linéaire dans
cmake.org/cmake.git
.Cette approche préserve le workflow basé sur CVS utilisé précédemment et peut faciliter la transition.
Une tentative de pousser C 'dans notre référentiel fonctionnera (en supposant que vous avez des autorisations et que personne n'a poussé pendant que vous rebasiez).
La commande git pull fournit un moyen raccourci pour récupérer à partir de l'origine et rebaser le travail local dessus:
Ceci combine les étapes de récupération et de rebase ci-dessus en une seule commande.
la source
git reset --hard HEAD
ne ferait que supprimer toute modification non indexée commis locale, et ne ferait rien pour concilier les différences entre les locaux et distants commits . Seule une fusion ou un rebase rapprochera les deux ensembles de commits (le local et le distant).master
montrerB
votre exemple.git reset --hard origin/master
comme mentionné dans la réponse ci-dessous: stackoverflow.com/a/8476004/6309J'ai eu cela et je suis mystifié de ce qui l'a causé, même après avoir lu les réponses ci-dessus. Ma solution était de faire
Ensuite, cela réinitialise simplement ma copie (locale) de master (que je suppose vissée) au bon point, comme représenté par origine / master (distant).
la source
git reflog
ou les voir dedansgitk --all
. Mais pourtant, bien sûr, la réinitialisation matérielle est autre chose qu'un rebase.est une commande unique qui peut vous aider la plupart du temps.
Modifier: extrait les validations de l'origine / du masque et applique vos modifications à l'historique de branche nouvellement extrait.
la source
Je me suis retrouvé dans cette situation lorsque j'ai essayé de rebaser une branche qui suivait une branche distante, et j'essayais de la rebaser sur master. Dans ce scénario, si vous essayez de rebaser, vous trouverez très probablement que votre branche a divergé et cela peut créer un gâchis qui n'est pas pour les git nubees!
Disons que vous êtes sur la branche my_remote_tracking_branch, qui a été branchée à partir de master
Et maintenant, vous essayez de rebaser du maître en tant que:
ARRÊTEZ MAINTENANT et épargnez-vous des ennuis! Utilisez plutôt la fusion comme:
Oui, vous vous retrouverez avec des commits supplémentaires sur votre branche. Mais à moins que vous ne souhaitiez des branches "non divergentes", ce sera un flux de travail beaucoup plus fluide que le rebasage. Voir ce blog pour une explication beaucoup plus détaillée.
D'un autre côté, si votre branche est uniquement une branche locale (c'est-à-dire qu'elle n'est pas encore envoyée à une télécommande), vous devez certainement faire un rebase (et votre branche ne divergera pas dans ce cas).
Maintenant , si vous lisez ceci parce que vous avez déjà êtes dans un scénario « divergé » en raison de ce changement de base, vous pouvez revenir à la dernière validation d'origine ( par exemple dans un état divergé non) en utilisant:
la source
rebase
si la branche que vous rebasez n'a pas été publiée (et utilisée par d'autres personnes). Sinon, utilisezmerge
. Si vous rebasez des branches déjà publiées (et utilisées), vous devez coordonner un complot pour réécrire l'historique de tous les développeurs qui ont utilisé votre branche.git rebase master
...git reset --hard origin/my_remote_tracking_branch
est ce qui a vraiment fonctionnéDans mon cas, voici ce que j'ai fait pour provoquer le message divergé : je l'ai fait
git push
mais j'ai ensuitegit commit --amend
ajouté quelque chose au message de validation. Ensuite, j'ai également fait un autre commit.Dans mon cas, cela signifiait simplement que l'origine / le maître était obsolète. Parce que je savais que personne d'autre ne touchait origine / maître, la correction était triviale:
git push -f
(où-f
signifie forcer)la source
git push -f
écraser les modifications précédemment validées et transmises à l'origine. Je suis également sûr que personne d'autre n'a touché le référentiel.Dans mon cas, j'ai poussé les modifications vers
origin/master
puis j'ai réalisé que je n'aurais pas dû le faire :-( Cela a été compliqué par le fait que les modifications locales étaient dans un sous-arbre. Je suis donc retourné au dernier bon commit avant le "mauvais" local. changements (en utilisant SourceTree) puis j'ai reçu le "message de divergence".Après avoir corrigé mon désordre localement (les détails ne sont pas importants ici), je voulais "remonter dans le temps" la
origin/master
branche distante afin qu'elle soit à nouveau synchronisée avec le localmaster
. La solution dans mon cas était:Notez l'
-f
interrupteur (force). Cela a supprimé les «mauvais changements» qui avaient été poussésorigin/master
par erreur et maintenant les branches locales et distantes sont synchronisées.Veuillez garder à l'esprit qu'il s'agit d'une opération potentiellement destructrice. N'effectuez-la donc que si vous êtes sûr à 100% que "reculer" le maître distant à temps est OK.
la source
You are not allowed to force push code to a protected branch on this project.
. J'essaye de pousser jusqu'à ma fourchette.Je sais qu'il y a beaucoup de réponses ici, mais je pense qu'il
git reset --soft HEAD~1
mérite une certaine attention, car cela vous permet de conserver les modifications dans le dernier commit local (non poussé) tout en résolvant l'état divergent. Je pense que c'est une solution plus polyvalente que de tirer avecrebase
, car le commit local peut être revu et même déplacé vers une autre branche.La clé utilise
--soft
, au lieu de la dure--hard
. S'il y a plus d'un commit, une variation deHEAD~x
devrait fonctionner. Voici donc toutes les étapes qui ont résolu ma situation (j'ai eu 1 commit local et 8 commits dans la télécommande):1)
git reset --soft HEAD~1
pour annuler la validation locale. Pour les étapes suivantes, j'ai utilisé l'interface de SourceTree, mais je pense que les commandes suivantes devraient également fonctionner:2)
git stash
pour cacher les modifications de 1). Maintenant, tous les changements sont sûrs et il n'y a plus de divergence.3)
git pull
pour obtenir les modifications à distance.4)
git stash pop
ougit stash apply
pour appliquer les dernières modifications cachées, suivies d'une nouvelle validation, si vous le souhaitez. Cette étape est facultative, avec 2) , lorsque vous souhaitez supprimer les modifications dans la validation locale. En outre, lorsque vous souhaitez vous engager dans une autre branche, cette étape doit être effectuée après le passage à la branche souhaitée.la source
pull --rebase
serait caché automatiquement de toute façon. stackoverflow.com/a/30209750/6309Pour voir les différences:
git difftool --dir-diff master origin/master
Cela affichera les changements ou les différences entre les deux branches. Dans araxis (My favorite), il l'affiche dans un style de dossier différent. Affichage de chacun des fichiers modifiés. Je peux ensuite cliquer sur un fichier pour voir les détails des modifications dans le fichier.
la source
Dans mon cas, cela a été causé par le fait de ne pas avoir engagé ma résolution de conflit.
Le problème est dû à l'exécution de la
git pull
commande. Des changements d'origine ont entraîné des conflits avec mon référentiel local, que j'ai résolu. Cependant, je ne les ai pas commis. La solution à ce stade est de valider les modifications (git commit
le fichier résolu)Si vous avez également modifié certains fichiers depuis la résolution du conflit, la
git status
commande affichera les modifications locales en tant que modifications locales non étagées et fusionnera la résolution en tant que modifications locales étagées. Cela peut être résolu correctement en validant les modifications de la fusion d'abord pargit commit
, puis en ajoutant et en validant les modifications non programmées comme d'habitude (par exemple pargit commit -a
).la source
J'ai eu le même message lorsque j'essayais de modifier le dernier message de validation, de validation déjà poussée, en utilisant:
git commit --amend -m "New message"
Lorsque j'ai poussé les modifications en utilisant,git push --force-with-lease repo_name branch_name
il n'y avait aucun problème.la source
J'ai rencontré ce problème lorsque j'ai créé une branche basée sur la branche A par
puis je mets le flux ascendant de la branche a à la branche d'origine B par
Ensuite, j'ai reçu le message d'erreur ci-dessus.
Une façon de résoudre ce problème pour moi était,
la source