Comment puis-je 'git fetch' et 'git merge' à partir d'une branche de suivi à distance (comme 'git pull')

111

J'ai mis en place des branches de suivi à distance dans git, mais je ne semble jamais être en mesure de les fusionner dans la branche locale une fois que je les ai mises à jour avec 'git fetch'.

Par exemple, supposons que j'ai une branche distante appelée «an-other-branch». Je l'ai configuré localement en tant que branche de suivi en utilisant

git branch --track an-other-branch origin/an-other-branch

Jusqu'ici tout va bien. Mais si cette branche est mise à jour (généralement en déplaçant la machine et en m'engageant à partir de cette machine), et que je souhaite la mettre à jour sur la machine d'origine, je rencontre des problèmes avec l'extraction / fusion:

git fetch origin an-other-branch
git merge origin/an-other-branch

Chaque fois que je fais cela, j'obtiens un message «Déjà à jour» et rien ne fusionne.

Cependant, un

git pull origin an-other-branch

le met toujours à jour comme prévu.

Aussi, exécuter git diff

git diff origin/an-other-branch

montre qu'il y a des différences, donc je pense que ma syntaxe est erronée.

Qu'est-ce que je fais mal?

EDIT [2010-04-09]: J'ai vérifié plusieurs fois, et je ne suis certainement pas sur une branche différente. Mon 'git fetch' suivi d'un 'git merge' (comme indiqué ci-dessus) devrait-il faire exactement la même chose qu'un git pull? Je vais avoir un flux de travail montrant les résultats d'un statut git, etc.

Kaybenleroll
la source

Réponses:

170

Vous ne récupérez pas une branche, vous récupérez une télécommande entière:

git fetch origin
git merge origin/an-other-branch
Gareth
la source
8
Plus de détails: git fetch origin an-other-branchstocke la pointe récupérée dans FETCH_HEAD, mais pas origin/an-other-branch(c'est-à-dire la «branche de suivi à distance» habituelle). Donc, on pourrait faire git fetch origin an-other-branch && git merge FETCH_HEAD, mais le faire comme @Gareth le dit est mieux (ou simplement utiliser git pull ).
Chris Johnsen
donc si l'origine a 1000 succursales, vous auriez une succursale distante pour toutes?
Gauthier
4
Sûr. Si j'ai ajouté un référentiel distant avec 1000 branches au mien, et que je demande quelles branches la télécommande a, il vaut mieux m'en donner 1000
Gareth
va git merge origin/an-other-branchfusionner origin/an-other-branchdans toutes les branches locales qui sont configurées pour le suivre? comment puis-je fusionner dans une seule succursale locale?
amphibient le
1
Alors, que fait git pull(sans arguments) - quelle branche fusionne-t-elle? Fusionne-t-il la branche de suivi à distance correspondant à la branche actuelle ?
The Red Pea
69

Sélection d'une seule branche: fetch/ merge vs. pull

Les gens vous conseillent souvent de séparer "récupération" de "fusion". Ils disent au lieu de ceci:

    git pull remoteR branchB

faites ceci:

    git fetch remoteR
    git merge remoteR branchB

Ce qu'ils ne mentionnent pas, c'est qu'une telle commande d'extraction récupérera en fait toutes les branches du dépôt distant, ce qui n'est pas ce que fait cette commande d'extraction. Si vous avez des milliers de branches dans le référentiel distant, mais que vous ne voulez pas les voir toutes, vous pouvez exécuter cette commande obscure:

    git fetch remoteR refs/heads/branchB:refs/remotes/remoteR/branchB
    git branch -a  # to verify
    git branch -t branchB remoteR/branchB

Bien sûr, c'est ridiculement difficile à retenir, donc si vous voulez vraiment éviter de récupérer toutes les branches, il est préférable de modifier votre .git/configcomme décrit dans ProGit.

Hein?

La meilleure explication de tout cela se trouve dans le chapitre 9-5 de ProGit, Git Internals - The Refspec ( ou via github ). C'est incroyablement difficile à trouver via Google.

Premièrement, nous devons clarifier une certaine terminologie. Pour le suivi des branches distantes, il y a généralement 3 branches différentes à connaître:

  1. La branche sur le repo distant: refs/heads/branchBà l'intérieur de l'autre repo
  2. Votre agence de suivi à distance : refs/remotes/remoteR/branchBdans votre repo
  3. Votre propre agence: refs/heads/branchBdans votre repo

Les branches de suivi à distance (in refs/remotes) sont en lecture seule. Vous ne les modifiez pas directement. Vous modifiez votre propre branche, puis vous poussez vers la branche correspondante dans le dépôt distant. Le résultat n'est reflété dans votre refs/remotesqu'après une extraction ou une récupération appropriée. Cette distinction était difficile pour moi à comprendre à partir des pages de manuel de git, principalement parce que la branche locale ( refs/heads/branchB) est censée "suivre" la branche de suivi à distance lorsqu'elle est .git/configdéfinie branch.branchB.remote = remoteR.

Considérez les «refs» comme des pointeurs C ++. Physiquement, ce sont des fichiers contenant des résumés SHA, mais en gros, ce ne sont que des pointeurs vers l'arborescence de commit. git fetchajoutera de nombreux nœuds à votre arbre de validation, mais comment git décide quels pointeurs déplacer est un peu compliqué.

Comme mentionné dans une autre réponse , ni

    git pull remoteR branchB

ni

    git fetch remoteR branchB

bougerait refs/remotes/branches/branchB, et ce dernier ne peut certainement pas bouger refs/heads/branchB. Cependant, les deux bougent FETCH_HEAD. (Vous pouvez catn'importe lequel de ces fichiers à l'intérieur .git/pour voir quand ils changent.) Et git mergese référera à FETCH_HEAD, lors du réglage MERGE_ORIG, etc.

cdunn2001
la source
1
Savez-vous que votre lien vers Git Internals est un lien vers cette même question?
Shahbaz
9

Êtes-vous sûr d'être sur le local an-other-branchlorsque vous fusionnez?

git fetch origin an-other-branch
git checkout an-other-branch
git merge origin/an-other-branch

L' autre explication :

toutes les modifications de la branche que vous essayez de fusionner ont déjà été fusionnées dans 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

si vous êtes en avance sur le dépôt distant d'un commit, c'est le dépôt distant qui est obsolète, pas vous.

Mais dans votre cas, si cela git pullfonctionne, cela signifie simplement que vous n'êtes pas sur la bonne branche.

VonC
la source
3

Git pull est en fait un outil combo: il exécute git fetch (obtenir les modifications) et git merge (les fusionner avec votre copie actuelle)

Êtes-vous sûr d'être sur la bonne branche?

RDL
la source
Je pense que l'OP est en diff. branche, m'arrive.
Chaklader Asfak Arefe
1

ce sont les commandes:

git fetch origin
git merge origin/somebranch somebranch

si vous faites cela sur la deuxième ligne:

git merge origin somebranch

il essaiera de fusionner le maître local dans votre branche actuelle.

La question, telle que je l'ai comprise, était que vous avez déjà récupéré localement et que vous souhaitez maintenant fusionner votre branche avec la dernière de la même branche.

user1524957
la source