Как мне сделать «git fetch» ​​и «git merge» из удаленной ветки отслеживания (например, «git pull») - PullRequest
111 голосов
/ 08 апреля 2010

Я настроил несколько удаленных веток отслеживания в git, но мне кажется, что я никогда не смогу объединить их с локальной веткой, как только я обновил их с помощью 'git fetch'.

Например, предположим, что у меня есть удаленная ветвь, называемая an-other-branch. Я настроил это локально как ветвь отслеживания, используя

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

Пока все хорошо. Но если эта ветка обновляется (как правило, я перемещаю машину и выполняю коммит с этой машины), и я хочу обновить ее на исходной машине, у меня возникают проблемы с fetch / merge:

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

Всякий раз, когда я делаю это, я получаю сообщение «Уже обновлено» и ничего не сливается.

Однако,

git pull origin an-other-branch

всегда обновляет его, как и следовало ожидать.

Также работает git diff

git diff origin/an-other-branch

показывает, что есть различия, поэтому я думаю, что у меня неправильный синтаксис.

Что я делаю не так?

РЕДАКТИРОВАТЬ [2010-04-09]: Я проверял пару раз, и я определенно не в другой ветке. Должен ли мой 'git fetch' с последующим 'git merge' (как показано выше) делать то же самое, что и git pull? Я получу некоторый рабочий процесс, показывающий результаты состояния git и т. Д.

Ответы [ 5 ]

166 голосов
/ 08 апреля 2010

Вы не получаете ветку, вы получаете весь пульт:

git fetch origin
git merge origin/an-other-branch
67 голосов
/ 18 января 2011

Выбор только одной ветви: fetch / merge против pull

Люди часто советуют вам отделить «извлечение» от «слияния». Вместо этого они говорят:

    git pull remoteR branchB

сделать это:

    git fetch remoteR
    git merge remoteR branchB

Что они не упоминают, так это то, что такая команда извлечения фактически извлечет все ветви из удаленного репозитория, что является не тем, что делает эта команда извлечения. Если у вас есть тысячи филиалов в удаленном репо, но вы не хотите видеть их все, вы можете выполнить эту неясную команду:

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

Конечно, это нелепо трудно запомнить, поэтому, если вы действительно хотите избежать выборки всех веток, лучше изменить .git/config, как описано в ProGit.

А?

Лучшее объяснение всего этого - в главе 9-5 ProGit, Git Internals - Refspec ( или via github ). Это невероятно трудно найти через Google.

Во-первых, нам нужно прояснить некоторую терминологию. Для отслеживания удаленных веток обычно нужно знать о трех разных ветках:

  1. Филиал на удаленном репо: refs/heads/branchB внутри другого репо
  2. Ваша ветка удаленного слежения : refs/remotes/remoteR/branchB in ваше репо
  3. Ваш собственный филиал: refs/heads/branchB внутри ваш репо

Ветви удаленного отслеживания (в refs/remotes) доступны только для чтения. Вы не изменяете их напрямую. Вы изменяете свою собственную ветку, а затем нажимаете на соответствующую ветку в удаленном репо. Результат не отражается в вашем refs/remotes до соответствующего извлечения или извлечения. Мне было трудно понять это различие из man-страниц git, главным образом потому, что локальная ветвь (refs/heads/branchB), как говорят, «отслеживает» ветку удаленного отслеживания, когда .git/config определяет branch.branchB.remote = remoteR.

Думайте о 'refs' как о указателях C ++. Физически это файлы, содержащие SHA-дайджесты, но в основном это просто указатели на дерево коммитов. git fetch добавит много узлов в ваше дерево коммитов, но то, как git решает, какие указатели перемещать, немного сложнее.

Как уже упоминалось в другом ответе , ни

    git pull remoteR branchB

ни

    git fetch remoteR branchB

будет двигаться refs/remotes/branches/branchB, и последний, конечно, не может двигаться refs/heads/branchB. Однако оба ходят FETCH_HEAD. (Вы можете cat любой из этих файлов внутри .git/, чтобы увидеть, когда они изменятся.) И git merge будет ссылаться на FETCH_HEAD при настройке MERGE_ORIG, и т. Д.

9 голосов
/ 08 апреля 2010

Вы уверены, что находитесь на локальном an-other-branch при слиянии?

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

Другое объяснение :

все изменения из ветви, которую вы пытаетесь объединить, уже объединены с веткой, в которой вы находитесь.
Более конкретно, это означает, что ветвь, которую вы пытаетесь объединить, является родительской для вашей текущей ветки

если вы опережаете удаленное репо на один коммит, это устаревшее удаленное репо, а не вы.

Но в вашем случае, если git pull работает, это просто означает, что вы не на правильной ветке.

3 голосов
/ 08 апреля 2010

Git pull - это на самом деле комбинированный инструмент: он запускает git fetch (получает изменения) и git merge (объединяет их с текущей копией)

Вы уверены, что находитесь на правильной ветке?

1 голос
/ 21 июля 2013

это команды:

git fetch origin
git merge origin/somebranch somebranch

если вы делаете это во второй строке:

git merge origin somebranch

попытается объединить локального мастера с вашей текущей веткой.

Вопрос, насколько я понял, состоял в том, что вы уже получили локально и хотите объединить свою ветку с самой последней из той же ветки.

...