web-dev-qa-db-fra.com

branche principale et "origine/maître" ont divergé, comment "dévier des branches"?

D'une manière ou d'une autre mon maître et mon origine/branche de maître ont divergé En fait, je ne veux pas qu'ils soient divergents. Comment puis-je voir ces différences et les "fusionner"?

794
Frank

Vous pouvez examiner les différences avec un:

git log HEAD..Origin/master

before en le tirant _ (chercher + fusionner) (voir aussi "Comment obtenez-vous qu'un git tire toujours d'une branche spécifique?" )


Quand vous avez un message comme:

"Votre branche et votre 'origine/maître' ont divergé, # et ont respectivement 1 et 1 commit (s) différent (s)."

, vérifiez si vous devez mettre à jour Origin . Si Origin est à jour, certains commits ont été poussés vers Origin à partir d'un autre référentiel pendant que vous effectuiez vos propres commits localement.

... o ---- o ---- A ---- B  Origin/master (upstream work)
                   \
                    C  master (your work)

Vous avez basé commit C sur commit A parce que c’était le dernier travail que vous aviez récupéré d’amont à l’époque.

Cependant, avant d'essayer de repasser à l'origine, quelqu'un d'autre a poussé le commit B.
L’histoire du développement a divergé en plusieurs chemins. 

Vous pouvez ensuite fusionner ou rebaser. Voir Pro Git: Git Branching - Rebasing pour plus de détails.

Fusionner

Utilisez la commande git merge:

$ git merge Origin/master

Cela indique à Git d'intégrer les modifications apportées par Origin/master à 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 ayant conduit au contenu stocké dans ce commit.

Notez que l'historique derrière M est maintenant non linéaire.

Rebase

Utilisez la commande git rebase:

$ git rebase Origin/master

Ceci dit à Git de rejouer commit C (votre travail) comme si vous l'aviez basé sur commit B au lieu de A.
Les utilisateurs de CVS et de Subversion modifient régulièrement leurs modifications locales par-dessus le travail en amont lorsqu’ils se mettent à jour avant la validation.
Git ajoute simplement une séparation explicite entre les étapes commit et 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 du C de deux manières:

  1. Il a une histoire différente: B au lieu de A.
  2. Son contenu rend compte des changements à la fois en B et en C; c'est le même que M de 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'historique linéaire dans cmake.org/cmake.git.
Cette approche préserve le flux de travail 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 ayez les permissions et que personne n’a poussé pendant que vous rebasonniez).

La commande git pull fournit un moyen rapide d'extraire de Origin et de rebaser le travail local sur celui-ci:

$ git pull --rebase

Cela combine les étapes d'extraction et de réabonnement ci-dessus en une seule commande. 

873
VonC

J'avais ceci 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 (ce qui, je suppose, est foutue) sur le bon point, comme représenté par Origin (remote) Origin/master.

WARNING: Vous perdrez toutes les modifications qui n'ont pas encore été poussées dans Origin/master.

561
skiphoppy
git pull --rebase Origin/master 

est une commande unique qui peut vous aider la plupart du temps.

Edit: Extrait les commits de Origin/master et applique vos modifications à l'historique de branche nouvellement extrait.

41
asitmoharna

Je me suis retrouvé dans cette situation lorsque j'ai essayé de rebaser une branche qui suivait une branche distante et que j'essayais de la rebaser sur master. Dans ce scénario, si vous essayez de vous rebaser, vous trouverez probablement votre branche divergente et elle peut créer un désordre qui ne concerne pas les nubees git!

Disons que vous êtes sur la branche my_remote_tracking_branch, qui est issue du maître

$ git status

# Sur la branche my_remote_tracking_branch

rien à commettre (répertoire de travail propre)

Et maintenant, vous essayez de vous rebaser de master en tant que:

maître git rebase

ARRÊTEZ MAINTENANT et épargnez-vous des ennuis! Au lieu de cela, utilisez fusionner comme:

maître de fusion

Oui, vous allez vous retrouver avec des commits supplémentaires sur votre branche. Mais à moins que vous ne souhaitiez des branches "non divergentes", le flux de travail sera beaucoup plus fluide que le changement de base. Voir ce blog pour une explication beaucoup plus détaillée.

Par contre, si votre branche n’est qu’une branche locale (c’est-à-dire qu’elle n’a pas encore été poussée vers une télécommande), vous devez absolument effectuer une rebase (et votre branche ne sera pas divergente dans ce cas ).

Maintenant, si vous lisez ceci parce que vous avez déjà are dans un scénario "divergé" en raison d'une telle rebase, vous pouvez revenir au dernier commit depuis Origin (c'est-à-dire dans un état non divergé) en utilisant:

réinitialisation de git - Hard Origin/my_remote_tracking_branch

27
paneer_tikka

Dans mon cas, voici ce que j’ai fait pour provoquer le message diverged message: j’ai fait git Push mais git commit --amend pour ajouter quelque chose au message commit. Puis j'ai aussi fait un autre commit.

Donc, dans mon cas, cela signifiait simplement que Origin/master était obsolète. Parce que je savais que personne ne touchait Origin/Master, le correctif était trivial: git Push -f (où -f signifie force)

20
Darren Cook

Dans mon cas, j'ai poussé les modifications vers Origin/master et ensuite réalisé que je n'aurais pas dû le faire. changements locaux (en utilisant SourceTree) et puis j'ai eu le "message de divergence".

Après avoir corrigé mes erreurs localement (les détails ne sont pas importants ici), je souhaitais "remonter dans le temps" la branche Origin/master distante afin qu'elle soit à nouveau synchronisée avec la variable locale master. La solution dans mon cas était:

git Push Origin master -f

Notez le commutateur -f (force). Cela supprimait les "modifications incorrectes" qui avaient été poussées par erreur sur Origin/master. Désormais, les branches locale et distante sont synchronisées.

N'oubliez pas qu'il s'agit d'une opération potentiellement destructive; ne l'exécutez donc que si vous êtes sûr à 100% que le "recul" du maître distant est correct.

6
Laryx Decidua

Je sais qu'il y a beaucoup de réponses ici, mais je pense que git reset --soft HEAD~1 mérite une attention particulière, car il vous permet de conserver les modifications dans le dernier local (non poussé) tout en résolvant l'état divergé. Je pense que cette solution est plus polyvalente que la méthode pull avec rebase, car le commit local peut être révisé et même déplacé vers une autre branche.

La clé utilise --soft, au lieu du --hard dur. S'il y a plus d'un commit, une variante de HEAD~x devrait fonctionner. Voici donc toutes les étapes qui ont résolu ma situation (j'avais 1 commit local et 8 commits dans la télécommande):

1) git reset --soft HEAD~1 pour annuler la validation locale. Pour les prochaines étapes, j'ai utilisé l'interface dans 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écurisés et il n'y a plus de divergence.

3) git pull pour obtenir les modifications à distance.

4) git stash pop ou git stash apply pour appliquer les dernières modifications cachées, suivies d'un nouveau commit, si vous le souhaitez. Cette étape est facultative, avec 2) , lorsque vous souhaitez supprimer les modifications apportées à la validation locale. En outre, lorsque vous souhaitez vous engager dans une autre branche, cette étape doit être effectuée après le basculement vers la branche souhaitée. 

4
Bianca D.

Pour 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 répertoire diff Affichage de chacun des fichiers modifiés. Je peux ensuite cliquer sur un fichier pour voir les détails des modifications dans le fichier.

4
C Johnson

Dans mon cas, cela était dû au fait que je ne résolvais pas le conflit.

Le problème était dû à l'exécution de la commande git pull. Les changements d'origine ont entraîné des conflits avec mon référant local, que j'ai résolus. 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 commande git status affiche les modifications locales en tant que modifications locales non mises en scène et fusionne la résolution en tant que modifications locales mises en scène. 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 mises en scène comme d'habitude (par exemple, par git commit -a). 

Rencontré ce problème lorsque j'ai créé une branche basée sur la branche A par

git checkout -b a

puis je règle le flux de la branche a jusqu'à la branche d'origine B par

git branch -u Origin/B

Ensuite, j'ai eu le message d'erreur ci-dessus.

Une façon de résoudre ce problème pour moi était,

  • Supprimer la branche a
  • Créer une nouvelle branche b par
git checkout -b b Origin/B
0
Shouheng Wang

J'avais le même message lorsque j'essayais de modifier le dernier message de validation, celui de la validation déjà envoyée, en utilisant: git commit --amend -m "New message" Lorsque j'ai transmis les modifications en utilisant git Push --force-with-lease repo_name branch_name.__, il n'y avait aucun problème.

0
LoveForDroid