На что должны быть установлены пульты / origin / HEAD? - PullRequest
0 голосов
/ 10 марта 2019

Если разработчики работают над веткой develop, для нового проекта

1) Клон

git clone <git_url> должен иметь возможность автоматически клонировать develop ветвление локально без использования опции -b, так что

$ git branch -a # after clone should give
* develop
  remotes/origin/HEAD -> origin/develop
  remotes/origin/develop

2) Нажмите

Когда разработчик отправляет изменения локальной ветки (develop) в удаленное хранилище (origin/develop) с помощью команды git push origin develop, насколько я понимаю, изменения переносятся в origin/master, , если remotes/origin/HEAD указывает на origin/master, в отличие от упомянутого в этом комментарии


Вопрос:

1) Рекомендуется запустить git remote set-head origin develop и установить указатель HEAD в удаленном репозитории, прежде чем выполнять две вышеуказанные задачи? любым разработчиком

2) git push origin develop толкает изменения origin/develop независимо от значения remotes/origin/HEAD в удаленном хранилище?

* 1 039 * 3) Мы используем webhook между GitLab и Jenkins. Предоставляет ли env.gitlabSourceBranch предоставляемый плагин GitLab , имя ветки, на которое указывает remotes/origin/HEAD? Если да, то как получить название ветви, в которой происходит событие push? через веб-крючок.

Ниже приведены настройки, выполненные в GitLab для получения имени ветви, в которой произошла новая фиксация:

enter image description here Ниже приведен код в Дженкинс:

node('worker_node'){

    stage('stage1'){

        def repoName = env.gitlabSourceRepoName
        println "Repository Name: " + repoName // gives correct repo name


        def branchName = env.gitlabSourceBranch
        println "Branch name: " + branchName // gives always 'master' as value
   }
}

1 Ответ

2 голосов
/ 10 марта 2019

Рекомендуется ли запускать git remote set-head origin develop и устанавливать указатель HEAD в удаленном хранилище ...

Это может быть языковой проблемой, но здесь стоит указать, что это не устанавливает HEAD в удаленном хранилище. не влияет на чью-либо команду git clone.

Терминология Git здесь очень запутанная.Давайте разберем его немного:

  • A remote - это короткое имя, которое вы используете в своем Git-репозитории для ссылки на какой-либо другой Git-репозиторий.Следовательно, origin является удаленным: он заменяет некоторый URL.Если ваш Git набирает этот URL, какой-то другой Git отвечает на этот «телефонный звонок».Обратите внимание, что слово remote здесь является существительным: оно само по себе.

  • A удаленный репозиторий - это репозиторий, отличный оттвой собственный.Когда ваш Git набирает какой-то URL и вызывает другой Git, этот другой Git является удаленным хранилищем .Слово remote здесь является прилагательным.

  • Слово branch довольно неоднозначно в Git.(См. Что именно мы подразумеваем под "ветвью"? ). Я предпочитаю использовать фразу название ветви , где branch - это прилагательное, изменяющее имя и имя для удаленного отслеживания (Git называет это именем ветви для удаленного отслеживания ), которое содержит целую прилагательную фразу, изменяющую слово name ,чтобы ссылаться на такие вещи, как master и origin/master соответственно.

    Слово branch также может означать неопределенно определенную серию коммитов.В данном конкретном случае - когда мы используем git clone, чтобы скопировать Git-репозиторий с какого-либо URL-адреса на нашу собственную машину, или git push, чтобы отправить коммиты из нашего Git-репозитория на нашей машине в какой-то другой Git-репозиторий в другом месте (возможно, на другоммашина) - нам не нужен этот другой смысл слова.Но имейте в виду, что он существует!

Нам также понадобится еще один или два кусочка терминологии Git:

  • A ссылка (или ref ) - это имя ветви, имя тега или другое подобное имя.Фактически, reference - это просто обобщение этих имен: имена ветвей, имена тегов и имена для удаленного отслеживания - это всего лишь конкретные разновидности ссылок.Ссылка имеет полное написание, начинающееся с refs/.

    . За ней обычно сразу следует классификация: например, все имена ветвей начинаются с refs/heads/.Фактически, это , как Git знает, что refs/heads/master - это ветвь.Все имена тегов начинаются с refs/tags/, поэтому Git знает, что refs/tags/v1.2 является тегом, а все имена для удаленного отслеживания начинаются с refs/remotes/.

    В большинстве случаев вы можете удалить refs/heads/или refs/tags/ или refs/remotes/ часть ссылки.Например, если вы просто скажете master, Git проверит все ваши ссылки.Если у вас есть refs/heads/master и нет refs/tags/master, имя master должно быть , что имя ветки, поэтому Git будет воспринимать его таким образом - как ветвь.Аналогично, если вы просто скажете v2.1, а Git выполнит поиск и найдет тег с именем refs/tags/v2.1, но не более, то v2.1 должно быть этим именем тега, поэтому Git будет обрабатывать его таким образом - кактег.

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

  • refspec во второй простейшей форме представляет собой пару ссылок с двоеточием :, вставленным между ними.Следовательно, master:master - это, например, refspec.Так же и refs/heads/master:refs/remotes/origin/master.Вещи слева от двоеточия - источник , а вещь справа от двоеточия - пункт назначения .

Команды git fetch и git push используют refspecs, как мы увидим ниже.Пока вы спрашиваете о git clone, а не git fetch, значительная часть git clone состоит в том, что работает git fetch.

Учитывая все это, давайтепосмотрите , как Git разрешает символическое имя, и , когда Git разрешает символическое имя.Эта часть немного сложна, потому что git fetch и git push используют позиционные аргументы .

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

git fetch [repository] [refspec [refspec ...]]
git push [repository] [refspec [refspec ...]]

То есть после подкоманды push или fetch следующий элемент, если есть следующий элемент, равен , по определению a repository.Любые элементы после аргументы repository по определению являются refspec аргументами.Вы можете ввести необработанный URL-адрес для части репозитория, но, как правило, вы должны использовать удаленное имя по двум причинам:

  • , его легче набирать и получать правильно;и
  • включает полезные специальные функции.

Чтобы ввести любые refspec аргументы, вам нужно вставить repository аргумент, потому что без него Git будет просто думать, что все, что вы ввели , является a repository аргументом.То есть, если вы случайно запустите git push master, Git не поймет, что вы хотели напечатать git push origin master.Он просто попытается обработать master как удаленный или, если его не удастся, как URL.Вероятно, это не сработает в любом случае, и вы получите этот удивительный вывод:

$ git push master
fatal: 'master' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Итак, с git push у вас есть такие варианты:

git push
git push origin
git push origin somebranch
git push origin branch1:branch1 branch2:branch2 branch3 tag1:tag1

Когда вы выходитеНапомним, как в первых двух примерах, Git выбирает пульт и refspec для вас (первый пример) или refspec для вас (второй пример).Когда вы включаете refspec (третий пример) или несколько refspecs (четвертый пример), вы контролируете все части.

Давайте теперь перейдем ко второму вопросу, прежде чем мы вернемся к первому:

Выдает ли git push origin develop изменения origin/develop независимо от значения remotes/origin/HEAD в удаленном репозитории?

Содержит несколько ошибок терминологии (опять же, это могут быть просто языковые проблемы).Общая идея, я думаю, достаточно ясна, и ответ - да: это полностью игнорирует remotes/origin/HEAD.

Чтобы быть точным, это:

  • определяет origin в качестве удаленного, и
  • указывает develop в качестве refspec.

Помните, что мы говорили, что вторая самая простая форма refspec это пара имен с двоеточием между ними.При этом используется простая форма most , в которой отсутствует второе имя.Поведение опускания второго имени отличается в push и fetch.Давайте позаботимся только о push.

Для git push, пропуск второй части refspec означает, что первая часть и вторая часть совпадают .То есть develop означает develop:develop.Само название develop короткое - оно не начинается с refs/ - но, вероятно, и ваш Git, и их Git имеют ответвление с именем develop и никакой тег с именемdevelop. 1 Так что develop на самом деле коротко для refs/heads/develop:refs/heads/develop здесь.

Помните, что их репозиторий Git является репозиторием Git.Поэтому у него есть его собственное refs/heads/develop - его собственное имя ветви пишется develop. Ваш refs/heads/develop идентифицирует некоторый коммит в вашем хранилище. Их refs/heads/develop идентифицирует некоторый коммит в их хранилище.

Когда вы запускаете git push, вы сообщаете ваш Git: Подключитесь к другому Git.Затем убедитесь, что у них достаточно коммитов и других внутренних объектов Git для выполнения последней части, предоставив им любые коммиты, которые у меня есть, которые им не нужны.Наконец, вы закончили с этим, попросите их - или дайте им команду - установить некоторые из их имен ветвей и / или тегов, чтобы они указывали на некоторые конкретные коммиты или другие соответствующие объекты Git.

Имена ветвей и / или тегов, которые вы попросите их установить, происходят из destination части refspec.Так что, если вы сказали git push ... develop:develop, то имя ветки или тега, которое будет у вашего Git, попросит их изменить Git: develop. commit , который вы попросите их установить в качестве их develop, это тот, который идентифицируется по имени источника - тот, что справа.Итак, вы попросите их установить их develop, чтобы идентифицировать тот же коммит, который ваш develop идентифицирует.


1 Если у вас есть есть как ветвь refs/heads/develop , так и тег refs/tags/develop, происходят некоторые не очень хорошие вещи.У Git есть правила для этого, но правила Git немного странные и тревожные.Лучше всего избегать этой ситуации полностью: никогда не используйте одно и то же короткое имя для тега и ветви.


Они могут сказать, да или нет

Еслиони говорят «да» на этот запрос , теперь ваш Git знает, что их develop представляет этот коммит.Ваш Git запоминает их develop, обновляя свои origin/develop.Итак, ваш Git обновляет ваш origin/develop - ваш refs/remotes/origin/develop, чтобы использовать его полное имя - для сохранения хеш-идентификатора этого коммита.

Обратите внимание, что нигде в этом процессе ваш Git не смотрел насвой собственный refs/remotes/origin/HEAD.Вы не поместили refs/remotes/origin/HEAD на левой стороне вашего refspec.Вы можете сделать это, если хотите.Например, вы можете написать:

git push origin refs/remotes/origin/HEAD:refs/heads/develop

Это позволит вашему Git преобразовать ваш refs/remotes/origin/HEAD в хеш-идентификатор коммита, вызвать Git в origin и спросить , что Git, чтобы установить их refs/heads/develop для этого хеш-идентификатора коммита.Вероятно, уже установлен для этого идентификатора, так что это, вероятно, просто трата времени, но это то, что вы можете запустить, если хотите.

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

git push origin HEAD:refs/heads/develop

, который преобразует ваш HEAD в идентификатор хэша коммита, вызывает Git на origin и просит их установить ветвь develop на основании этого;и вы можете выполнить:

git push origin a123456:refs/heads/develop

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

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

git push origin master develop v1.3

и тем самым попросить их установить обе их ветви, и создают новый тег, все за один раз.

Если тЭй, скажите нет, они могут сделать это по частям. Предположим, вы попросите их установить все три из этих имен, и они примут ваш запрос на обновление их develop и создадут новый v1.3, но отклонят ваш запрос на обновлениеих master.Вы получите два успеха один за другим, и ваш Git обновит ваш refs/remotes/origin/develop, чтобы запомнить успех ветки, но не обновит ваш refs/remotes/origin/master, потому что сбой ветви означает, что вы не знаете, какой у них master в конце концов,(Не существует такой вещи, как удаленный тег , поэтому успех или неудача при запросе их создания v1.3 не влияет на имена в вашем хранилище.)

Назад к origin/HEAD: что это и чем это хорошо?

Короче говоря (и, может быть, немного слишком агрессивно), refs/remotes/origin/HEAD бесполезно.

Что это is - это символическая ссылка, которую имеет ваш Git. 2 Вы можете установить его в любое время, используя git remote set-head origin.Первоначально он был создан во время git clone.Но, насколько я могу судить, нет практической цели.

Я уже упоминал выше, что вы можете сократить ссылки: вы можете сказать master, что означает refs/heads/master и v2.1 означает refs/tags/v2.1.Попробуйте это сделать в своем собственном Git-репозитории: запустите git rev-parse и дайте ему короткие и длинные имена для веток и тегов.(Используйте git branch, чтобы перечислить ваши ветви, и git tag, чтобы перечислить ваши теги.) Вы увидите такие вещи:

$ git rev-parse master
b5101f929789889c2e536d915698f58d5c5c6b7a
$ git rev-parse v2.1.0
7452b4b5786778d5d87f5c90a94fab8936502e20

Команда rev-parse преобразуется из символического имени, например master, к хэш-идентификатору, например b5101f929789889c2e536d915698f58d5c5c6b7a.(Он также может переводить с короткого хеш-идентификатора на полный или делать много других трюков, но это одна из его основных задач: превращать имя в хеш-идентификатор.)

В общем, когда выдать Git короткое имя, Git просматривает все ваши ссылки, чтобы выяснить, какой это длинный.Команда git rev-parse делает это, а затем выдает идентификатор хеша.Большинство других команд Git также делают это, но затем переходят к , используя идентификатор хэша каким-то образом.Однако почти во всех случаях 3 этот процесс поиска описан в документации gitrevisions , которая с течением времени заслуживает тщательного и тщательного изучения.Но быстро взгляните на него и прокрутите немного вниз, чтобы найти список из шести шагов.

Список из шести шагов здесь как Git превращает короткое имя вдлинныйОбратите внимание, что на шаге 3 в качестве имени тега используется v2.1: если существует refs/tags/v2.1, тогда v2.1 является именем тега, и именно поэтому git rev-parse знает и находит его хэш-идентификатор.Это шаг 4, который пытается master в качестве имени ветви: если существует refs/heads/master, тогда master - это имя ветви, и вот как git rev-parse знает.

Внизу в нижней части шестиступенчатойсписок, есть шаг 6. Этот последний шаг берет любую строку, которую вы ввели - например, origin - и пытается использовать ее как refs/remotes/<em>string</em>/HEAD.Если это существует, это должно быть то, что вы имели ввидуТаким образом, хотя origin обычно является удаленным - это то, что вы вводите в качестве аргумента repository для git fetch и git push - это также допустимое короткое имя для commit , если вы поместите его в место, где какая-то команда Git, такая как git rev-parse, будет использовать как коммит.

Возможно удалить refs/remotes/origin/HEAD и git remote origin set-head -d сделает именно это.Если вы удалили его, origin не будет соответствовать шагу 6, а git rev-parse origin просто не удастся.Можно использовать от git remote origin set-head до , изменить имя, сохраненное в вашем refs/remotes/origin/HEAD, на любое другое origin/* имя ветви, чтобы шаг 6 был успешным, но использовал это другое имя.Ничто из этого когда-либо не возвращается к другому Git по адресу origin!


2 Я приукрашиваю символьная ссылка Вот.Символьная ссылка возникает, когда имя типа HEAD содержит вместо хеш-идентификатора какого-либо объекта Git другое имя.Механизм, который использует Git, должен быть общим, но он полон странных причуд и недостатков и на самом деле работает только с HEAD и - в меньшей степени - с этими именами стилей origin/HEAD для удаленного слежения.

Вы можетеНапример, создайте свои собственные символические ссылки в пространстве имен веток. Использование git symbolic-ref refs/heads/INDIR refs/heads/master создает имя INDIR в качестве символьной ссылочной ветви. К сожалению, если вы сделаете это, а затем попытаетесь удалить имя INDIR, Git удалит имя master вместо этого! Все это не совсем готово для такого использования (злоупотребление?). Не делай этого!

3 Я говорю почти во всех случаях , потому что некоторые команды Git знают , что их аргумент name является именем ветви или тега, а другие suspect это. Например, git branch знает , что вы собираетесь дать ему имя ветви, а не имя тега, в качестве следующего аргумента. Таким образом, он не использует шестиэтапный процесс разрешения, и фактически требует, чтобы вы не произвели написание имени ветви с полной формой refs/heads/ при создании новой ветви.

Команда git checkout является самой странной, потому что позиционный аргумент после checkout (и любые флаги) может быть именем ветви, именем тега или чем угодно, что разрешает допустимый коммит. Похоже, что должен использовать шестиступенчатый процесс. Если вы создаете ветку и тег с именем X, но указывающий на два разных коммита, вы можете ожидать, что git checkout X извлечет с тегом X. На самом деле он проверяет ветку 1554 *. Таким образом, в то время как git checkout будет пробовать все шесть шагов, он пробует шаг 4 раньше , чем шаг 3.

(Технически, он не проходит шестиступенчатый процесс, когда пытается использовать имя как имя ветви. Вместо этого он сначала просто пытается использовать его как имя ветви. Если это сработает, git checkout ставит вас на ответвление и готово. Если это не удается, , тогда код вызывает шестишаговый преобразователь name-ID-resolver, и пока хеш коммита возвращается, git checkout помещает вас в отдельную HEAD на этом коммите. Таким образом, он на самом деле пытается выполнить шаг 4 дважды, но если он потерпел неудачу в первый раз, то, скорее всего, он потерпит неудачу и во второй раз.)


Как git clone работает

Когда вы запускаете git clone <em>url</em>, у вас есть Git:

  1. Создайте новый пустой каталог (или возьмите какой-нибудь существующий пустой каталог). Все остальные шаги происходят в этой директории.
  2. Запустите git init, чтобы создать пустой репозиторий Git.
  3. Запустите git remote add, чтобы создать пульт. Название этого пульта - это то, что вы выбрали с вашим флагом -o, но если вы его не выбрали, это просто origin. URL для этого нового пульта - это URL, который вы дали git clone.
  4. Установить некоторые стандартные настройки для git fetch. Фактические refspecs зависят от флагов командной строки, но типичным стандартным является +refs/heads/*:refs/remotes/origin/*. Обратите внимание, насколько близко это напоминает refspecs, который мы использовали для git push. Сконфигурируйте символическую HEAD для этого пульта, как будто с помощью git remote set-head. Выполните любые дополнительные команды git config, указанные в дополнительных флагах командной строки.
  5. Выполнить git fetch. При этом используется пульт, созданный на шаге 3, и refspecs, установленные на шаге 4.
  6. Выполнить git checkout <em>name</em>. Аргумент name для этого шага зависит от флагов командной строки и от информации, полученной из другого Git. Подробности см. Ниже.

Это шаг 6, который ставит ваш новый клон на master, или, возможно, на develop, или даже вообще без ветви, если вы выбрали здесь что-то вроде v2.1. Если шаг 6 помещает вас в ветку master, это то, что создает вашу ветку master. Если на шаге 6 у вас есть собственная ветка develop, то создает вашу ветку develop. Если на шаге 6 у вас отсоединяется HEAD, ваш Git не создает веток!

Вы можете, если хотите, указать , какое имя должен использовать этот последний шаг клонирования, используя git clone -b <em>name</em>. Если вы сделаете это, ничего, что другой Git не скажет, имеет значение , за исключением, конечно, что name должно соответствовать одному из его имен. Но если вы не используете аргумент -b, тогда - и только тогда - то, что говорит другой Git, имеет большое значение.

Другое хранилище Git является хранилищем Git. Это означает, что другой репозиторий Git - для простоты назовем его серверным репозиторием - имеет HEAD. HEAD в хранилище сервера указывает, какая ветвь извлечена в хранилище сервера. Если серверное хранилище является --bare, оно не имеет рабочего дерева, поэтому его HEAD в некоторой степени не имеет значения. Но он все еще имеет единицу, и это означает, что есть еще один, когда сервер "включен", если Git сервера не находится в режиме отсоединенного HEAD (что возможно).

Когда ваш Git вызывает сервер Git, одна из вещей, которую ваш Git может запросить у сервера: В каком филиале вы находитесь? То есть ваш Git может спросить сервер о сервер HEAD. Если вы не указали выбранную ветку для -b во время git clone, , то это имя, которое ваш Git будет использовать для вашего git checkout.

Это также имя, которое ваш Git будет использовать для вашего git remote set-head origin --auto, и имя, которое ваш git clone автоматически установит как ваш origin/HEAD. Таким образом, параметр HEAD сервера является значением по умолчанию для вашей копии origin/HEAD в git clone время, и значение по умолчанию для команды последнего шага клона git checkout .

Это все это действительно хорошо. Если вы переопределите его с помощью -b во время git clone, , то значение не имеет значения, и поскольку origin/HEAD в любом случае совершенно бесполезно, , то значение также не имеет значения .

Заключение

Не беспокойтесь о origin/HEAD. Это бесполезно. Это тебе не поможет.

Не волнуйтесь много о HEAD в хранилище сервера. Это влияет на новые клоны, но только если человек, выполняющий клон, не выбирает ветку. Если вы хотите установить его, вы можете сделать это так, как позволяет ваш сервер. (У разных веб-сервисов есть разные способы установить или изменить это.)

Последнее, относительно этого вопроса:

Мы используем webhook между GitLab & Jenkins

Я ничего не знаю о конкретном плагине, который вы используете. Документация Jenkins варьируется: некоторые из них немного полезны, большинство из них, кажется, отсутствует, а некоторые, кажется, просто неправильно. Обычно Jenkins получает уведомления от с любого используемого вами хост-сервера, о том, что что-то произошло, и затем вы пишете код, который декодирует произошедшее событие (события). Но эта часть:

как получить название ветки, в которой происходят события push

принципиально плохой вопрос, потому что не обязательно любое имя ветви - мы могли бы git push только для тега, например - и если есть ветвь name, может быть много имен ветвей, и они могли изменить хэш-идентификаторы или нет. Правильный вопрос - уместно ли, чтобы Дженкинс запустил какой-то конвейер (ы) Я не могу помочь ответить на это, но это ваш гид, чтобы задавать правильные вопросы.

...