Почему action/checkout извлекает последнюю фиксацию сразу после клонирования репозитория?

Пытаясь понять смысл действия actions/checkout@version, я наткнулся на этот ответ, в котором было сказано следующее, чтобы объяснить, что происходит, когда выполняется одно и то же действие:

По умолчанию выполняются следующие шаги:

  1. Текущее репо, в котором запускается рабочий процесс, клонируется.

  2. В зависимости от определенных событий, таких как push-запрос или пул реквест:
    Для push-события выполняется команда ниже, где $GITHUB_REF указывает к последней фиксации в указанной ветке для события push в рабочий процесс:
    git fetch --depth 1 $GITHUB_REF

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


50
3

Ответы:

Хотя может показаться, что достаточно «только» клонировать репозиторий git, вы должны помнить, что git — это распределенный контроль версий.

Таким образом, git-clone(1) позаботится о клонировании фактического репозитория (или завершится ошибкой с этой операцией), но если вы дважды подумаете, содержимое репозитория могло уже измениться во время его клонирования (просто для примера).

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

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

Теперь следующая задача — получить конкретную версию, которая может быть использована. Ну, давай принеси. Потому что git-fetch(1) скажет нам, сработало это или нет.

Так...

... в то время как git-clone (1) достаточно, чтобы убедиться, что удаленный репозиторий доступен и может быть клонирован ...

... git-fetch(1) - это правильная операция для получения ("выборки") конкретной интересующей ревизии (в контексте действия).

Обе операции должны быть выполнены. Последнее, логически более важное (работа над этой ревизией), может быть выполнено только в том случае, если репозиторий уже клонирован (загружен, инициализирован).

Я надеюсь, что это отвечает на ваш вопрос и не звучит как высмеивание вашего вопроса, потому что это легко пропустить. Я часто просто клонирую репозиторий, и мне не нужно заботиться о получении правильной версии, потому что она уже есть. Git с git-clone(1) достаточно умен, чтобы уже понять, что я ищу (например, имя ветки), а затем я имел в виду HEAD.

Однако, когда мы автоматизируем сборку, мы хотим конкретно убедиться (утвердить), что мы можем и действительно собираем очень четкую ревизию. GITHUB_REF, CI_COMMIT, BUILD_REVISION, REVISION — существует много названий в зависимости от того, на какой (собственной) платформе вы его запускаете.

В конце концов, это ссылка на фиксацию в git, идентифицированную хешем SHA1, ревизией. Любой из этих параметров просто ссылается на него, и git-fetch(1) гарантирует, что он извлекает его (а вместе с ним и все необходимые файлы/деревья/объекты). Для этого мы используем систему контроля версий. И это, безусловно, требует сначала получить эту версию.

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

Что затем снова требует настройки пульта и его клонирования. (это делается за один шаг с помощью git-clone(1) для всей начальной загрузки.)

Удачного кодирования и пусть сборка идет своим чередом!


Упражнение:

Вместо action/checkout[@<revision>] можно просто run:git clone и git fetch, git checkout... . Более ранняя версия представляет собой оболочку javascript для этих точных команд оболочки, о которых вы просили (но, очевидно, в их документации отсутствует обоснование реализации, иначе вы бы не просили об этом, верно?).

Поэтому, если вы хотите поэкспериментировать, клонируйте репозиторий git через run: в оболочке bash и исследуйте среду, как git на самом деле клонируется в инфраструктуре Microsoft, на которой работает Github (и, следовательно, ваш рабочий процесс).

Для этого узнайте, как использовать интерфейс командной строки gh и создать один (временный) репозиторий (после другого), чтобы запускать выполнение действий, а затем удалить временный репозиторий после просмотра результата.


2 примера причин для запуска этой команды:

  • $GITHUB_REF может быть чем-то другим, кроме ссылки или тега; например, github управляет ссылками с именем refs/pull/<id>/head, чтобы они указывали на последнюю фиксацию запроса на вытягивание, и эти ссылки по умолчанию не загружаются git clone
  • в зависимости от того, как клонируется репо (например, если это неглубокий клон), у него может не быть всех ветвей для начала.

Запуск git fetch ... $GITHUB_REF первым — это способ убедиться, что действие работает во всех возможных условиях.


Решено

Первый шаг, упомянутый в вашей цитате, неверен (выделено мной):

  1. Текущее репо, в котором запускается рабочий процесс, клонируется.

Взглянув на код [GitHub] для действия, вот шаги, которые он выполняет для проверки ссылки:

  1. Если git отсутствует, загрузите код с помощью API и верните
  2. В противном случае, если git присутствует, инициализируйте пустой репозиторий git.
  3. Добавьте удаленный для этого пустого репозитория, указывающий на репозиторий, который будет использоваться.
  4. Получить и проверить конкретную ссылку, необходимую

Здесь вы можете заметить, что репозиторий на самом деле не клонирован, а удаленный сервер настроен на только что инициализированный пустой репозиторий. Следовательно, запуск fetch действительно необходим, поскольку у него еще нет фиксации.

Примечание. Я пропустил некоторые другие шаги, выполняемые кодом, которые не имеют отношения к вопросу.