Команда git-rev-parse: опции, ключи и примеры использования
Общие команды – Общие команды, присущие различным операционным системам.
git rev-parse
- Get the commit hash of a branch:
- Get the current branch name:
git rev-parse —abbrev-ref >
- Get the absolute path to the root directory:
git rev-parse —show-toplevel
Примеры кода, демонстрирующие общие подходы в программировании или же решающие небольшие прикладные задачи. Языки программирования и библиотеки, позволяющие эффективно решать задачи разработки. Объектно-ориентированное программирование, функциональное программирование и прочие подходы и …

Трюки Bash
Полезные заметки по работе с командной строкой: bash и прочие *sh. Однострочники, скрипты, позволяющие решать большие и малые задачи администрирования и настройки Юникс систем. Zsh для современного MacOS, Bash для …

Заметки о настройке различных IT-штуковин. Настройка, допиливание, полировка. Конфигурируем приложения и тюнингуем сервера. Полезные параметры и ключи запуска программ. Увеличиваем скорость, уменьшаем отклик, ускоряем работу и улучшаем результаты работы. Объясняем …

Терминал/Консоль
Команды и инструкции терминала (консоли) Linux, MacOS, Windows и прочих операционных систем. Трюки и особенности командных оболочек, скрипты для администрирования Unix. Программирование и скриптование Windows и Linux, тонкая настройка Macos. …

Также может быть вам интересно:
- Как получить дерево директорий на Bash одним однострочником
- Python: Функции
- Python: Встроенные типы данных (list, set, dict, etc)
- Python: типы данных, переменные, логическое ветвление и циклы
- Как сделать свою middleware в Django (с примерами)
Свежее на «Цифре»
MessageId или как дебажить систему с минимумом проблем
Программы, 09.09.2023
Проверочный список для выпуска промышленных приложений с иллюстрациями
Работа и управление, 30.07.2023
В Google Pixel и Windows Snipping Tool есть возможность восстановления обрезанных изображений
Новости, 23.03.2023
Два подарка «под ёлочку» от Heroes of Might and Magic
Новости, 25.12.2022
Вышел Pulsar – редактор кода на основе Atom
Новости, 25.12.2022
Ленивый backup PostgreSQL
Программы, 17.12.2022
Google анонсировала OSV-Scanner: сканер уязвимостей в программных проектах
Новости, 16.12.2022

Gitea запускает коммерческую версию, а недовольные – форк Forĝejo
На днях группа бывших разработчиков Gitea решили создать на базе хостинга кода Gitea свою версию проекта – «Forgejo». Причиной тому …

Пользователи и их создание в Django — своя регистрация на сайте
Если вашим сайтом должны активно пользоваться несколько человек, то полезно их различать, а значит — надо уметь создавать пользователей, либо …

Новый синтаксис старой команды with в Python 3.10
Как же долго моё чувство прекрасного страдало… Но в Python 3.10 появился новый парсер синтаксических конструкций Python!

Добавляем постраничную пагинацию на Django сайт
На сайтах часто встречаются многостраничные объекты: список товаров, список заметок и т.д. Поэтому важно уметь добавить навигацию по страницам на …

Новый оператор match-case в Python
В новой версии Python (3.10) появится новый оператор. Новый оператор сопоставления по шаблону (match-case).

Нет слов, одни. однострочники
На днях вышел пост со списком полезных однострочников для JavaScript программистов. Памятуя Perl-овую молодость, заглянул туда.

Добавляем переменные в контекст Django шаблонов (свой контекст-процессор)
В Django вы можете передавать данные в шаблоны посредством контекстов. Контекст передаётся из контроллера (view в терминах Django), однако, если …

Пример своей консольной команды в Django проекте
Если вы работали с Django проектом, то, скорее всего, запускали команды из консоли (manage.py). В Django есть простой способ писать …

Разграничение прав доступа на Django сайте
Почти на любом веб-сайте необходимо разделять пользователей на группы и предоставлять им разные возможности. В Django есть довольно серьёзная система …
7.1 Инструменты Git — Выбор ревизии
К этому моменту вы уже изучили большинство повседневных команд и способов организации рабочего процесса, которые необходимы для управления Git репозиторием, используемого для управления вашим исходным кодом. Вы выполнили основные задания по отслеживанию и сохранению файлов в Git, вооружились мощью области подготовленных изменений, легковесного ветвления и слияния.
Теперь настало время познакомиться с некоторыми очень мощными возможностями Git, которые при повседневной работе вам, наверное, не потребуются, но в какой-то момент могут оказаться полезными.
Выбор ревизии
Git позволяет различными способами указать коммиты или их диапазоны. Эти способы не всегда очевидны, но их полезно знать.
Одиночные ревизии
Конечно, вы можете ссылаться на коммит по его SHA-1 хешу, но существуют более удобные для человека способы. В данном разделе описываются различные способы обращения к одному коммиту.
Сокращённый SHA-1
Git достаточно умен, чтобы понять какой коммит имеется ввиду по нескольким первым символам его хеша, если указанная часть SHA-1 имеет в длину по крайней мере четыре символа и однозначна — то есть в текущем репозитории существует только один объект с таким частичным SHA-1.
Например, предположим, чтобы найти некоторый коммит, вы выполнили команду git log и нашли коммит, в которой добавили определённую функциональность:
$ git log commit 734713bc047d87bf7eac9674765ae793478c50d3 Author: Scott Chacon Date: Fri Jan 2 18:32:33 2009 -0800 Fix refs handling, add gc auto, update tests commit d921970aadf03b3cf0e71becdaab3147ba71cdef Merge: 1c002dd. 35cfb2b. Author: Scott Chacon Date: Thu Dec 11 15:08:43 2008 -0800 Merge commit 'phedders/rdocs' commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b Author: Scott Chacon Date: Thu Dec 11 14:58:32 2008 -0800 Add some blame and merge stuff
Предположим, что в нашем примере это коммит 1c002dd…. . Если вы хотите выполнить для него git show , то следующие команды эквиваленты (предполагается, что сокращения однозначны):
$ git show 1c002dd4b536e7479fe34593e72e6c6c1819e53b $ git show 1c002dd4b536e7479f $ git show 1c002d
Git может вычислить уникальные сокращения для ваших значений SHA-1. Если вы передадите опцию —abbrev-commit команде git log , в выводе будут использоваться сокращённые значения, сохраняющие уникальность; по умолчанию используется семь символов, но для сохранения уникальности SHA-1 могут использоваться более длинные значения.
$ git log --abbrev-commit --pretty=oneline ca82a6d Change the version number 085bb3b Remove unnecessary test code a11bef0 Initial commit
Обычно от восьми до десяти символов более чем достаточно для сохранения уникальности значений в проекте.
Например, в ядре Linux, который является довольно большим проектом с более чем 450 тыс. коммитов и 3.6 млн. объектов, отсутствуют объекты, чьи SHA-1 совпадают более чем в 11 первых символах.
Примечание
Небольшое замечание о SHA-1
Большинство людей в этом месте начинают беспокоиться о том, что будет, если у них в репозитории случайно появятся два объекта с одинаковыми значениями SHA-1. Что тогда?
Если вы вдруг зафиксируете объект, который имеет такое же значение SHA-1, как и предыдущий объект в вашем репозитории, Git увидит этот предыдущий объект в своей базе и посчитает, что он уже был записан. Если вы позже попытаетесь переключиться на этот объект, то вы всегда будете получать данные первого объекта.
Однако, вы должны осознавать, насколько маловероятен такой сценарий. Длина SHA-1 составляет 20 байт или 160 бит. Количество случайно хешированных объектов, необходимых для достижения 50% вероятности возникновения коллизии, равно примерно 2 80 . (формула для определения вероятности возникновения коллизии p = (n(n-1)/2) * (1/2^160)) . 2 80 — это 1.2 × 10 24 , или 1 миллион миллиардов миллиардов, что в 1200 раз больше количества песчинок на земле.
Приведём пример, чтобы дать вам представление, чего будет стоить получение коллизии SHA-1. Если бы все 6.5 миллиардов человек на Земле были программистами, и ежесекундно каждый из них производил количество кода, эквивалентное всей истории ядра Linux (3.6 миллиона Git-объектов), и отправлял его в один огромный Git репозитории, то потребовалось бы около 2 лет, пока этот репозиторий накопил бы количество объектов, достаточное для 50% вероятности возникновения SHA-1 коллизии. Более вероятно, что каждый член вашей команды в одну и туже ночь будет атакован и убит волками в несвязанных друг с другом происшествиях.
Если выделить на это несколько тысяч долларов вычислительной мощности, можно будет синтезировать два файла с одним и тем же хешем, что было доказано проектом https://shattered.io/ в феврале 2017 года. Git движется к использованию SHA256 в качестве алгоритма хеширования по умолчанию, который намного более устойчив к атакам с коллизиями и имеет код, помогающий смягчить эту атаку (хотя он не может полностью её устранить).
Ссылки на ветки
Для наиболее простого способа указать коммит требуется существование ветки, указывающей на этот коммит. Тогда вы можете использовать имя ветки в любой команде Git, которая ожидает коммит или значение SHA-1. Например, если вы хотите просмотреть последний коммит в ветке, то следующие команды эквивалентны (предполагается, что ветка topic1 указывает на коммит ca82a6d ):
$ git show ca82a6dff817ec66f44342007202690a93763949 $ git show topic1
Если вы хотите узнать SHA-1 объекта, на который указывает ветка, или увидеть к чему сводятся все примеры в терминах SHA-1, то вы можете воспользоваться служебной командой Git, называемой rev-parse . Служебные команды подробно рассмотрены в главе Git изнутри; в основном, команда rev-parse существует для низкоуровневых операций и не предназначена для ежедневного использования. Однако она может быть полезна, когда вам нужно увидеть, что в действительности происходит. Теперь вы можете выполнить rev-parse для вашей ветки.
$ git rev-parse topic1 ca82a6dff817ec66f44342007202690a93763949
RefLog-сокращения
Одна из вещей, которую Git делает в фоновом режиме, является ведение журнала ссылок, в котором сохраняется то, куда указывали HEAD и ветки за последние несколько месяцев.
Для просмотра этого журнала используется команда git reflog :
$ git reflog 734713b HEAD@: commit: Fix refs handling, add gc auto, update tests d921970 HEAD@: merge phedders/rdocs: Merge made by the 'recursive' strategy. 1c002dd HEAD@: commit: Add some blame and merge stuff 1c36188 HEAD@: rebase -i (squash): updating HEAD 95df984 HEAD@: commit: # This is a combination of two commits. 1c36188 HEAD@: rebase -i (squash): updating HEAD 7e05da5 HEAD@: rebase -i (pick): updating HEAD
Каждый раз когда по каким-то причинам изменяется вершина вашей ветки, Git сохраняет информацию об этом в эту временную историю. И вы можете указывать старые коммиты, используя эти данные. Например, чтобы посмотреть, куда ссылался указатель HEAD пять шагов назад, используйте ссылку @, которую можно увидеть в выводимых данных команды reflog:
$ git show HEAD@
Этот синтаксис используется и в случае, когда требуется посмотреть, в каком состоянии пребывала ветка некоторое время назад. В частности, чтобы увидеть где была ветка master вчера, следует написать:
$ git show master@
Вы увидите, что было на вершине ветки вчера. Такой способ работает только для данных, которые всё ещё содержатся в вашем журнале ссылок, поэтому вы не можете использовать её для коммитов, которые старше нескольких месяцев.
Для просмотра журнала ссылок в формате, похожем на вывод git log , вы можете выполнить git log -g :
$ git log -g master commit 734713bc047d87bf7eac9674765ae793478c50d3 Reflog: master@ (Scott Chacon ) Reflog message: commit: Fix refs handling, add gc auto, update tests Author: Scott Chacon Date: Fri Jan 2 18:32:33 2009 -0800 Fix refs handling, add gc auto, update tests commit d921970aadf03b3cf0e71becdaab3147ba71cdef Reflog: master@ (Scott Chacon ) Reflog message: merge phedders/rdocs: Merge made by recursive. Author: Scott Chacon Date: Thu Dec 11 15:08:43 2008 -0800 Merge commit 'phedders/rdocs'
Важно отметить, что информация в журнале ссылок строго локальная — это лог того, что вы делали в вашем репозитории. Ссылки не будут такими же в других копиях репозитория; а сразу после первоначального клонирования репозитория, у вас будет пустой журнал ссылок, так как никаких действий в вашем репозитории пока не производилось. Команда git show HEAD@ будет работать только если вы клонировали проект по крайней мере два месяца назад — если вы клонировали его пять минут назад, то не получите никаких результатов.
Воспринимайте reflog Git как историю командной строки
Если у вас есть опыт работы с UNIX или Linux, можете думать о reflog как об истории командной строки Git, которая подчеркивает, что то, что там есть, явно актуально только для вас и вашего «сеанса» и не имеет ничего общего с кем-либо ещё, кто может работать на той же машине.
Примечание
Экранирование фигурных скобок в PowerShell
При использовании PowerShell фигурные скобки, такие как < и >, являются специальными символами и должны быть экранированы. Вы можете экранировать их с помощью апострофа ` или поместить ссылку на коммит в кавычки:
$ git show HEAD@ # НЕ будет работать $ git show HEAD@` # OK $ git show "HEAD@" # OK
Ссылки на предков
Ещё один популярный способ указать коммит — это использовать его родословную. Если вы поместите ^ в конце ссылки, Git поймёт, что нужно использовать родителя этого коммита. Предположим, история вашего проекта выглядит следующим образом:
$ git log --pretty=format:'%h %s' --graph * 734713b Fix refs handling, add gc auto, update tests * d921970 Merge commit 'phedders/rdocs' |\ | * 35cfb2b Some rdoc changes * | 1c002dd Add some blame and merge stuff |/ * 1c36188 Ignore *.gem * 9b29157 Add open3_detach to gemspec file list
Для просмотра предыдущего коммита достаточно написать HEAD^ , что означает «родитель HEAD»:
$ git show HEAD^ commit d921970aadf03b3cf0e71becdaab3147ba71cdef Merge: 1c002dd. 35cfb2b. Author: Scott Chacon Date: Thu Dec 11 15:08:43 2008 -0800 Merge commit 'phedders/rdocs'
Примечание
Экранирование карета в Windows
В командной строке Windows ( cmd.exe ) ^ является специальным символом и требует другого обращения. Вы можете либо удвоить его, либо поместить ссылку на коммит в кавычки:
$ git show HEAD^ # НЕ будет работать в Windows $ git show HEAD^^ # OK $ git show "HEAD^" # OK
Также вы можете указать число после ^ — например, d921970^2 означает «второй родитель коммита d921970». Такой синтаксис полезен только для коммитов слияния, которые имеют больше одного родителя. Первым родителем является ветка, в которую вы выполняли слияние, а вторым — коммит в ветке, которую вы сливали:
$ git show d921970^ commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b Author: Scott Chacon Date: Thu Dec 11 14:58:32 2008 -0800 Add some blame and merge stuff $ git show d921970^2 commit 35cfb2b795a55793d7cc56a6cc2060b4bb732548 Author: Paul Hedderly Date: Wed Dec 10 22:22:03 2008 +0000 Some rdoc changes
Второе важное обозначение для указания предков это символ тильда ~ . Он также соответствует ссылке на первого родителя, поэтому HEAD~ и HEAD^ эквивалентны. Различия становятся заметными, когда вы указываете число. HEAD~2 означает «первый родитель первого родителя» или «дедушка» — при этом происходит переход от заданного предка вглубь указанное число раз. К примеру, для показанной ранее истории, коммитом HEAD~3 будет:
$ git show HEAD~3 commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d Author: Tom Preston-Werner Date: Fri Nov 7 13:47:59 2008 -0500 Ignore *.gem
То же самое можно записать как HEAD~~~ , что также является первым родителем первого родителя первого родителя:
$ git show HEAD~~~ commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d Author: Tom Preston-Werner Date: Fri Nov 7 13:47:59 2008 -0500 Ignore *.gem
Вы также можете совмещать эти обозначения — можно получить второго родителя предыдущей ссылки (предполагается, что это коммит слияния) используя запись HEAD~3^2 , и так далее.
Диапазоны коммитов
Теперь вы умеете указывать отдельные коммиты, давайте посмотрим как указывать диапазоны коммитов. Это в частности полезно для управления вашими ветками — если у вас есть множество веток, вы можете использовать указание диапазонов коммитов для ответа на вопрос «Что было сделано в этой ветке, что я ещё не слил в основную ветку?»
Две точки
Наиболее часто для указания диапазона коммитов используется синтаксис с двумя точками. Таким образом, вы, по сути, просите Git включить в диапазон коммитов только те, которые достижимы из одной, но не достижимы из другой. Для примера предположим, что ваша история выглядит, как представлено на Пример истории для выбора диапазонов коммитов.

Рисунок 136. Пример истории для выбора диапазонов коммитов
Вы хотите посмотреть что находится в вашей экспериментальной ветке, которая ещё не была слита в основную. Вы можете попросить Git отобразить в логе только такие коммиты, используя запись master..experiment — она означает «все коммиты, которые доступны из ветки experiment , но не доступны из ветки master ». Для краткости и наглядности в этих примерах вместо настоящего вывода лога мы будем использовать для коммитов их буквенные обозначения из диаграммы, располагая их в должном порядке:
$ git log master..experiment D C
С другой стороны, если вы хотите наоборот увидеть все коммиты ветки master , которых нет в ветке experiment , вы можете поменять имена веток в команде. При использовании записи experiment..master будут отображены все коммиты ветки master , недоступные из ветки experiment :
$ git log experiment..master F E
Это полезно если вы хотите сохранить ветку experiment в актуальном состоянии и просмотреть, какие изменения нужно в неё слить. Другое частое использование такого синтаксиса — просмотр того, что будет отправлено в удалённый репозиторий.
$ git log origin/master..HEAD
Такая команда покажет вам все коммиты вашей текущей ветки, которые отсутствуют в ветке master удалённого репозитория origin . Если вы выполните git push , находясь на ветке, отслеживающей origin/master , то коммиты, отображённые командой git log origin/master..HEAD , будут теми коммитами, которые отправятся на сервер. Вы также можете опустить одну из частей в такой записи, Git будет считать её равной HEAD . Например, вы можете получить такой же результат как в предыдущем примере, выполнив git log origin/master.. — Git подставит HEAD , если одна часть отсутствует.
Множественная выборка
Запись с двумя точками полезна как сокращение, но, возможно, вы захотите использовать более двух веток для указания нужной ревизии, например, для того, чтобы узнать какие коммиты присутствуют в любой из нескольких веток, но отсутствуют в ветке, в которой вы сейчас находитесь. Git позволяет сделать это, используя символ ^ или опцию —not , перед любой ссылкой, доступные коммиты из которой вы не хотите видеть. Таким образом, следующие три команды эквивалентны:
$ git log refA..refB $ git log ^refA refB $ git log refB --not refA
Этот синтаксис удобен, так как позволяет указывать в запросе более двух ссылок, чего не позволяет сделать синтаксис с двумя точками. Например, если вы хотите увидеть все коммиты, доступные из refA и refB , но не доступные из refC , вы можете использовать одну из следующих команд:
$ git log refA refB ^refC $ git log refA refB --not refC
Это делает систему запросов ревизий более мощной и должно помочь вам лучше понять, что содержится в вашей ветке.
Три точки
Последний основной способ выбора ревизий — это синтаксис с тремя точками, который обозначает все коммиты, доступные хотя бы из одной ссылки, но не из обеих сразу. Вспомните пример истории коммитов в Пример истории для выбора диапазонов коммитов. Если вы хотите узнать какие коммиты есть либо в ветке master , либо в experiment , но не в обеих сразу, вы можете выполнить:
$ git log master. experiment F E D C
Эта команда снова выводит обычный журнал коммитов, но в нём содержится информация только об этих четырёх коммитах, традиционно отсортированная по дате коммитов.
В таких случаях с командой log часто используют опцию —left-right , которая отображает сторону диапазона, с которой был сделан каждый из коммитов. Это делает данную информацию более полезной:
$ git log --left-right master. experiment < F < E >D > C
С помощью этих инструментов, вам будет намного проще указать Git какой коммит или коммиты вы хотите изучить.
7.1 Инструменты Git – Выбор ревизии (коммита)
К этому моменту вы уже изучили большинство повседневных команд и способов организации рабочего процесса, которые необходимы для управления Git репозиторием, используемым для управления вашим исходным кодом. Вы выполнили основные задания по отслеживанию и сохранению файлов в Git, вооружились мощью области подготовленных изменений (индекса), легковесного ветвления и слияния.
Теперь настало время познакомиться с некоторыми очень мощными возможностями Git, которые при повседневной работе вам, наверное, не потребуются, но в какой-то момент могут оказаться полезными.
Git позволяет различными способами указать коммиты или их диапазоны. Эти способы не всегда очевидны, но их полезно знать.
Одиночные ревизии
Конечно, вы можете ссылаться на коммит по его хешу SHA-1, но существуют более удобные для человека способы. В данном разделе описываются различные способы обращения к одному коммиту.
Сокращённый SHA-1
Git достаточно умен, чтобы понять какой коммит имеется ввиду по нескольким первым символам его хеша, если указанная часть SHA-1 имеет в длину, по крайней мере, четыре символа и однозначна – то есть в текущем репозитории существует только один объект с таким частичным SHA-1.
Например, предположим, чтобы найти некоторый коммит, вы выполнили команду git log и нашли коммит, в котором добавили определённую функциональность:
$ git log commit 734713bc047d87bf7eac9674765ae793478c50d3 Author: Scott Chacon Date: Fri Jan 2 18:32:33 2009 -0800 Fix refs handling, add gc auto, update tests commit d921970aadf03b3cf0e71becdaab3147ba71cdef Merge: 1c002dd. 35cfb2b. Author: Scott Chacon Date: Thu Dec 11 15:08:43 2008 -0800 Merge commit 'phedders/rdocs' commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b Author: Scott Chacon Date: Thu Dec 11 14:58:32 2008 -0800 Add some blame and merge stuff
Предположим, что в нашем примере это коммит 1c002dd… . Если вы хотите выполнить для него git show , то следующие команды эквиваленты (предполагается, что сокращения однозначны):
$ git show 1c002dd4b536e7479fe34593e72e6c6c1819e53b $ git show 1c002dd4b536e7479f $ git show 1c002d
Git может вычислить уникальные сокращения для ваших значений SHA-1. Если вы передадите опцию —abbrev-commit команде git log , в выводе будут использоваться сокращённые значения, сохраняющие уникальность; по умолчанию используется семь символов, но для сохранения уникальности SHA-1 могут использоваться и более длинные значения.
$ git log --abbrev-commit --pretty=oneline ca82a6d Change the version number 085bb3b Remove unnecessary test code a11bef0 Initial commit
Обычно от восьми до десяти символов более чем достаточно для сохранения уникальности значений в проекте.
Например, в ядре Linux, который является довольно большим проектом с более чем 450 тыс. коммитов и 3.6 млн. объектов, отсутствуют объекты, чьи SHA-1 совпадают более, чем в 11 первых символах.
Примечание
Небольшое замечание о SHA-1
Большинство людей в этом месте начинают беспокоиться о том, что будет, если у них в репозитории случайно появятся два объекта с одинаковыми значениями SHA-1. Что тогда?
Если вы вдруг зафиксируете объект, который имеет такое же значение SHA-1, как и предыдущий объект в вашем репозитории, Git увидит этот предыдущий объект в своей базе и посчитает, что он уже был записан. Если вы позже попытаетесь переключиться на этот объект, то вы всегда будете получать данные первого объекта.
Однако, вы должны осознавать, насколько маловероятен такой сценарий. Длина SHA-1 составляет 20 байт или 160 бит. Количество случайно хешированных объектов, необходимых для достижения 50% вероятности возникновения коллизии, равно примерно 2 80 (формула для определения вероятности возникновения коллизии p = (n(n-1)/2) * (1/2^160)). 2 80 – это 1.2 × 10 24 , или 1 миллион миллиардов миллиардов, что в 1200 раз больше количества песчинок на земле.
Приведём пример, чтобы дать вам представление, чего будет стоить получение коллизии SHA-1. Если бы все 6.5 миллиардов человек на Земле были программистами, и ежесекундно каждый из них производил количество кода, эквивалентное всей истории ядра Linux (3.6 миллиона Git-объектов), и отправлял его в один огромный Git репозиторий, то потребовалось бы около 2 лет, пока этот репозиторий накопил бы количество объектов, достаточное для 50% вероятности возникновения коллизии SHA-1. Более вероятно, что каждый член вашей команды в одну и туже ночь будет атакован и убит волками в несвязанных друг с другом происшествиях.
Если выделить на это несколько тысяч долларов вычислительной мощности, можно будет синтезировать два файла с одним и тем же хешем, что было доказано проектом https://shattered.io/ в феврале 2017 года. Git движется к использованию SHA256 в качестве алгоритма хеширования по умолчанию, который намного более устойчив к атакам с коллизиями и имеет код, помогающий смягчить эту атаку (хотя он не может полностью ее устранить).
Ссылки на ветки
Для наиболее простого способа указать коммит требуется существование ветки, указывающей на этот коммит. Тогда вы можете использовать имя ветки в любой команде Git, которая ожидает коммит или значение SHA-1. Например, если вы хотите просмотреть последний коммит в ветке, то следующие команды эквивалентны (предполагается, что ветка topic1 указывает на коммит ca82a6d ):
$ git show ca82a6dff817ec66f44342007202690a93763949 $ git show topic1
Если вы хотите узнать SHA-1 объекта, на который указывает ветка, или увидеть, к чему сводятся все примеры в терминах SHA-1, то вы можете воспользоваться служебной командой Git rev-parse . Служебные команды подробно рассмотрены в главе «Git изнутри»; в основном, команда rev-parse предназначена для низкоуровневых операций, а не для ежедневного использования. Однако она может быть полезна, когда вам нужно увидеть, что происходит в действительности. Теперь вы можете выполнить rev-parse для вашей ветки.
$ git rev-parse topic1 ca82a6dff817ec66f44342007202690a93763949
Сокращения журнала ссылок
Одна из вещей, которую Git делает в фоновом режиме, является ведение журнала ссылок, в котором сохраняется то, куда указывали HEAD и ветки за последние несколько месяцев.
Для просмотра этого журнала используется команда git reflog :
$ git reflog 734713b HEAD@: commit: Fix refs handling, add gc auto, update tests d921970 HEAD@: merge phedders/rdocs: Merge made by the 'recursive' strategy. 1c002dd HEAD@: commit: Add some blame and merge stuff 1c36188 HEAD@: rebase -i (squash): updating HEAD 95df984 HEAD@: commit: # This is a combination of two commits. 1c36188 HEAD@: rebase -i (squash): updating HEAD 7e05da5 HEAD@: rebase -i (pick): updating HEAD
Каждый раз, когда по каким-то причинам изменяется вершина вашей ветки, Git сохраняет информацию об этом в эту временную историю. И вы можете указывать старые коммиты, используя эти данные. Например, чтобы посмотреть, куда ссылался указатель HEAD пять шагов назад, используйте ссылку @ , которую можно увидеть в выводимых данных команды reflog :
$ git show HEAD@
Этот синтаксис используется и в случае, когда требуется посмотреть, в каком состоянии пребывала ветка некоторое время назад. В частности, чтобы увидеть, где была ветка master вчера, следует написать:
$ git show master@
Вы увидите, что было на вершине ветки вчера. Такой способ работает только для данных, которые всё ещё содержатся в вашем журнале ссылок, поэтому вы не можете использовать её для коммитов, которые старше нескольких месяцев.
Для просмотра журнала ссылок в формате, похожем на вывод git log , вы можете выполнить git log -g :
$ git log -g master commit 734713bc047d87bf7eac9674765ae793478c50d3 Reflog: master@ (Scott Chacon ) Reflog message: commit: Fix refs handling, add gc auto, update tests Author: Scott Chacon Date: Fri Jan 2 18:32:33 2009 -0800 Fix refs handling, add gc auto, update tests commit d921970aadf03b3cf0e71becdaab3147ba71cdef Reflog: master@ (Scott Chacon ) Reflog message: merge phedders/rdocs: Merge made by recursive. Author: Scott Chacon Date: Thu Dec 11 15:08:43 2008 -0800 Merge commit 'phedders/rdocs'
Важно отметить, что информация в журнале ссылок строго локальная – это лог того, что вы делали в вашем репозитории. Ссылки не будут такими же в других копиях репозитория; а сразу после первоначального клонирования репозитория, у вас будет пустой журнал ссылок, так как никаких действий в вашем репозитории пока не производилось. Команда git show HEAD@ будет работать, только если вы клонировали проект, по крайней мере, два месяца назад – если вы клонировали его пять минут назад, то не получите никаких результатов.
Подсказка
Воспринимайте reflog в Git как историю командной строки
Если у вас есть опыт работы с UNIX или Linux, можете думать о reflog как об истории командной строки Git, которая подчеркивает, что то, что там есть, явно актуально только для вас и вашего «сеанса» и не имеет ничего общего с кем-либо еще, кто может работать на той же машине.
Примечание
Экранирование фигурных скобок в PowerShell
При использовании PowerShell фигурные скобки, такие как < и >, являются специальными символами и должны быть экранированы. Вы можете экранировать их с помощью апострофа ` или поместить ссылку на коммит в кавычки:
$ git show HEAD@ # НЕ будет работать $ git show HEAD@` # OK $ git show "HEAD@" # OK
Ссылки на предков
Ещё один популярный способ указать коммит – это использовать её родословную. Если вы поместите ^ в конце ссылки, Git поймёт, что нужно использовать родителя этого коммита. Предположим, история вашего проекта выглядит следующим образом:
$ git log --pretty=format:'%h %s' --graph * 734713b Fix refs handling, add gc auto, update tests * d921970 Merge commit 'phedders/rdocs' |\ | * 35cfb2b Some rdoc changes * | 1c002dd Add some blame and merge stuff |/ * 1c36188 Ignore *.gem * 9b29157 Add open3_detach to gemspec file list
Для просмотра предыдущего коммита достаточно написать HEAD^ , что означает «родитель HEAD »:
$ git show HEAD^ commit d921970aadf03b3cf0e71becdaab3147ba71cdef Merge: 1c002dd. 35cfb2b. Author: Scott Chacon Date: Thu Dec 11 15:08:43 2008 -0800 Merge commit 'phedders/rdocs'
Примечание
Экранирование символа карета в Windows
В командной строке Windows (cmd.exe) ^ является специальным символом и требует другого обращения. Вы можете либо удвоить его, либо поместить ссылку на коммит в кавычки:
$ git show HEAD^ # НЕ будет работать в Windows $ git show HEAD^^ # OK $ git show "HEAD^" # OK
Также вы можете указать число после ^ – например, d921970^2 означает «второй родитель коммита d921970 ». Такой синтаксис полезен только для коммитов слияния, которые имеют больше одного родителя. Первым родителем является ветка, в которую вы выполняли слияние, а вторым – коммит в ветке, которую вы сливали:
$ git show d921970^ commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b Author: Scott Chacon Date: Thu Dec 11 14:58:32 2008 -0800 Add some blame and merge stuff $ git show d921970^2 commit 35cfb2b795a55793d7cc56a6cc2060b4bb732548 Author: Paul Hedderly Date: Wed Dec 10 22:22:03 2008 +0000 Some rdoc changes
Второе важное обозначение для указания предков – это символ тильда ~ . Он также соответствует ссылке на первого родителя, поэтому HEAD~ и HEAD^ эквивалентны. Различия становятся заметными, когда вы указываете число. HEAD~2 означает «первый родитель первого родителя» или «дедушка» – при этом происходит переход от заданного предка вглубь указанное число раз. К примеру, для показанной ранее истории, коммитом HEAD~3 будет:
$ git show HEAD~3 commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d Author: Tom Preston-Werner Date: Fri Nov 7 13:47:59 2008 -0500 Ignore *.gem
То же самое можно записать как HEAD~~~ , что также является первым родителем первого родителя первого родителя:
$ git show HEAD~~~ commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d Author: Tom Preston-Werner Date: Fri Nov 7 13:47:59 2008 -0500 Ignore *.gem
Вы также можете совмещать эти обозначения – можно получить второго родителя предыдущей ссылки (предполагается, что это коммит слияния) используя запись HEAD~3^2 , и так далее.
Диапазоны коммитов
Теперь вы умеете указывать отдельные коммиты; давайте посмотрим, как указывать диапазоны коммитов. Это в частности полезно для управления вашими ветками – если у вас есть множество веток, вы можете использовать указание диапазонов коммитов для ответа на вопрос «Что было сделано в этой ветке, что я ещё не слил в основную ветку?»
Две точки
Наиболее часто для указания диапазона коммитов используется синтаксис с двумя точками. Таким образом, вы, по сути, просите Git включить в диапазон коммитов только те, которые достижимы из одной, но не достижимы из другой. Для примера предположим, что ваша история выглядит, как представлено на рисунке 136.

Вы хотите посмотреть, что находится в вашей экспериментальной ветке, которая ещё не была слита в основную. Вы можете попросить Git отобразить в логе только такие коммиты, используя запись master..experiment – она означает «все коммиты, которые доступны из ветки experiment , но не доступны из ветки master ». Для краткости и наглядности в этих примерах вместо настоящего вывода лога мы будем использовать для коммитов их буквенные обозначения из диаграммы, располагая их в должном порядке:
$ git log master..experiment D C
И напротив, если вы хотите наоборот увидеть все коммиты ветки master , которых нет в ветке experiment , вы можете поменять местами имена веток в команде. При использовании записи experiment..master будут отображены все коммиты ветки master , недоступные из ветки experiment :
$ git log experiment..master F E
Это полезно, если вы хотите сохранить ветку experiment в актуальном состоянии и просмотреть, какие изменения нужно в нее слить. Другое частое использование такого синтаксиса – просмотр того, что будет отправлено в удалённый репозиторий.
$ git log origin/master..HEAD
Такая команда покажет вам все коммиты вашей текущей ветки, которые отсутствуют в ветке master удалённого репозитория origin . Если вы выполните git push , находясь на ветке, отслеживающей origin/master , то коммиты, отображённые командой git log origin/master..HEAD , будут теми коммитами, которые отправятся на сервер. Вы также можете опустить одну из частей в такой записи, Git будет считать её равной HEAD . Например, вы можете получить такой же результат как в предыдущем примере, выполнив git log origin/master.. , – Git подставит HEAD , если одна часть отсутствует.
Множественная выборка
Запись с двумя точками полезна как сокращение, но, возможно, вы захотите использовать более двух веток для указания нужной ревизии, например, для того, чтобы узнать какие коммиты присутствуют в любой из нескольких веток, но отсутствуют в ветке, в которой вы сейчас находитесь. Git позволяет сделать это, используя символ ^ или опцию —not перед любой ссылкой, доступные коммиты из которой вы не хотите видеть. Таким образом, следующие три команды эквивалентны:
$ git log refA..refB $ git log ^refA refB $ git log refB --not refA
Этот синтаксис удобен, так как позволяет указывать в запросе более двух ссылок, чего не позволяет сделать синтаксис с двумя точками. Например, если вы хотите увидеть все коммиты, доступные из refA и refB , но не доступные из refC , вы можете использовать одну из следующих команд:
$ git log refA refB ^refC $ git log refA refB --not refC
Это делает систему запросов ревизий более мощной и должно помочь вам лучше понять, что содержится в вашей ветке.
Три точки
Последний основной способ выбора ревизий – это синтаксис с тремя точками, который обозначает все коммиты, доступные хотя бы из одной ссылки, но не из обеих сразу. Вспомните пример истории коммитов на рисунке 136. Если вы хотите узнать, какие коммиты есть либо в ветке master , либо в experiment , но не в обеих сразу, вы можете выполнить:
$ git log master. experiment F E D C
Эта команда снова выводит обычный журнал коммитов, но в нем содержится информация только об этих четырёх коммитах, обычно отсортированных по дате.
В таких случаях с командой log часто используют опцию —left-right , которая отображает сторону диапазона, с которой был сделан каждый из коммитов. Это делает данную информацию более полезной:
$ git log --left-right master. experiment < F < E >D > C
С помощью этих инструментов, вам будет намного проще указать Git, какой коммит или коммиты вы хотите изучить.
Выбор ревизии
Git позволяет вам указывать конкретные коммиты или их последовательности несколькими способами. Они не всегда очевидны, но иногда их полезно знать.
Одиночные ревизии
Вы можете просто сослаться на коммит по его SHA-1 хешу, но также существуют более понятные для человека способы ссылаться на коммиты. В этом разделе кратко описаны различные способы обратиться к одному определённому коммиту.
Сокращенный SHA
Git достаточно умён для того, чтобы понять какой коммит вы имеете в виду по первым нескольким символам (частичному хешу), конечно, если их не меньше четырёх и они однозначны, то есть если хеш только одного объекта в вашем репозитории начинается с этих символов. Например, предположим, что вы хотите посмотреть содержимое какого-то конкретного коммита. Вы выполняете команду git log и находите этот коммит (например тот, в котором вы добавили какую-то функциональность): $ git log commit 734713bc047d87bf7eac9674765ae793478c50d3 Author: Scott Chacon Date: Fri Jan 2 18:32:33 2009 -0800 fixed refs handling, added gc auto, updated tests commit d921970aadf03b3cf0e71becdaab3147ba71cdef Merge: 1c002dd. 35cfb2b. Author: Scott Chacon Date: Thu Dec 11 15:08:43 2008 -0800 Merge commit ‘phedders/rdocs’ commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b Author: Scott Chacon Date: Thu Dec 11 14:58:32 2008 -0800 added some blame and merge stuff В нашем случае, выберем коммит 1c002dd. Если вы будете использовать git show , чтобы посмотреть содержимое этого коммита следующие команды эквивалентны (предполагая, что сокращенные версии однозначны): $ git show 1c002dd4b536e7479fe34593e72e6c6c1819e53b $ git show 1c002dd4b536e7479f $ git show 1c002d Git может показать короткие, уникальные сокращения ваших SHA-1 хешей. Если вы передадите опцию —abbrev-commit команде git log , то её вывод будет использовать сокращённые значения, сохраняя их уникальными; по умолчанию будут использоваться семь символов, но при необходимости длина будет увеличена для сохранения однозначности хешей: $ git log —abbrev-commit —pretty=oneline ca82a6d changed the version number 085bb3b removed unnecessary test code a11bef0 first commit В общем случае, восемь-десять символов более чем достаточно для уникальности внутри проекта. В одном из самых больших проектов на Git, ядре Linux только начинает появляться необходимость использовать 12 символов из 40 возможных для сохранения уникальности.
Небольшое замечание о SHA-1
Многие люди интересуются, что произойдет, если они в какой-то момент, по некоторой случайности, получат два объекта в репозитории, которые будут иметь два одинаковых значения SHA-1 хеша. Что тогда? Если вы вдруг закоммитите объект, SHA-1 хеш которого такой же, как у некоторого предыдущего объекта в вашем репозитории, Git обнаружит предыдущий объект в вашей базе данных Git, и посчитает, что он был уже записан. Если вы в какой-то момент попытаетесь получить этот объект опять, вы всегда будете получать данные первого объекта. Однако, вы должны осознавать то, как смехотворно маловероятен этот сценарий. Длина SHA-1 составляет 20 байт или 160 бит. Количество случайно хешированных объектов, необходимое для того, чтобы получить 50% вероятность одиночного совпадения составляет порядка 2^80 (формула для определения вероятности совпадения: p = (n(n-1)/2) * (1/2^160))) . 2^80 это 1.2 x 10^24 или один миллион миллиарда миллиардов. Это в 1200 раз больше количества песчинок на земле. Вот пример для того, чтобы вы поняли, что необходимо, чтобы получить SHA-1 коллизию. Если бы все 6.5 миллиардов людей на Земле программировали, и каждую секунду каждый из них производил количество кода, эквивалентное всей истории ядра Linux (1 миллион Git объектов) и отправлял его в один огромный Git-репозиторий, то потребовалось бы 5 лет для того, чтобы заполнить репозиторий достаточно для того, чтобы получить 50% вероятность единичной SHA-1 коллизии. Более вероятно, что каждый член вашей команды программистов будет атакован и убит волками в несвязанных друг с другом случаях в одну и ту же ночь.
Ссылки на ветки
Для самого прямого метода указать коммит необходимо, чтобы этот коммит имел ветку ссылающуюся на него. Тогда, вы можете использовать имя ветки в любой команде Git, которая ожидает коммит или значение SHA-1. Например, если вы хотите посмотреть последний коммит в ветке, следующие команды эквивалентны, предполагая, что ветка topic1 ссылается на ca82a6d : $ git show ca82a6dff817ec66f44342007202690a93763949 $ git show topic1 Чтобы посмотреть на какой именно SHA указывает ветка, или понять для какого-то из приведённых примеров к каким SHA он сводится, можно использовать служебную (plumbing) утилиту Git, которая называется rev-parse . Вы можете заглянуть в Главу 9 для получения большей информации о служебных утилитах; в основном rev-parse нужна для выполнения низкоуровневых операций и не предназначена для использования в повседневной работе. Однако, она может пригодиться, если вам необходимо разобраться, что происходит на самом деле. Сейчас вы можете попробовать применить rev-parse к своей ветке. $ git rev-parse topic1 ca82a6dff817ec66f44342007202690a93763949
RefLog-сокращения
Одна из вещей, которую Git делает в фоновом режиме, пока вы работаете, это запоминание ссылочного лога — лога того, где находились HEAD и ветки в течение последних нескольких месяцев. Ссылочный лог можно просмотреть с помощью git reflog : $ git reflog 734713b. HEAD@<0>: commit: fixed refs handling, added gc auto, updated d921970. HEAD@: merge phedders/rdocs: Merge made by recursive. 1c002dd. HEAD@: commit: added some blame and merge stuff 1c36188. HEAD@: rebase -i (squash): updating HEAD 95df984. HEAD@: commit: # This is a combination of two commits. 1c36188. HEAD@: rebase -i (squash): updating HEAD 7e05da5. HEAD@: rebase -i (pick): updating HEAD Каждый раз, когда верхушка ветки обновляется по какой-либо причине, Git сохраняет эту информацию в эту временную историю. И вы можете использовать и эти данные, чтобы задать прошлый коммит. Если вы хотите посмотреть какое значение HEAD имел пять шагов назад для своего репозитория, вы можете использовать ссылку вида @ , как показано в выводе команды reflog : $ git show HEAD@ Также вы можете использовать эту команду, чтобы увидеть, где ветка была некоторое время назад. Например, чтобы увидеть, где была ветка master вчера, наберите $ git show master@ Эта команда покажет, где верхушка ветки находилась вчера. Такой подход работает только для данных, которые всё ещё находятся в ссылочном логе. Так что вы не сможете использовать его для коммитов с давностью в несколько месяцев. Чтобы просмотреть информацию ссылочного лога в таком же формате как вывод git log , можно выполнить git log -g : $ git log -g master commit 734713bc047d87bf7eac9674765ae793478c50d3 Reflog: master@ <0>(Scott Chacon ) Reflog message: commit: fixed refs handling, added gc auto, updated Author: Scott Chacon Date: Fri Jan 2 18:32:33 2009 -0800 fixed refs handling, added gc auto, updated tests commit d921970aadf03b3cf0e71becdaab3147ba71cdef Reflog: master@ (Scott Chacon ) Reflog message: merge phedders/rdocs: Merge made by recursive. Author: Scott Chacon Date: Thu Dec 11 15:08:43 2008 -0800 Merge commit ‘phedders/rdocs’ Важно отметить, что информация в ссылочном логе строго локальная — это лог того, чем вы занимались со своим репозиторием. Ссылки не будут теми же самыми в чьей-то чужой копии репозитория; и после того как вы только что склонировали репозиторий, ссылочный лог будет пустым, так как вы ещё ничего не делали со своим репозиторием. Команда git show HEAD@ сработает только если вы склонировали свой проект как минимум два месяца назад. Если вы склонировали его пять минут назад, то вы ничего не получите.0>
Ссылки на предков
Ещё один основной способ указать коммит — указать коммит через его предков. Если поставить ^ в конце ссылки, для Git это будет означать родителя этого коммита. Допустим история вашего проекта выглядит следующим образом: $ git log —pretty=format:’%h %s’ —graph * 734713b fixed refs handling, added gc auto, updated tests * d921970 Merge commit ‘phedders/rdocs’ |\ | * 35cfb2b Some rdoc changes * | 1c002dd added some blame and merge stuff |/ * 1c36188 ignore *.gem * 9b29157 add open3_detach to gemspec file list В этом случае вы можете посмотреть предыдущий коммит указав HEAD^ , что означает “родитель HEAD ”: $ git show HEAD^ commit d921970aadf03b3cf0e71becdaab3147ba71cdef Merge: 1c002dd. 35cfb2b. Author: Scott Chacon Date: Thu Dec 11 15:08:43 2008 -0800 Merge commit ‘phedders/rdocs’ Вы также можете указать некоторое число после ^ . Например, d921970^2 означает “второй родитель коммита d921970 ”. Такой синтаксис полезен только для коммитов-слияний, которые имеют больше, чем одного родителя. Первый родитель это ветка, на которой вы находились во время слияния, а второй — коммит на ветке, которая была слита: $ git show d921970^ commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b Author: Scott Chacon Date: Thu Dec 11 14:58:32 2008 -0800 added some blame and merge stuff $ git show d921970^2 commit 35cfb2b795a55793d7cc56a6cc2060b4bb732548 Author: Paul Hedderly
Date: Wed Dec 10 22:22:03 2008 +0000 Some rdoc changes
Другое основное обозначение для указания на предков это ~ . Это тоже ссылка на первого родителя, поэтому HEAD~ и HEAD^ эквивалентны. Различия становятся очевидными, только когда вы указываете число. HEAD~2 означает первого родителя первого родителя HEAD или прародителя — это переход по первым родителям указанное количество раз. Например, для показанной выше истории, HEAD~3 будет $ git show HEAD~3 commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d Author: Tom Preston-Werner Date: Fri Nov 7 13:47:59 2008 -0500 ignore *.gem То же самое можно записать как HEAD^^^ , что опять же означает первого родителя первого родителя первого родителя: $ git show HEAD^^^ commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d Author: Tom Preston-Werner Date: Fri Nov 7 13:47:59 2008 -0500 ignore *.gem Кроме того, можно комбинировать эти обозначения. Например, можно получить второго родителя для предыдущей ссылки (мы предполагаем, что это коммит-слияние) написав HEAD~3^2 , ну и так далее.
Диапазон коммитов
Теперь, когда вы умеете задавать отдельные коммиты, разберёмся как указать диапазон коммитов. Это особенно полезно при управлении ветками — если у вас много веток, вы можете использовать обозначения диапазонов, чтобы ответить на вопросы типа “Какие в этой ветке есть коммиты, которые не были слиты в основную ветку?”
Две точки
Наиболее распространённый способ задать диапазон коммитов — это запись с двумя точками. По существу, таким образом вы просите Git взять набор коммитов достижимых из одного коммита, но не достижимых из другого. Например, пускай ваша история коммитов выглядит так как показано на Рисунке 6-1.
Рисунок 6-1. Пример истории для выбора набора коммитов
Допустим, вы хотите посмотреть что в вашей ветке experiment ещё не было слито в ветку master . Можно попросить Git показать вам лог только таких коммитов с помощью master..experiment — эта запись означает “все коммиты достижимые из experiment , которые недостижимы из master ”. Для краткости и большей понятности в примерах мы будем использовать буквы для обозначения коммитов на диаграмме вместо настоящего вывода лога в том порядке в каком они будут отображены: $ git log master..experiment D C С другой стороны, если вы хотите получить обратное — все коммиты в master , которых нет в experiment , можно переставить имена веток. Запись experiment..master покажет всё, что есть в master , но недостижимо из experiment : $ git log experiment..master F E Такое полезно если вы хотите, чтобы ветка experiment была обновлённой, и хотите посмотреть, что вы собираете в неё слить. Ещё один частый случай использования этого синтаксиса — посмотреть, что вы собираетесь отправить на удалённый сервер: $ git log origin/master..HEAD Эта команда покажет вам все коммиты в текущей ветке, которых нет в ветке master на сервере origin . Если бы вы выполнили git push , при условии, что текущая ветка отслеживает origin/master , то коммиты, которые перечислены в выводе git log origin/master..HEAD это те коммиты, которые были бы отправлены на сервер. Кроме того, можно опустить одну из сторон в такой записи — Git подставит туда HEAD . Например, вы можете получить такой же результат как и в предыдущем примере, набрав git log origin/master.. — Git подставит HEAD сам если одна из сторон отсутствует.
Множество вершин
Запись с двумя точками полезна как сокращение, но, возможно, вы захотите указать больше двух веток, чтобы указать нужную ревизию. Например, чтобы посмотреть, какие коммиты находятся в одной из нескольких веток, но не в текущей. Git позволяет сделать это с помощью использования либо символа ^ , либо —not перед любыми ссылками, коммиты достижимые из которых вы не хотите видеть. Таким образом, следующие три команды эквивалентны: $ git log refA..refB $ git log ^refA refB $ git log refB —not refA Это удобно, потому что с помощью такого синтаксиса можно указать более двух ссылок в своём запросе, чего вы не сможете сделать с помощью двух точек. Например, если вы хотите увидеть все коммиты достижимые из refA или refB , но не из refC , можно набрать одну из таких команд: $ git log refA refB ^refC $ git log refA refB —not refC Всё это делает систему выбора ревизий очень мощной, что должно помочь вам определять, что содержится в ваших ветках.
Три точки
Последняя основная запись для выбора диапазона коммитов — это запись с тремя точками, которая означает те коммиты, которые достижимы по одной из двух ссылок, но не по обеим одновременно. Вернёмся к примеру истории коммитов на Рисунке 6-1. Если вы хотите увидеть, что находится в master или experiment , но не в обоих сразу, выполните $ git log master. experiment F E D C Повторимся, что это даст вам стандартный log -вывод, но покажет только информацию об этих четырёх коммитах упорядоченных по дате коммита как и обычно. В этом случае вместе с командой log обычно используют параметр —left-right , который показывает, на какой стороне диапазона находится каждый коммит. Это помогает сделать данные полезнее: $ git log —left-right master. experiment < F < E >D > C С помощью этих инструментов, вы можете намного легче объяснить Git, какой коммит или коммиты вы хотите изучить. Pro Git