В чем разница между "git show ..origin / master: somefile" и "git show origin / master: somefile" - PullRequest
1 голос
/ 26 мая 2020

Для контекста из моей собственной ветки функций я использую следующие команды:

> git fetch
> git show ..origin/master:somefile > ../external_folder/somefile

, чтобы убедиться, что у меня есть последняя копия файла из origin / master для чтения без перезаписи моей собственной ветки .

Вышеупомянутое работает, но если я опущу две точки в команде git show, полученный файл будет таким же, как и в моей ветке, даже если более новый был отправлен в origin / master.

Может кто-нибудь объяснить в чем разница? Кроме того, если это имеет какое-то значение, рассматриваемый файл является blob.

edit: Я ошибся:

> git show ..origin/master:somefile > ../external_folder/somefile

создает пустой файл, и я неверно истолковал diff

Ответы [ 2 ]

0 голосов
/ 27 мая 2020

из git -документации:

... в этих двух сокращенных обозначениях вы можете опустить один конец и оставить по умолчанию HEAD. Например, origin.. является сокращением для origin..HEAD и спрашивает: «Что я сделал после того, как разветвился из исходной ветки?» Точно так же ..origin является сокращением для HEAD..origin и спрашивает: «Что сделал источник, так как я его разветвил?» Обратите внимание, что .. будет означать HEAD..HEAD , который представляет собой пустой диапазон, достижимый и недоступный из HEAD.

Вся документация по обозначению диапазона с точками вы можете прочитать здесь

Git заменяет HEAD, если одна сторона отсутствует -> git show ..origin/master становится git show HEAD..origin/master и посмотрите, что сделал origin с момента его разветвления.

Если вы пишете без двойной точки , вы берете текущий origin и показываете содержимое из этого origin.

В примере на картинке выше, с ..experiment вы увидите, стоявшую от красной точки. Если вы напишете experiment, вы увидите, что стояло с синей точки.

Изображение из здесь

Также посмотрите этот вопрос

0 голосов
/ 27 мая 2020

Вы должны просто использовать git show origin/master:somefile здесь без двух начальных точек. Команда git show, вероятно, должна жаловаться на ..origin/master:somefile: выводить сообщение об ошибке в stderr и не выводить на стандартный вывод вообще.

С версиями Git у меня есть под рукой , git show ..<rev>:path не производит никакого вывода (и завершается успешно!), Даже если данный путь существует в обоих коммитах. Итак, если бы я использовал ваш:

git show ..origin/master:somefile > ../external_folder/somefile

, я бы всегда получал пустой ../external_folder/somefile файл. Я прихожу к выводу, что ваша версия Git должна предшествовать Git 1.7.11.3.

Long-i sh

Синтаксис <rev1>..<rev2> в основном 1 означает выберите диапазон коммитов , причем диапазон определяется вызовом git rev-list, более или менее, как если бы вы запустили:

git log ^$(git rev-parse rev1) $(git rev-parse rev2)

Вы можете увидеть этот эффект более непосредственно, если просто запустите git rev-parse самостоятельно:

$ git rev-parse master~2..master
b994622632154fc3b17fb40a38819ad954a5fb88
^41eae3eaa81c5f2b61b2610ed74de15c4291b318

Имя master в этом конкретном репозитории Git выбирает фиксацию b994622632154fc3b17fb40a38819ad954a5fb88. Относительное выражение master~2 выбирает фиксацию 41eae3eaa81c5f2b61b2610ed74de15c4291b318.

Пропуск одного из двух имен означает притвориться, что я написал HEAD, так что, поскольку HEAD в настоящее время master, мы также get:

git rev-parse master~2..
b994622632154fc3b17fb40a38819ad954a5fb88
^41eae3eaa81c5f2b61b2610ed74de15c4291b318

Такие команды, как git log или git cherry-pick, могут принимать ряд таких коммитов. Набор коммитов, выбранных этим выражением диапазона:

  • все коммиты достижимы из неотрицательного (без ^ префикса) коммита, за исключением
  • всех коммитов, достижимых из отрицательного (^ -префикс) commit.

Итак, если у нас есть:

...--E--F--G--H   <-- master (HEAD)

, то master~2..master, или - короче, но идентичный по смыслу - HEAD~2.. выбирает коммиты G и H, потому что master (или HEAD) означает фиксация H, а master~2 (или HEAD~2) означает фиксация F . Мы выбираем все завершающие коммиты, включая фиксацию H, но затем отбрасываем все завершенные коммиты, включая фиксацию F, оставляя здесь только G и H.

Команда git show однако обычно показывает только одно: например, одну фиксацию или один файл. Поэтому идея дать ему выражение range не имеет смысла (но см. Ниже). Однако команда может отображать отдельные файлы, и это происходит, когда выражение ревизии, которое вы указываете, называет объект blob:

$ git rev-parse master:Makefile
3d3a39fc192d5544a411d4cedb3785473b6f1148
$ git cat-file -t 3d3a39fc192d5544a411d4cedb3785473b6f1148
blob

Итак, когда git show master:Makefile дается выражение ревизии, которое разрешается в один blob например, git show показывает содержимое этого blob-объекта.

Теперь рассмотрим:

$ git rev-parse master~2..master:Makefile
3d3a39fc192d5544a411d4cedb3785473b6f1148
^41eae3eaa81c5f2b61b2610ed74de15c4291b318

Хотя ha sh идентификаторы большие, уродливые, их трудно запомнить или получить правильно, мы можем увидеть здесь, что мы даем git show:

  • неотрицательный ha sh ID объекта blob, который нам нужен чтобы увидеть, плюс
  • инвертированный ha sh ID фиксации master~2.

Как оказалось, commit c5941f1aac071addc1c9b0781c323b588c542420, который сначала был опубликован c в Git 1.7.11.3, изменил команду git show, чтобы действовать очень похоже на git log при заданном диапазоне фиксации:

git show master~2..master

работает так же, как и бег:

git rev-list master~2..master | while read commit; do git show $commit; done

Есть несколько отличий. В частности, git log по умолчанию не показывает патч для фиксации слияния, но git show по умолчанию показывает патч, как если бы вы использовали git log --cc. (Другое отличие здесь менее важно: вариант оболочки с последовательностью while read commit; do ...; done должен порождать несколько git show команд.)

Обратите внимание, что вызов git rev-list таким образом не дает результата:

$ git rev-list master~2..master:Makefile
$ 

Это потому, что второй (неотрицательный) ha sh ID является идентификатором объекта blob, а объекты blob не участвуют в обходе ревизий. Таким образом, это составляет выбрать без коммитов, при этом исключая все коммиты, доступные из master~2.

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


1 Причина использования наречия в основном здесь в том, что некоторые команды имеют особую обработку. В частности, и git diff, и git rebase играют особые трюки с синтаксисом из двух и / или трех точек: они не позволяют просто git rev-list выполнять свою работу.

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