Git Merge rapporte «Déjà à jour» bien qu'il y ait une différence

286

J'ai un dépôt git avec 2 branches: master et test.

Il existe des différences entre les branches maître et test.

Les deux branches ont tous les changements engagés.

Si je fais:

git checkout master
test git diff

Un écran plein de changements apparaît montrant les différences. Je veux fusionner les modifications dans la branche de test et faire de même:

test de fusion git

Mais obtenez le message "Déjà à jour"

Cependant, l'examen des fichiers sous chaque branche différente montre clairement des différences.

Quel est le problème ici et comment le résoudre?

Charles Darke
la source
Avez-vous du code modifié non engagé?
ozma
Est-ce que cela répond à votre question? Pourquoi Git dit que ma branche principale est "déjà à jour" alors qu'elle ne l'est pas?
Michael Freidgeim

Réponses:

146

Le message «Déjà à jour» signifie que toutes les modifications de la branche que vous essayez de fusionner ont déjà été fusionnées avec la branche sur laquelle vous vous trouvez actuellement. Plus précisément, cela signifie que la branche que vous essayez de fusionner est un parent de votre branche actuelle . Félicitations, c'est la fusion la plus simple que vous puissiez faire. :)

Utilisez gitkpour jeter un œil à votre référentiel. L'étiquette de la branche «test» doit se trouver quelque part sous votre étiquette de branche «maître».

Votre succursale est à jour par rapport à son parent. Selon la fusion, il n'y a pas de nouveaux changements dans le parent depuis la dernière fusion. Cela ne signifie pas que les branches sont les mêmes, car vous pouvez avoir beaucoup de changements dans votre branche de travail et cela ressemble à vous.

Modifier le 10/12/2019:

Selon Charles Drake dans le commentaire de cette réponse, une solution pour résoudre le problème est:

git checkout master
git reset --hard test

Cela le ramène au niveau «test».

Alors fais:

git push --force origin master

afin de forcer le retour au référentiel central.

Bombe
la source
2
Holy cr * p! Vous avez raison! Je pense que ce qui s'est passé est qu'une autre branche (développement instable) a été incorrectement fusionnée avec master et la branche de test était un sous-ensemble d'instable. La fusion que j'essayais de faire était de ramener le maître au niveau «test».
Charles Darke
2
Droite. Cette opération n'aurait aucun sens, alors Git refuse de faire quoi que ce soit. :)
Bombe
24
Ce que j'ai fait maintenant, c'est: git checkout master; git reset --hard test; Cela le ramène au niveau «test». J'ai ensuite fait un "git push --force origin master" pour forcer les modifications au repo central.
Charles Darke
22
Cela aurait été bien si git avait un avertissement pour dire "essayer de fusionner avec le parent".
Charles Darke
1
Pousser une branche qui n'est pas une descendante de la branche déjà existante du côté distant est considéré comme une mauvaise chose: voir les discussions sur les pages de manuel pour git-push et git-pull.
Bombe
131

Cela m'arrive souvent lorsque je sais qu'il y a des changements sur le maître distant, donc j'essaye de les fusionner en utilisant git merge master. Cependant, cela ne fusionne pas avec le maître distant, mais avec votre maître local.

Donc, avant de faire la fusion, passez à la caisse, puis git pulllà. Ensuite, vous pourrez fusionner les nouvelles modifications dans votre branche.

ACarter
la source
7
Existe-t-il un moyen d'éviter le changement de branche, quelque chose comme faire une traction de la branche à fusionner tout en restant dans la branche à fusionner, puis fusionner?
Japheth Ongeri - inkalimeva
Ahh, chouette. Je pensais que cela git fetchmettrait à jour la branche principale même si je suis actuellement sur une autre. Il s'avère que non. Merci! Je suis sûr qu'il existe une option fetchqui vous permet de spécifier la branche à obtenir.
Raik
1
@Raik Vous pouvez le faire git fetch --all, mais cela ne récupère que les branches, il ne les tire pas.
Ingo Bürk
6
@ JaphethOngeri-inkalimeva Vous pouvez simplement le faire git fetch --all && git merge origin/master. Pas besoin de mettre à jour votre local masterpour fusionner les modifications à distance.
Ingo Bürk
@ IngoBürk J'avais 2 succursales, mis à jour 1 avec git merge masteret 1 avec git merge origin/master. J'avais également vérifié masteret git pullavant de mettre à jour 2 succursales. même s'ils partageaient le même contenu, la création d'un PR entre les 2 branches montrait quelques fichiers diff. J'ai corrigé par git pullla branche cible dans la branche de fonctionnalité, ce qui a montré: Already up to date! Merge made by the 'recursive' strategy.cela a entraîné la validation de la fusion sans changement, mais a supprimé les fichiers diff inattendus de PR. une idée de la raison pour laquelle il existe une différence entre la fusion de branches locales et distantes "équivalentes"?
wrapperapps
45

Supposons que vous ayez une branche masteravec l'historique de validation suivant:

A -- B -- C -- D

Maintenant, vous créez un test de branche, travaillez dessus et effectuez 4 validations:


                 E -- F -- G -- H
                /
A -- B -- C -- D

masterla tête pointe vers D et testla tête pointe vers H.

Le message "Déjà à jour" s'affiche lorsque le HEAD de la branche dans laquelle vous fusionnez est un parent de la chaîne de validations de la branche que vous souhaitez fusionner. C'est le cas, ici: Dest un parent de E.

Il n'y a rien à la fusion de testla master, puisque rien n'a changé sur masterdepuis. Ce que vous voulez faire ici est littéralement de dire à Git d'avoir masterla tête de pointer vers H, donc la branche master a l'historique des validations suivant:

A -- B -- C -- D -- E -- F -- G -- H

Il s'agit d'un travail pour la commande Git reset. Vous souhaitez également que le répertoire de travail reflète cette modification, vous effectuerez donc une réinitialisation matérielle :

git reset --hard H
Marek Stanley
la source
3
On m'a dit dans le passé que l'utilisation git reset --hardest une chose assez drastique à faire, peut-elle perdre des commits? Existe-t-il un moyen plus sûr d'apporter ces changements, ou les dangers sont-ils git reset --hardexagérés?
Graham R. Armstrong
1
Cette commande est sensée, pas de soucis. Je dirais que la seule chose à laquelle faire attention avec l' --hardoption est le fait qu'elle modifie réellement votre répertoire de travail, et par conséquent, vous perdez les modifications non validées. Personnellement, je fais git statusavant et après chaque commande git exécutée manuellement pour m'assurer que mon dépôt est propre ou dans l'état attendu.
Marek Stanley
cela produira un message d'état "Votre succursale et 'origine / maître' ont divergé", comment puis-je le résoudre?
Eido95
1
J'aimerais pouvoir vous donner plus d'un vote positif. Merci!
KMC
Y a-t-il un besoin pour l' --hardoption? J'ai été dans cette situation plusieurs fois maintenant et toujours réinitialisé sans --hard. Cela a très bien fonctionné sans risque de perdre des modifications non validées.
Casimir
16

Ce qui fonctionne pour moi, disons que vous avez branch1 et que vous voulez le fusionner dans branch2.

Vous ouvrez la ligne de commande git allez dans le dossier racine de branch2 et tapez:

git checkout branch1
git pull branch1
git checkout branch2
git merge branch1
git push

Si vous avez des conflits, vous n'avez pas besoin de faire git push, mais d'abord résoudre les conflits, puis pousser.

Stefan Pintilie
la source
6

Une fusion est toujours entre le HEAD en cours et un ou plusieurs commits (généralement, tête de branche ou balise),
et le fichier d'index doit correspondre à l'arborescence du commit HEAD (c'est-à-dire le contenu du dernier commit) au début.
En d'autres termes, ne git diff --cached HEADdoit signaler aucun changement.

Le commit fusionné est déjà contenu dans HEAD. Il s'agit du cas le plus simple, appelé "Déjà à jour".

Cela devrait signifier que les validations dans test sont déjà fusionnées dans master, mais comme d'autres validations sont effectuées sur master, git diff testcela donnerait quand même quelques différences.

VonC
la source
6

Cela se produit car votre copie locale de la branche que vous souhaitez fusionner est obsolète. J'ai ma succursale appelée MyBranchet je veux la fusionner ProjectMaster.

_>git status
On branch MyBranch-Issue2
Your branch is up-to-date with 'origin/MyBranch-Issue2'.

nothing to commit, working tree clean

_>git merge ProjectMaster
Already up-to-date.

Mais je sais qu'il y a des changements à fusionner!

Voici la chose, quand je tape git merge ProjectMaster, git regarde ma copie locale de cette branche, qui n'est peut-être pas à jour . Si oui en utilisant, euh, pour voir si tel est le cas, je dis d' abord Git pour vérifier et voir si mes branches sont à jour et les modifications aille chercher fetch. Ensuite, je saute dans la branche que je veux fusionner pour voir ce qui s'y passe ...

_>git fetch origin

_>git checkout ProjectMaster
Switched to branch ProjectMaster
**Your branch is behind 'origin/ProjectMaster' by 85 commits, and can be fast-forwarded.**
  (use "git pull" to update your local branch)

Ah-ha! Ma copie locale est périmée par 85 commits, cela explique tout! Maintenant, je Pullnote les modifications qui me manquent, puis je rejoins MyBranchla tentative de fusion.

_>git pull
Updating 669f825..5b49912
Fast-forward

_>git checkout MyBranch-Issue2
Switched to branch MyBranch-Issue2
Your branch is up-to-date with 'origin/MyBranch-Issue2'.

_>git merge ProjectMaster
Auto-merging Runbooks/File1.ps1
CONFLICT (content): Merge conflict in Runbooks/Runbooks/File1.ps1

Automatic merge failed; fix conflicts and then commit the result.

Et maintenant, j'ai un autre problème à résoudre ...

FoxDeploy
la source
5

Cela m'est arrivé parce que GIT pensait étrangement que la branche locale était différente de la branche distante. Cela était visible dans le graphique des branches: il affichait deux branches différentes: télécommandes / origine / nom_branche et nom_branche.

La solution consistait simplement à supprimer le dépôt local et à le recloner à distance. De cette façon, GIT comprendrait que les télécommandes / origin / branch_name> et branch_name sont en effet les mêmes, et je pourrais émettre le git merge branch_name.

rm <my_repo>
git clone <my_repo>
cd <my_repo>
git checkout <branch_name>
git pull
git checkout master
git merge <branch_name>
cdupont
la source
N'est-ce pas exactement la même réponse que celle d'Acarter?
Andrew C
Je pense qu'Acarter a en fait manqué le point - il n'y a eu aucun changement sur la télécommande - ce n'était pas du tout le problème. J'avais besoin de "git checkout master" puis "git merge <branch_name>" pour forcer la fusion rapide. L'inverse n'a rien fait puisque la branche était en avance sur le maître. La réponse de Bombe est une belle explication mais n'a jamais répondu à la partie "comment le résoudre" de la question.
MrMas
5

git merge origin/mastera plutôt git merge masterfonctionné pour moi. Donc, pour fusionner le maître dans la branche de fonctionnalité, vous pouvez utiliser:

git checkout feature_branch
git merge origin/master
Tout comme
la source
5

Assurez-vous de vérifier d'abord la branche que vous souhaitez fusionner, puis tirez-la (pour que votre version locale corresponde à la version distante).

Ensuite, passez à la succursale dans laquelle vous souhaitez effectuer la fusion et votre fusion Git devrait fonctionner.

John Murphy
la source
1
C'était tout pour moi - j'ai fait un pull alors que j'étais maître; j'ai appris que j'avais de nouveaux commits dans "branch". J'ai essayé de fusionner "branche" en maître - "Déjà à jour". Did git checkout "branch" - got "Your branch is behind ... and can be fast-forwarded.", git pull
That means I need
3

est arrivé à moi et a été envoyé sur cette page, je ne sais pas si j'avais le même scénario, mais le mien était moi essayant de "re-fusionner" cette branche "test".

J'ai donc précédemment fusionné mais j'exclus intentionnellement certains changements spécifiques lors de cette fusion, il a donc clairement des différences entre les branches. J'essayais alors de le refusionner parce que je me rends compte / oublie que j'aurais dû et voulais ajouter un changement / fichier particulier que j'ai précédemment exclu et j'espérais que si je refais une fusion montrerait tous les changements que j'avais exclus auparavant , mais je me suis trompé et je reçois à la place le message "Déjà à jour".

En lisant le commentaire / la réponse de @ Bombe, il a raison, et je pense que cela se comporte de cette façon, donc ce que j'ai fait était de faire une sauvegarde matérielle des fichiers sur la branche de test, puis de vérifier la branche principale et de coller manuellement les fichiers dedans et de les valider comme s'il s'agissait de nouveaux changements.

Je ne sais pas si c'est la bonne façon ou pourrait aider d'autres personnes ayant ce même problème, mais cela a apporté une solution à mon cas particulier.

bubjavier
la source
Même situation ici. Le scénario est que je souhaite diviser une branche "intégration" en plusieurs branches "fonction".
Yadli
2
Au lieu de la pâte manuelle, vous pouvez directement la caisse des fichiers d'une branche dans la branche actuelle: git checkout srcBranch -- path/to/file. Peut également utiliser des globes de fichiers.
Todd
Merci, j'ai utilisé votre méthode de paiement, mais j'ai mis checkout srcBranch -- *puis regardé mes différences
portforwardpodcast
2

Si la fusion de la branche A dans la branche B signale "Déjà à jour", l'inverse n'est pas toujours vrai. Ce n'est vrai que si la branche B est descendante de la branche A, sinon la branche B peut simplement avoir des changements qui ne sont pas dans A.

Exemple:

  1. Vous créez des branches A et B hors maître
  2. Vous effectuez quelques modifications dans le maître et fusionnez ces modifications uniquement dans la branche B (sans mettre à jour ou oublier de mettre à jour la branche A).
  3. Vous apportez quelques modifications dans la branche A et fusionnez A à B.

À ce stade, la fusion de A à B signale "Déjà à jour" mais les branches sont différentes car la branche B a des mises à jour du maître alors que la branche A n'en a pas.

Stan Bashtavenko
la source
2

Face à ce scénario en utilisant Git Bash.

Notre référentiel a plusieurs branches et chaque branche a un cycle de validation différent et la fusion se produit de temps en temps. Old_Branch a été utilisé comme parent pour New_Branch

Old_Branch a été mis à jour avec quelques modifications qui devaient être fusionnées avec New_Branch

J'utilisais la commande pull ci-dessous sans aucune branche pour obtenir toutes les sources de toutes les branches.

git pull origine

Étrangement, cela ne tire pas tous les commits de toutes les branches. Je l'avais pensé car l'indiqué montre presque toutes les branches et les balises.

Donc, pour résoudre ce problème, le Old_Branch a tiré la dernière en utilisant

git checkout Old_Branch

git pull origine Old_Branch

Maintenant vérifié New_Branch

git checkout New_Branch

Je l'ai tiré pour être sûr

git pull origine New_Branch

git merge Old_Branch

Et l'alto a des conflits à régler de Old_Branch à New_Branch :), ce qui était attendu

satlead
la source
0

La même chose m'est arrivée. Mais le scénario était un peu différent, j'avais une branche principale et j'en ai découpé release_1 (disons). Apporté quelques modifications dans la branche release_1 et fusionné en origine. puis j'ai fait ssh et sur le serveur distant, j'ai de nouveau extrait release_1 en utilisant la commande git checkout -b release_1 - qui crée en fait une nouvelle branche release_! du maître plutôt que de vérifier l'origine de la branche release_1 déjà existante. Résolu le problème en supprimant le commutateur "-b"

Deepika Anand
la source
0

J'ai eu le même problème. J'ai eu des changements dans la télécommande et elle montrait toujours "Déjà à jour". Recloner le référentiel a résolu le problème pour moi.

Mohammad Rayan
la source
0

C'est idiot mais ça pourrait arriver. Supposons que votre nom de branche soit préfixé avec une référence de problème (par exemple #91-fix-html-markup), si vous effectuez cette fusion:

$ git merge #91-fix-html-markup

cela ne fonctionnera pas comme prévu, car tout ce qui suit #est ignoré, car #démarre un commentaire en ligne.

Dans ce cas , vous pouvez renommer l'omission de branche #ou d' utiliser des guillemets simples pour entourer le nom de la branche: git merge '#91-fix-html-markup'.

Paolo
la source