Вы должны просто использовать 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
выполнять свою работу.