Как сделать Git тянуть только на ветке в сценарии оболочки? - PullRequest
1 голос
/ 16 марта 2012

У меня есть сценарий оболочки Bourne, который создаст HEAD указанной удаленной ветви или указанного удаленного тега. Ветвь / тег указывается в качестве входного аргумента скрипта.

В скрипте я выполняю git fetch для обновления всей локальной информации удаленной информацией. Затем я выполняю ветку / тег git checkout.

Затем мне нравится выполнять условное перетаскивание (если я правильно понимаю). В случае, если это касается ветки, мне нравится выполнять git pull для объединения из удаленной ветки с тем же именем. Однако в случае указанного тега я не хочу выполнять git pull (это приводит к ошибке).

Как мне лучше решить эту условную задачу? Или более простой: какие команды git мне нужны в сценарии оболочки для создания удаленной ветви или удаленного тега?

  • 1010 * Ed *

Ответы [ 3 ]

1 голос
/ 17 марта 2012

В данный момент (основываясь на обсуждении выше) я думаю, что вы немного путаетесь с тем, что значит быть «на ветке» и т. Д.

Глубоко внутри git, когда вы делаете git checkout NAME, git преобразует NAME в конкретный конкретный коммит. Эта фиксация прикреплена к «дереву» - дереву каталогов, заполненному файлами, и извлечение пытается вставить это конкретное дерево в ваше рабочее дерево (при этом не прерывая сохранение несохраненных файлов и т. Д., Но давайте предположим что ваше дерево работы во всех случаях является нетронутым, чтобы упростить ситуацию здесь.

Другая вещь, которую checkout делает, состоит в том, что если имя является одним из ваших собственных имен ветвей, оно записывает вашу "текущую ветку" как HEAD. Однако это имя может не называться «вашей» веткой. Это верно, если вы проверите явную «удаленную» ветку:

$ git checkout remotes/origin/master
Note: checking out 'remotes/origin/master'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at fb4a1b2... (some commit message)

Это также происходит, если вы проверите явный тег:

$ git checkout v1.0
Previous HEAD position was fb4a1b2... (some commit message)
HEAD is now at cfb9904... (another commit message)

Во всех этих случаях у вас есть совершенно хорошее рабочее дерево, которое представлено этими конкретными идентификаторами фиксации. Вы просто больше не «на ветке» (состояние «отсоединённая голова»). (Вы можете «вернуться на ветку», проверив какую-то локальную ветку или создав новую локальную ветку с git checkout -b newname, чей совет равен HEAD is now at ...)

Теперь, скажем, у вас есть какая-то "удаленная ветвь", которую вы намеренно отслеживаете:

$ git checkout GRONKLE # my local branch, which tracks remotes/origin/GRONKLE
$ git pull

«Вытягивание» здесь состоит из выборки плюс слияние. Шаг "выборки" использует соответствующий базовый транспорт для переноса любых новых коммитов в удаленной ветви. Это дает вам «то, что они сделали». Затем на этапе «слияния» предпринимается попытка применить «то, что они сделали», к «тому, что у вас есть» в вашей локальной ветке.

Скажем, например, что "то, что у вас есть" было полностью синхронизировано с "тем, что они сделали" вчера. Затем сегодня вы изменили dir1 / file1 и dir1 / file2 (и зафиксировали это). Тем временем «они» изменили dir2 / file3 (и зафиксировали это в вашем репозитории remotes / origin). Когда вы делаете «git fetch», он получает свои обновления для dir2 / file3 и делает remotes/origin/GRONKLE именем «то, что у них есть». Ваша ветка сейчас behind ... by 1 commit.

Однако, если вы продолжите выполнять «git merge», это применяет их изменения к dir2 / file3, но также сохраняет ваши изменения к dir1 / file1 и dir1 / file2. Это дает вам новый коммит, который является «коммитом слияния». Ваша ветка теперь впереди на один коммит.

Если вы хотите построить «то, что у них есть» - то, что вы сказали в первоначальном вопросе, - тогда вы не хотите ваших изменений в dir1 / file1 и dir1 / file2. Вы можете просто проверить remotes/origin/GRONKLE (в этом примере), и вы получите именно то, что вам дали, не больше и не меньше.

Если вы хотите построить «то, что у них есть, плюс то, что у меня есть», то вам нужно объединить и / или перебазировать, как сказал @Adam Dymitruk. Но это не "то, что у них есть". И - в ответ на ваш ответ ему - вы никогда не «на бирке» вообще. Тег - это просто имя определенного коммита, и если вы проверите этот тег, вы снова окажетесь в том же состоянии «отсоединенного HEAD». Если вы хотите внести изменения в «новую ветвь, которая начинается там, где начинается этот тег» (см. Сноску), вам необходимо создать указанную новую ветвь, начиная с этого тега.

Если вы хотите создать новую (локальную) ветку, начиная с некоторого данного коммита, есть два простых способа:

$ git checkout <commit>

(вы сейчас на этом коммите и можете осмотреться и посмотреть, действительно ли это тот, который вам нужен) с последующим:

$ git checkout -b new_local_branch

Или, если вы достаточно уверены в своей отправной точке:

$ git checkout -b new_local_branch <commit>

(и еще около полудюжины способов, использующих git branch, но этих двух достаточно).


Footnote: ветви на самом деле нигде не «начинаются», после того, как все сказано и сделано.Точнее, вы получаете себе отправную точку - проверяя какой-то конкретный идентификатор коммита - и выполняете любую понравившуюся вам работу вперед, делая новые коммиты и т. Д., Но как только вы добавите метку ветки, чтобы запомнить эту работу, веткалейбл просто следует «совету» этой работы.До этого момента, если вы находитесь в состоянии «отсоединенный ГОЛОВ», основной ссылкой на любые новые коммиты, которые вы делаете, является ваш отсоединенный ГОЛОВ.Легко «потерять» эту ссылку, хотя, если вы не создаете новую ветку, хотя, если вы ковыряетесь в git, вы можете найти все дополнительные места, где он сохраняет вещи для вас, как правило,на срок до трех месяцев.
0 голосов
/ 19 августа 2018

Примечание: если ваше удаленное репо имеет ветку и тег с тем же именем, ваша выборка может не получить ветку после Git 2.19 (Q3 2018)

См. коммит 60650a4 (01 августа 2018) Джунио С. Хамано (gitster) .
Помогли: Джонатан Тан (jhowtan) и Джонатан Найдер (artagnon) .
(Объединено Junio ​​C Hamano - gitster - в коммит 72c11b7 , 17 августа 2018 г.)

remote: заставить refspec следовать тому же правилу устранения неоднозначности, что и для локальных ссылок

При сопоставлении LHS без подстановочного знака ( см. Здесь ) refspec со списком ссылок, find_ref_by_name_abbrev() возвращает первую ссылку, которая соответствует с использованием любых правил DWIM , используемых refname_match() в refs.c, даже если лучшее совпадение произойдет позже в списке ссылок.

Это вызывает неожиданное поведение, когда (например) выборка с использованием refspec "refs/heads/s:<something>" с пульта дистанционного управления с "refs/heads/refs/heads/s" и "refs/heads/s" ; даже если первый был случайно создан, можно было бы ожидать, что последний будет извлечен.

Точно так же, , когда существует тег T и ветвь T, выборка T должна отдавать предпочтение тегу , так же, как работает правило устранения неоднозначности локального refname.
Но поскольку код проходит по выводу ls-remote с пульта дистанционного управления, который сортируется в алфавитном порядке и имеет refs/heads/T перед refs/tags/T, запрос на выборку T интерпретируется (неправильно) как выборка refs/heads/T.

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

0 голосов
/ 16 марта 2012

Вы хотите получить.Затем объединить, перебазировать или сбросить.

...