Почему git fetch origin master: master переходит вперед по локальной ветке? - PullRequest
2 голосов
/ 16 июня 2019

Я играл с git и придерживался концепции git fetch.

Я пробовал и наблюдал следующие сценарии:

1) $ git fetch

Всеудаленные ветви выбираются, и все соответствующие ветви удаленного отслеживания обновляются.Я понимаю, что он просматривает файл .git / config и использует расположение удаленного репозитория по умолчанию и выборку по умолчанию refspec, которая обычно называется "refs / head / : refs / remotes / origin / ".Он не перематывает вперед ни одну локальную ветвь.

2) $ git fetch origin

Наблюдается так же, как 1)

3) $ git fetch origin master

Только мастерветвь извлекается и источник / мастер ветки удаленного отслеживания обновляется.Не ускоряет пересылку локальной ветки master.

4) $ git fetch origin master:master

Извлекается только ветвь master, а источник / master ветки удаленного отслеживания обновляется.Быстрая перемотка вперед местной ветки 'master'.

Понимание 1) и 2) было простым.Однако 3) и 4) меня смущает.

Какое отношение команда fetch имела к локальным ветвям?Почему это ускоряет пересылку в местное отделение?(Доказательством того, что это влияет на локальную ветвь, является попытка git fetch origin master:master, в то время как мастер-ветвь извлечена, выдает следующую ошибку: fatal: Refusing to fetch into current branch refs/heads/master of non-bare repository)

Согласно моей интуиции, при любом типе выборкиКоманда обновления веток удаленного отслеживания является поведением по умолчанию.Однако, когда git fetch origin master выполняется, он имеет дополнительное поведение обновления FETCH_HEAD.Когда git fetch origin master:master выполняется, он имеет дополнительное поведение обновления локальной ветки 'master'.Моя интуиция права?

Она интерпретирует git fetch origin master:master как git fetch origin refs/heads/master:refs/heads/master?(Может быть, излишним для моего предыдущего вопроса)

Он интерпретирует git fetch origin master как git fetch origin refs/heads/master:?

Ответы [ 2 ]

2 голосов
/ 16 июня 2019

Ответ RomainValeri является в основном правильным, но пропускает несколько пунктов.

Во-первых, мы должны отметить особый случай с версиями Git, предшествовавшими 1.8.4. В примечаниях к выпуску 1.8.4 упоминается, что

  • "мастер происхождения git fetch" в отличие от "git fetch origin" или "git fetch" не обновлял "refs / remotes/ происхождение / мастер ";Это было раннее решение, чтобы сохранить предсказуемость обновления веток удаленного отслеживания, но на практике оказывается, что людям удобнее своевременно обновлять их всякий раз, когда у нас есть такая возможность, и мы обновляли их, когда запускаем «git push»."который уже нарушает первоначальную" предсказуемость "в любом случае.

Следовательно:

git fetch origin master

ведет себя иначе в Git 1.8.3 и более ранних версиях.В 1.8.4 и более поздних версиях это обновляет refs/remotes/origin/master (по умолчанию, но это зависит от используемых вами по умолчанию ссылок на выборки).

Описание ссылки правильное, но отсутствует один элемент: в общем случае синтаксис:

  • необязательный начальный знак плюс +, указывающий --force (только для этой конкретной спецификации);
  • ссылка на источник;
  • разделитель :
  • ссылка на пункт назначения.

Как источник, так и пункт назначения могут быть полностью определены, например, refs/heads/master, или нет, например, master.Если вы используете неквалифицированный вариант, Git выяснит, если это возможно, полностью квалифицированное написание.

В общем, любой (или иногда даже оба) источника и получателя может быть опущен.Значение такого refspec различно для git fetch и git push.Для пропуска источника необходимо добавить двоеточие, а опускание пункта назначения позволяет также опустить двоеточие.То есть:

  • master:master, или branch1:branch2, или tag:tag и т. Д., Все обеспечивают источник и назначение.
  • master - источник безприемник.
  • master: также является источником без адресата.
  • :master является адресатом без источника.Это справедливо только для git push, где это означает, что просит, чтобы другие Git удалили свою ссылку. .
  • : указывает, что и источник, и пункт назначения опущены.Это действительно только для git push, где это означает, что находит соответствующие имена ветвей и нажимает на них .

Игнорируя git push, мы разрешаем только источник и пункт назначения,как в master:origin/master или master:master, или в источнике без назначения, как в master или master:.Таким образом, есть только два случая:

  1. Вы указали источник, но не указали пункт назначения.git fetch не будет обновлять никакие имена, , за исключением , которые Git начиная с 1.8.4 будет своевременно обновлять любые удаленного слежения имен, как указано в refspec выборки по умолчанию.Поэтому, если ваш Git по крайней мере 1.8.4, git fetch origin master обновит ваш origin/master, который является именем вашего Git для удаленного отслеживания для master Git's *1090*.

  2. Вы указали источник и пункт назначения.git fetch попытается обновить имя получателя.Если вы не установили флаг форсирования - либо глобальный, либо ведущий +, - это обновление должно быть ускоренным.Если вы не указали --update-head-ok, адресатом также не должна быть текущая ветвь. 1 В любом случае, если ваш Git версии 1.8.4 или новее, ваш Git будет своевременно обновлять имя удаленного отслеживания.для имени источника.

Обратите внимание, что:

git fetch origin

(который не указывает никаких refspecs в командной строке) будет использовать refspecs по умолчанию из вашей конфигурации.Предполагая, что это origin, см. git config --get-all remote.origin.fetch, чтобы увидеть эти refspecs по умолчанию.


1 В том, что я считаю ошибкой, тест здесь, для ветви извлечен , тестирует только HEAD главное рабочего дерева *1118*.Если ветвь в настоящее время извлечена в добавленном рабочем дереве, индекс и рабочее дерево добавленного рабочего дерева больше не синхронизируются с его ветвью.См. Также Почему Git позволяет перемещаться в извлеченную ветку в добавленном рабочем дереве?Как мне восстановиться? - ошибка симметрична при извлечении и отправке.

2 голосов
/ 16 июня 2019

Обновление соответствующей локальной ссылки является ожидаемым поведением, когда вы явно упоминаете пункт назначения в <refspec>.

В формате:

git fetch [options] <remote> <refspec>

, где refspec принимает форму

<src>:<dst>

(очевидно, для «источника» и «места назначения»)

в руководстве сказано, что

Удаленная ссылка, соответствующая <src>, извлекается, и если <dst> не является пустой строкой, делается попытка обновить локальную ссылку, соответствующую ей.

Вы также можете взглянуть на этот абзац над этим конкретным синтаксисом.


И ответить на дополнительные вопросы:

Однако, когда git fetch origin master выполняется, он имеет дополнительное поведение обновления FETCH_HEAD. Когда git fetch origin master:master выполняется, он имеет дополнительное поведение обновления локальной ветки 'master'. Правильна ли моя интуиция?

Не совсем. Если <refspec> задан не как <src>:<dst>, указанное имя будет взято как <src>, поэтому, когда вы сделали git fetch origin master, оно совпадает с git fetch origin master:master , FETCH_HEAD используется для внутренних устройств, а именно для git pull, и доступен для сценариев, но вам не нужно беспокоиться о повседневном использовании git.

"Это интерпретирует git fetch origin master:master как git fetch origin refs/heads/master:refs/heads/master? (Может быть, излишним для моего предыдущего вопроса)"

Да.

Он интерпретирует git fetch origin master как git fetch origin refs/heads/master:?

Нет , если сторона <dst> в <refspec> пуста, ничего вообще не обновляется, так как вы указываете ни на что. (не путать со случаем, когда вы пропускаете сам :, упомянутый выше. Анекдотически, обратный :my-branch удаляет my-branch, так как он обновляется с помощью void ref)

...