Использование обновления ветки удаленного отслеживания локальным филиалом

Я знаю, что можно создавать, обновлять или удалять remote-tracking branch по содержанию local branch текущего хранилища. Например:

$ git push . :refs/remotes/origin/master

Который удаляет remote-tracking branch, Но обновляет remote-tracking branch по местному отделению хорошая практика? Если да, есть ли другое использование этой работы?

2 ответа

Решение

Во-первых, давайте определим термин ветка удаленного отслеживания. Ветвь удаленного отслеживания - это просто ссылка, полное написание которой начинается с refs/remotes/, такой как refs/remotes/origin/master в вашем примере. В большинстве нормальных взаимодействий с Git мы отбрасываем refs/remotes/ расстаться и просто написать origin/master, но иногда - как с низкоуровневыми командами Git, ориентированными на сценарии, или при выполнении странных вещей, таких как ваш пример, - необходимо полностью изложить это.

Теперь цель удаленного отслеживания ветви состоит в том, чтобы отслеживать идентификатор, хранящийся в ветви на одном из ваших удаленных компьютеров (отсюда и имя). Итак, если мы посмотрим внимательно на ваш вопрос здесь:

... Является ли обновление удаленной ветки локальной веткой хорошей практикой?

нам нужно отметить несколько вещей: это не обновление "удаленной ветви" (которую мы на самом деле не определили), а обновление ветки удаленного отслеживания, т. е. одной из тех локальных сущностей, имя которых начинается с refs/remotes/, Также отметим, что вы специально удаляете ветку удаленного отслеживания (это довольно серьезная форма обновления:-)).

Тем не менее, предполагая, что вы только что пропустили слово и действительно имели в виду "ветвь удаленного отслеживания": является ли это правильным обновлением? Нет, вообще нет.

Позвольте мне добавить намного больше фона, хотя. Мне также нужно определить термин refspec здесь. Refspec это просто пара ссылок (например, master или же origin/master или их полностью прописанные версии, refs/heads/master а также refs/remotes/origin/master соответственно) разделены двоеточием : персонаж. Ссылка слева называется источником или src и тот, что справа, является пунктом назначения или dst, При желании вы можете поставить перед парой знак плюс + и опустить не более одного из src и / или dst, Если вы опустите dst Вы можете и, вероятно, должны также пропустить двоеточие: git fetch origin master Например, это источник без пункта назначения. Вам нужно двоеточие при пропуске src хоть: git push origin :foo не может быть написано git push origin foo,

(Что это означает, когда вы опускаете половину refspec варьируется, между git fetch а также git push, Я не собираюсь описывать это полностью, просто достаточно, чтобы покрыть интересующие нас случаи.)

Обновить через git fetch а также git push

Начиная с версии Git 1.8.4, оба git push а также git fetch будет своевременно обновлять ветки удаленного отслеживания. То есть, если у вас есть удаленный контакт Git R и вы получаете или устанавливаете его ветвь B, и ваша конфигурация говорит, что нужно отслеживать B под refs/remotes/R/B (как обычно), ваш Git (начиная с 1.8.4) обновит эту ветку удаленного отслеживания. (До 1.8.4, Git делал оппортунистические обновления для push но не для fetch.)

Удаленные ветки и --prune

Просто работает git fetch origin (без дополнительных ссылок) обновит все ваши refs/remotes/origin/ удаленное отслеживание филиалов. Но предположим, что вы сделали это раньше, и был xyz ветка, на которую скопировал ваш Git refs/remotes/origin/xyz и с тех пор кто-то удалил ветку xyz на origin?

Сегодня происходит то, что ваш Git сохраняет ваши origin/xyz (предположительно, если вы все еще использовали его). Чтобы сообщить вашему Git, что он должен автоматически удалить любую ветвь удаленного отслеживания, которая у вас больше отсутствует, просто добавьте --prune (или же -p) к вашей команде:

$ git fetch --prune origin

Ваш Git теперь удалит все ветки удаленного отслеживания, которые вы перечислили в origin это все еще не отслеживает фактическую ветвь на удаленном названном origin,

Вы также можете записать это по буквам:

git remote update --prune origin

и есть некоторые ошибки в некоторых версиях (версиях) Git, где одна из двух команд работает, а другая нет (я не уверен, какая версия или какая из них успешна).

Обновление вручную

Как правило, вы должны позволить Git автоматически обновлять ветки удаленного отслеживания. Есть несколько конкретных случаев, когда вам может потребоваться обновить их вручную, например, после изменения конфигурации вручную, чтобы изменить имя удаленного или изменить сопоставление, примененное к удаленному (remote.remote.fetch линии), или обнаружена ошибка, подобная той, которую я только что упомянул. Или, например, если вы только что использовали источник без git push, или же git push --delete, чтобы удалить ветку git push origin :foo - и у вас очень медленное сетевое соединение, вы можете быть слишком нетерпеливы, чтобы запустить git fetch -p origin и ждать.

В этом случае пока git push . :refs/remotes/origin/foo работает, чтобы удалить origin/foo из вашего хранилища вы можете использовать более прямую команду:

$ git branch -r -d origin/foo
Deleted remote-tracking branch origin/foo (was 5ace313).

Фактически, любое обновление веток удаленного отслеживания может быть выполнено через git branch -r (или основная команда "сантехника", git update-ref), так же, как обновления в местных филиалах могут быть сделаны через git branch (без -r). Единственное место, где я считаю, есть веская причина для использования git push . обновить ветку значит добиться результата git merge --ff-only фактически не проверяя ветку. 1


1 В частности, git push . x:y пытается выполнить ускоренную перемотку локального идентификатора x - это может быть что угодно, что разрешает допустимый идентификатор объекта - со ссылкой y, когда y является локальной ветвью, это эквивалент:

git checkout y && git merge --ff-only x && git checkout -

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

x="$1" y="$2"
# resolve x to an object ID
xid=$(git rev-parse $x) || exit
# resolve y to a reference
yref=$(git rev-parse --symbolic-full-name $y) || exit
[ -z "$yref" ] && { echo "fatal: $y: not a valid reference"; exit 1; }
# make sure the current value of y is an ancestor of (resolved) x
git merge-base --is-ancestor $yref $xid || { echo 'not a fast forward'; exit 1; }
# ok, it is a fast forward: update
git update-ref -m "fast forward" $yref $xid

Обратите внимание, что --symbolic-full-ref разрешает символьную ссылку как origin/HEAD к названию это относится, например, refs/remotes/origin/master, Это, вероятно, нежелательно здесь, но нет очевидного флага для git rev-parse чтобы проверить, что ссылочное имя является действительным, и преобразовать его в полностью определенное, но не расширять символическое имя до его цели.

Я не совсем уверен, что вы спрашиваете, хотя. Если вы хотите использовать альтернативу удаленному удалению, вот так:

git push origin --delete branchName

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

Когда я удаляю удаленный локальный, это когда особенность ветви была реализована, и запрос на получение к мастеру был только что завершен. Все изменения в удаленной ветке теперь в master, поэтому мы можем безопасно удалить ветку.

Другие вопросы по тегам