Есть ли способ получить код с PR с удаленной веткой на GitHub? - PullRequest
3 голосов
/ 04 марта 2020

На GitHub я обычно клонирую чьи-то форки или добавляю их как удаленные, чтобы загружать их изменения. Однако, если ветка / ветвь полностью удалена, это не вариант.

Тем не менее, вы по-прежнему можете просматривать измененные файлы в PR, если вы щелкнете вкладку «Файлы изменены» в PR , даже с удаленной веткой / веткой и закрытым PR.

Есть ли способ получить ветку с этими изменениями локально в моей системе? Одной из идей было бы просто вручную воссоздать все, скопировав изменения с веб-сайта, но этот подход кажется неоптимальным.

1 Ответ

2 голосов
/ 04 марта 2020

Да, это относительно просто: например,

git fetch <remote-or-url> refs/pull/1234/head:refs/heads/pr1234

превратит их (GitHub) pull-request- # 1234 коммитов в вашу ветку pr1234.

Фон

Способ, которым это работает, прост:

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

  2. Когда вы запускаете git fetch, ваш Git получает их коммитов (и других объектов) по имени-и-ха sh -ID пары, которые их Git показывает вашему Git. Затем он копирует любые необходимые коммиты (и другие объекты), чтобы ваш Git мог обновлять ваши имена для удаленного отслеживания и / или записывать записи в ваш файл Git .git/FETCH_HEAD и так далее. И наконец, он делает пару вещей:

    • обновляет ваши собственные ссылки, как указано; и
    • запись .git/FETCH_HEAD.


    Файл FETCH_HEAD оставлен для кода git pull, в основном; Это немного исторический артефакт, теперь, когда git pull был переписан в C.

Хорошая вещь в refs заключается в том, что разделение на пространства имен Вы или кто-либо другой может изобрести свой собственный. Используются пробелы refs/heads/ и refs/tags/ и refs/remotes/, а также refs/bisect/ и refs/replace/ и некоторые другие, но GitHub был в состоянии использовать refs/pull/, который сам Git не может хранить их имен.

В этом refs/pull/ пространстве GitHub вставляет PR или номер выпуска (эти номера относятся к репозиторию и являются глобальными для репозитория), а затем /head для подсказки commit и /merge для результата автоматического выполнения c test git merge. Если автомат c объединить завершится неудачно , GitHub просто не создаст ссылку merge. Следовательно, если есть PR с номером 1234, существует refs/pull/1234/head; Если этот PR был успешно объединен с тестом, refs/pull/1234/merge также существует, а если нет, то его нет.

Обратите внимание, что преобразование из их (GitHub's) branch имен в ваши дистанционное отслеживание имен контролируется вашей собственной remote.origin.fetch строкой конфигурации, которая по умолчанию:

+refs/heads/*:refs/remotes/origin/*

Это refspe c: пара ссылок , разделенные двоеточием и, возможно, префикс со знаком плюс + (всегда используется для этого конкретного случая). Это соответствует их именам branch , поскольку левая сторона или шаблон source соответствуют именам ветвей. Это заставляет Git заменять имена их ветвей именами для удаленного отслеживания, поскольку правая сторона или шаблон destination заменяет refs/heads/ на refs/remotes/origin/ (при этом все совпадает с * без изменений).

Это означает, что вы можете добавить:

+refs/pull/*/head:refs/heads/pr*

к вашим remote.origin.fetch refspecs в вашем .git/config, так что git fetch будет автоматически, и почти всегда, 2 создайте или обновите ваши pr<em>number</em> ветви. Тем не менее, он потенциально разрушит любую из ваших личных pr<em>number</em> веток, которые вы создали самостоятельно, поэтому имейте в виду, что если вы сделаете это, вы должны избегать именования веток pr -что-то (по крайней мере что-то числительное c) , но остерегайтесь обрезки, см. сноску 2).


1 Исключениями здесь являются HEAD, MERGE_HEAD, CHERRY_PICK_HEAD и тому подобное. Хотя FETCH_HEAD иногда работает как ссылка, файл FETCH_HEAD особенно особенный, он может содержать несколько строк и некоторые дополнительные аннотации; другие содержат только (и точно) один га sh удостоверение личности или один символ c ref.

2"Всегда" слишком сильно, и даже мой слегка ласка формулируется почти всегда также может быть: каждый раз, когда вы запускаете git fetch с некоторыми refspe c аргументом (ами), это переопределит это значение по умолчанию. Ваши сконфигурированные настройки remote.origin.fetch используются только в том случае, если вы их не переопределяли. Вспомните, как это взаимодействует с fetch.prune или git fetch -p: * в пункте назначения теперь означает, что Git автоматически удалит соответствующих ссылок, которые не были записаны действием извлечения.

Способность писать pr*, а не, например, pr/*, зависит от вашего Git года изготовления вина. В некоторых более старых версиях Git глобальные шаблоны * в refspecs можно использовать только в «компоненте полного имени», например, refs/heads/*:refs/remotes/origin/* всегда в порядке во всех Git версиях, независимо от того, насколько они древние, но иногда refs/heads/a*:refs/remotes/origin/a* нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...