Git как найти коммит по хеш

I need to find a commit in Git by a given hash, SHA. For example, if I have the «a2c25061» hash, and I need to get the author and the committer of this commit.

What is the command to get that?

Flip's user avatar

Flip

6,0937 gold badges44 silver badges75 bronze badges

asked Jan 5, 2013 at 0:51

Ghadeer's user avatar

0

Just use the following command

git show a2c25061

6

git log -1 --format="%an %ae%n%cn %ce" a2c25061

The Pretty Formats section of the git show documentation contains

  • format:<string>

The format:<string> format allows you to specify which information you want to show. It works a little bit like printf format, with the notable exception that you get a newline with %n instead of n

The placeholders are:

  • %an: author name
  • %ae: author email
  • %cn: committer name
  • %ce: committer email

Community's user avatar

answered Jan 5, 2013 at 1:29

Greg Bacon's user avatar

Greg BaconGreg Bacon

134k31 gold badges187 silver badges245 bronze badges

1

There are two ways to do this.

1. providing the SHA of the commit you want to see to git log

git log -p a2c25061

Where -p is short for patch

2. use git show

git show a2c25061

The output for both commands will be:

  • the commit
  • the author
  • the date
  • the commit message
  • the patch information

answered Dec 28, 2019 at 18:55

Yamona's user avatar

YamonaYamona

1,0401 gold badge16 silver badges36 bronze badges

I am fairly new to Github and have come across an amateur-ish problem.

I have been asked to do a code review and have been provided with a commit hash, however I have tried looking in Git if I can search using commit hashes but couldn’t find anything.

Is there a way I can find the changed code just by using the commit hash?

frederj's user avatar

frederj

1,4459 silver badges20 bronze badges

asked Aug 31, 2012 at 11:48

dopplesoldner's user avatar

dopplesoldnerdopplesoldner

8,77312 gold badges43 silver badges55 bronze badges

5

A URL of the form https://github.com/<owner>/<project>/commit/<hash> will show you the changes introduced in that commit. For example here’s a recent bugfix I made to one of my projects on GitHub:

https://github.com/jerith666/git-graph/commit/35e32b6a00dec02ae7d7c45c6b7106779a124685

You can also shorten the hash to any unique prefix, like so:

https://github.com/jerith666/git-graph/commit/35e32b


I know you just asked about GitHub, but for completeness: If you have the repository checked out, from the command line, you can achieve basically the same thing with either of these commands (unique prefixes work here too):

git show 35e32b6a00dec02ae7d7c45c6b7106779a124685
git log -p -1 35e32b6a00dec02ae7d7c45c6b7106779a124685

Note: If you shorten the commit hash too far, the command line gives you a helpful disambiguation message, but GitHub will just return a 404.

answered Aug 31, 2012 at 11:52

Matt McHenry's user avatar

Matt McHenryMatt McHenry

19.8k8 gold badges65 silver badges64 bronze badges

10

View single commit:
https://github.com/<user>/<project>/commit/<hash>

View log:
https://github.com/<user>/<project>/commits/<hash>

View full repo:
https://github.com/<user>/<project>/tree/<hash>

<hash> can be any length as long as it is unique.

answered Jan 20, 2015 at 19:18

qwertzguy's user avatar

2

The ability to search commits has recently been added to GitHub.

To search for a hash, just enter at least the first 7 characters in the search box. Then on the results page, click the «Commits» tab to see matching commits (but only on the default branch, usually master), or the «Issues» tab to see pull requests containing the commit.

To be more explicit you can add the hash: prefix to the search, but it’s not really necessary.

There is also a REST API (at the time of writing it is still in preview).

answered May 31, 2017 at 0:30

Todd Owen's user avatar

Todd OwenTodd Owen

15.6k7 gold badges53 silver badges52 bronze badges

4

With the GitHub CLI gh v2.22.0 (Jan. 2023), you can search from within your local cloned GitHub repository:

See gh search commits:

Examples:

# search commits matching hash "8dd03144ffdc6c0d486d6b705f9c7fba871ee7c3"
$ gh search commits --hash=8dd03144ffdc6c0d486d6b705f9c7fba871ee7c3

But also:

# search commits matching set of keywords "readme" and "typo"
$ gh search commits readme typo

# search commits matching phrase "bug fix"
$ gh search commits "bug fix"

# search commits committed by user "monalisa"
$ gh search commits --committer=monalisa

answered Jan 26 at 0:00

VonC's user avatar

VonCVonC

1.2m516 gold badges4333 silver badges5150 bronze badges

Вне зависимости от размера кодовой базы, часто возникает необходимость поиска места вызова/определения функции или получения истории изменения метода.
Git предоставляет несколько полезных утилит, с помощью которых легко и просто осуществлять поиск по коду и коммитам.
Мы обсудим некоторые из них.

Команда git grep

Git поставляется с командой grep, которая позволяет легко искать в истории коммитов или в рабочем каталоге по строке или регулярному выражению.
В следующих примерах, мы обратимся к исходному коду самого Git.

По умолчанию эта команда ищет по файлам в рабочем каталоге.
В качестве первого варианта вы можете использовать любой из параметров -n или --line-number, чтобы распечатать номера строк, в которых Git нашел совпадения:

$ git grep -n gmtime_r
compat/gmtime.c:3:#undef gmtime_r
compat/gmtime.c:8:      return git_gmtime_r(timep, &result);
compat/gmtime.c:11:struct tm *git_gmtime_r(const time_t *timep, struct tm *result)
compat/gmtime.c:16:     ret = gmtime_r(timep, result);
compat/mingw.c:826:struct tm *gmtime_r(const time_t *timep, struct tm *result)
compat/mingw.h:206:struct tm *gmtime_r(const time_t *timep, struct tm *result);
date.c:482:             if (gmtime_r(&now, &now_tm))
date.c:545:             if (gmtime_r(&time, tm)) {
date.c:758:             /* gmtime_r() in match_digit() may have clobbered it */
git-compat-util.h:1138:struct tm *git_gmtime_r(const time_t *, struct tm *);
git-compat-util.h:1140:#define gmtime_r git_gmtime_r

В дополнение к базовому поиску, показанному выше, git grep поддерживает множество других интересных параметров.

Например, вместо того, чтобы печатать все совпадения, вы можете попросить git grep обобщить выводимые командой данные, показав только те файлы, в которых обнаружены совпадения, вместе с количеством этих совпадений в каждом файле. Для этого потребуется параметр -c или --count:

$ git grep --count gmtime_r
compat/gmtime.c:4
compat/mingw.c:1
compat/mingw.h:1
date.c:3
git-compat-util.h:2

Если вас интересует контекст строки поиска, можно показать метод или функцию, в котором присутствует совпадение с помощью параметра -p или --show-function:

$ git grep -p gmtime_r *.c
date.c=static int match_multi_number(timestamp_t num, char c, const char *date,
date.c:         if (gmtime_r(&now, &now_tm))
date.c=static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt)
date.c:         if (gmtime_r(&time, tm)) {
date.c=int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset)
date.c:         /* gmtime_r() in match_digit() may have clobbered it */

Здесь вы можете видеть, что gmtime_r вызывается из функций match_multi_number и match_digit в файле date.c (третье отображаемое совпадение представляет собой только строку, появившуюся в комментарии).

Вы также можете искать сложные комбинации строк, используя опцию --and, которая гарантирует, что будут отображены только строки, имеющие сразу несколько совпадений.
Например, давайте поищем любые строки, которые определяют константу, имя которой содержит любую из подстрок «LINK» или «BUF_MAX», особенно в более старой версии кодовой базы Git, представленной тегом v1.8.0 (мы добавим параметры --break и --heading, которые помогут вывести результаты в более читаемом виде):

$ git grep --break --heading 
    -n -e '#define' --and ( -e LINK -e BUF_MAX ) v1.8.0
v1.8.0:builtin/index-pack.c
62:#define FLAG_LINK (1u<<20)

v1.8.0:cache.h
73:#define S_IFGITLINK  0160000
74:#define S_ISGITLINK(m)       (((m) & S_IFMT) == S_IFGITLINK)

v1.8.0:environment.c
54:#define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS

v1.8.0:strbuf.c
326:#define STRBUF_MAXLINK (2*PATH_MAX)

v1.8.0:symlinks.c
53:#define FL_SYMLINK  (1 << 2)

v1.8.0:zlib.c
30:/* #define ZLIB_BUF_MAX ((uInt)-1) */
31:#define ZLIB_BUF_MAX ((uInt) 1024 * 1024 * 1024) /* 1GB */

Команда git grep имеет несколько преимуществ перед поиском с помощью таких команд, как grep и ack.
Во-первых, она действительно быстрая, во-вторых — git grep позволяет искать не только в рабочем каталоге, но и в любом другом дереве Git.
Как вы видели, в прошлом примере мы искали в старой версии исходных кодов Git, а не в текущем снимке файлов.

Поиск в журнале Git

Возможно, вы ищете не где присутствует некоторое выражение, а когда оно существовало или было добавлено.
Команда git log обладает некоторыми мощными инструментами для поиска определённых коммитов по содержимому их сообщений или содержимому сделанных в них изменений.

Например, если вы хотите найти, когда была добавлена константа ZLIB_BUF_MAX, то вы можете с помощью опции -S попросить Git показывать только те коммиты, в которых была добавлена или удалена эта строка.

$ git log -S ZLIB_BUF_MAX --oneline
e01503b zlib: allow feeding more than 4GB in one go
ef49a7a zlib: zlib can only process 4GB at a time

Если мы посмотрим на изменения, сделанные в этих коммитах, то увидим, что в ef49a7a константа была добавлена, а в e01503b — изменена.

Если вам нужно найти что-то более сложное, вы можете с помощью опции -G передать регулярное выражение.

Поиск по журналу изменений строки

Другой, довольно продвинутый, поиск по истории, который бывает чрезвычайно полезным — поиск по истории изменений строки.
Просто запустите git log с параметром -L, и он покажет вам историю изменения функции или строки кода в вашей кодовой базе.

Например, если мы хотим увидеть все изменения, произошедшие с функцией git_deflate_bound в файле zlib.c, мы можем выполнить git log -L :git_deflate_bound:zlib.c.
Эта команда постарается определить границы функции, выполнит поиск по истории и покажет все изменения, которые были сделаны с функцией, в виде набора патчей в обратном порядке до момента создания функции.

$ git log -L :git_deflate_bound:zlib.c
commit ef49a7a0126d64359c974b4b3b71d7ad42ee3bca
Author: Junio C Hamano <gitster@pobox.com>
Date:   Fri Jun 10 11:52:15 2011 -0700

    zlib: zlib can only process 4GB at a time

diff --git a/zlib.c b/zlib.c
--- a/zlib.c
+++ b/zlib.c
@@ -85,5 +130,5 @@
-unsigned long git_deflate_bound(z_streamp strm, unsigned long size)
+unsigned long git_deflate_bound(git_zstream *strm, unsigned long size)
 {
-       return deflateBound(strm, size);
+       return deflateBound(&strm->z, size);
 }


commit 225a6f1068f71723a910e8565db4e252b3ca21fa
Author: Junio C Hamano <gitster@pobox.com>
Date:   Fri Jun 10 11:18:17 2011 -0700

    zlib: wrap deflateBound() too

diff --git a/zlib.c b/zlib.c
--- a/zlib.c
+++ b/zlib.c
@@ -81,0 +85,5 @@
+unsigned long git_deflate_bound(z_streamp strm, unsigned long size)
+{
+       return deflateBound(strm, size);
+}
+

Если для вашего языка программирования Git не умеет правильно определять функции и методы, вы можете передать ему регулярное выражение.
Например, следующая команда выполнит такой же поиск как и предыдущая git log -L '/unsigned long git_deflate_bound/',/^}/:zlib.c.
Также вы можете передать интервал строк или номер определённой строки и в этом случае вы получите похожий результат.

Урок, в котором мы подробнее рассмотрим историю коммитов и научимся путешествовать по истории

Видеоурок

Конспект урока

Краткое содержание урока, основные инструкции для командной строки, полезные ссылки и советы.

Для информации

Урок частично повторяет содержание предыдущего. Но в отличие от прошлого историю коммитов мы рассмотрим намного подробнее.

История коммитов

Сохранение истории изменений или история коммитов — одна из самых важных частей git. В истории сохраняются все коммиты, по которым можно посмотреть автора коммита, commit message, дату коммита и его хэш.
А также можно увидеть измененные файлы и изменения в каждом файле. То есть git хранит буквально все, от самого начала проекта.

Команда git log

За просмотр истории коммитов отвечает команда git log. В сочетании с различными параметрами эта команда выводит историю по-разному.
Есть много различных вариантов и комбинаций параметров, посмотрим некоторые из них

git log, просмотр истории по умолчанию


    $ git log

Показывает все коммиты от новых к старым. Для каждого коммита выводится

  • хэш
  • автор
  • дата
  • сообщение (commit message)

git log -p, расширенный вывод истории


    $ git log -p

Выводит то же, что и git log, но еще и с изменениями в файлах

git log —oneline, короткая запись


    $ git log --oneline

Вывод коммитов в одну строку. Показывает только хэш коммита и commit message

git log —stat —graph, история в виде дерева


    $ git log --stat --graph

Выводит коммиты в виде дерева, в командной строке псевдографикой. Плюс выводит список измененных файлов. К дереву коммитов мы вернемся, когда будем работать с ветками.

Сортировка и фильтрация истории

Есть множество команд, которые позволяют сортировать и фильтровать историю коммитов в командной строке. В том числе в сочетании с линуксовыми командами.
Рассмотрим некоторые из них

Поиск по коммитам

Команда grep — мощный инструмент, который помогает работать в том числе и с git. Например, искать по коммитам


    git log --oneline | grep revert # поиск упоминания revert
    git log --oneline | grep -i revert # независимо от регистра

Коммиты, затронувшие один файл


    git log index.html

Поиск по автору


    git log --author webdevkin

В опции —author можно указать имя или email, необязательно целиком, можно только часть.

Поиск по диапазону дат

Опции —after и —before задают начальную и конечную даты коммитов


     git log --after='2020-03-09 15:30' --before='2020-03-09 16:00'

Комбинация команд и опций

Команды и опции git можно комбинировать и дополнять их линуксовыми командами


    git log --author=webdevkin --oneline | grep footer # все коммиты от автора, в которых упоминается footer
    git log --oneline | wc -l # количество коммитов

Какие еще есть варианты

Мы рассмотрели базовые примеры, но в документации по git log есть много различных опций.
Все их рассматривать нет смысла, при необходимости изучайте документацию.


    git log --help

Просмотр отдельного коммита, git show

Чтобы просмотреть отдельный коммит, нужно узнать его хэш. Хэш коммита выводится в любой команде git log, с параметрами или без. Например,


    $ git log --oneline
    
    7b7d7fa Fixed footer
    26812f9 Revert "Fixed footer"
    0f90ae7 Revert "Fixed styles"
    ...
    a1f3c45 Added footer
    a65aa43 Added new block students to main page
    0b90433 Initial commit

Смотрим второй коммит


    $ git show 43f6afc

Выводится подробная информация о коммите:

  • хэш
  • автор
  • дата
  • commit message
  • список измененных файлов
  • изменения в каждом файле

Короткий хэш коммита

Хэш коммита 40-символьный, но можно использовать короткую запись — первые 7 символов хэша.
Команда git log —oneline выводит именно короткий хэш. Для других операций с коммитами достаточно использовать первые 4 символа.
Например, 3 команды ниже покажут содержимое одного и того же коммита


    $ git show 051f75475cb1dca3cd08c1c7367a3308671ccf7b
    $ git show 051f754
    $ git show 051f

История коммитов в PhpStorm

В окне Local Changes, на вкладке Log показывается вся история коммитов, в левой половине вкладки. В списке коммитов показываются их commit message, автор и дата.
Клик на нужный коммит откроет в правой части вкладки список измененных файлов. Клик на нужном файле и Ctrl/Cmd+D покажет все изменения в этом файле точно так же, как и git diff.

В тексте объяснить работу с историей в PhpStorm сложно, смотрите видеоурок.

Переключение на старый коммит, зачем это нужно

Нужно это обычно в двух случаях:

1. При неудачном деплое, когда вскрылась критичная бага.
Если бага сложная и пофиксить ее быстро не удается, можно откатиться на рабочий коммит, задеплоить рабочую версию и уже потом чинить багу.

2. При отладке. Когда в код закралась бага и мы постепенно продвигаемся «назад в прошлое» и ищем, в какой момент что-то сломалось

Как переключиться на коммит в терминале

Первое — узнать хэш нужного коммита. Например, имеем такую историю


    $ git log --oneline
    
    7b7d7fa Fixed footer
    26812f9 Revert "Fixed footer"
    0f90ae7 Revert "Fixed styles"
    ...
    a1f3c45 Added footer
    a65aa43 Added new block students to main page
    0b90433 Initial commit

Хотим переключиться на предпоследний коммит. Коммиты идут в порядке убывания, поэтому нам нужен второй сверху — 26812f9. Переключаемся на него командой


    $ git checkout 26812f9

Все, вернулись в прошлое. Проверим историю, теперь коммит, на который мы переключились — последний


    $ git log --oneline 
    
    26812f9 Revert "Fixed footer"
    0f90ae7 Revert "Fixed styles"
    ...
    a1f3c45 Added footer
    a65aa43 Added new block students to main page
    0b90433 Initial commit

Уйдем еще дальше, переключимся на первый коммит. Так как коммиты упорядочиваются по убыванию даты, то первый коммит — это последний в списке — 0b90433 Initial commit


    $ git checkout 0b90433

Проверяем историю


    $ git log --oneline 
    
    0b90433 Initial commit

Чтобы вернуться обрано, в исходное состояние, нужно набрать


    $ git checkout master

master — это ветка, в которой мы работаем по умолчанию. О ветках поговорим через пару уроков

Как переключаться между коммитами в PhpStrom

Вкладка Log, правый клик на нужном коммите и Checkout Revision. Все. История коммитов будет видна по-прежнему вся, но напротив текущего коммита будет стоять значок HEAD с символом «!»

Как вернуться обратно? В правом нижем угле PhpStorm есть пункт git:, кликаем на него, выбираем Local Branches — master — checkout. Значок «!» пропадет — мы вернулись в исходное состояние

Что могу посоветовать

  • как и git diff, историю коммитов git log удобнее смотреть в PhpStorm
  • в команде git log есть множество вариантов сортировки и фильтрации
  • сочетание git log с простыми линуксовыми командами дает хороший эффект. Обычный grep — очень хороший помощник
  • PhpStorm предоставляет удобные возможности по фильтрации коммитов. Можно искать коммиты по commit message, по автору, дате и по папкам, в которых происходили изменения
  • перемещайтесь по истории осторожно, не забывайте возвращаться в исходное состояние

На этом все. В следующем уроке мы поговорим о взаимодействии с сервером и познакомимся с командами git push и git pull.

Спасибо за внимание и до встречи!

Все уроки курса

  • Вводный урок
  • 1. Установка и базовая настройка git
  • 2. Создание и клонирование репозитория git
  • 3. Делаем первые изменения, git status и git diff
  • 4. Коммиты и история коммитов, git commit, git log и git show
  • 5. Подробнее об истории коммитов. Путешествие по истории
  • 6. Работа с сервером, git push и git pull
  • 7. Ветки — главная фишка git, git branch и git checkout
  • 8. Работа с ветками на сервере, git fetch
  • 9. Слияния или мерджи веток, git merge
  • 10. Конфликты и их разрешение
  • Платная часть курса. Презентация
  • * 11. Работа с gitignore и git exclude
  • * 12. Буфер обмена git, git stash
  • * 13. Копирование коммитов, git cherry-pick
  • * 14. Отмена и редактирование последнего коммита
  • * 15. Отмена произвольного коммита, git revert
  •    16. Склеивание коммитов, git rebase —interactive и git reflog
  • * 17. Зачем склеивать коммиты. Плюсы и минусы сквоша
  • * 18. Работа с git rebase. Отличия от merge
  • * 19. Что такое git push —force и как с ним работать
  • * 20. Ищем баги с помощью git, git bisect
  • * 21. Как и зачем работать с тегами git
  • * 22. Процессы: github flow и git flow
  • * 23. Псевдонимы в git
  •    24. Мердж-реквесты
  • * 25. Форки

* платные уроки

список обновляется…

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

Теперь настало время познакомиться с некоторыми очень мощными возможностями Git, которые при повседневной работе вам, наверное, не потребуются, но в какой-то момент могут оказаться полезными.

Выбор ревизии

Git позволяет различными способами указать коммиты или их диапазоны.
Эти способы не всегда очевидны, но их полезно знать.

Одиночные ревизии

Конечно, вы можете ссылаться на коммит по его SHA-1 хешу, но существуют более удобные для человека способы.
В данном разделе описываются различные способы обращения к одному коммиту.

Сокращённый SHA-1

Git достаточно умен, чтобы понять какой коммит имеется ввиду по нескольким первым символам его хеша, если указанная часть SHA-1 имеет в длину по крайней мере четыре символа и однозначна — то есть в текущем репозитории существует только один объект с таким частичным SHA-1.

Например, предположим, чтобы найти некоторый коммит, вы выполнили команду git log и нашли коммит, в которой добавили определённую функциональность:

$ git log
commit 734713bc047d87bf7eac9674765ae793478c50d3
Author: Scott Chacon <schacon@gmail.com>
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 <schacon@gmail.com>
Date:   Thu Dec 11 15:08:43 2008 -0800

    Merge commit 'phedders/rdocs'

commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
Author: Scott Chacon <schacon@gmail.com>
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% вероятности возникновения коллизии, равно примерно 280.
(формула для определения вероятности возникновения коллизии p = (n(n-1)/2) * (1/2^160)).
280 — это 1.2 × 1024, или 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@{0}: commit: Fix refs handling, add gc auto, update tests
d921970 HEAD@{1}: merge phedders/rdocs: Merge made by the 'recursive' strategy.
1c002dd HEAD@{2}: commit: Add some blame and merge stuff
1c36188 HEAD@{3}: rebase -i (squash): updating HEAD
95df984 HEAD@{4}: commit: # This is a combination of two commits.
1c36188 HEAD@{5}: rebase -i (squash): updating HEAD
7e05da5 HEAD@{6}: rebase -i (pick): updating HEAD

Каждый раз когда по каким-то причинам изменяется вершина вашей ветки, Git сохраняет информацию об этом в эту временную историю.
И вы можете указывать старые коммиты, используя эти данные.
Например, чтобы посмотреть, куда ссылался указатель HEAD пять шагов назад, используйте ссылку @{5}, которую можно увидеть в выводимых данных команды reflog:

Этот синтаксис используется и в случае, когда требуется посмотреть, в каком состоянии пребывала ветка некоторое время назад.
В частности, чтобы увидеть где была ветка master вчера, следует написать:

$ git show master@{yesterday}

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

Для просмотра журнала ссылок в формате, похожем на вывод git log, вы можете выполнить git log -g:

$ git log -g master
commit 734713bc047d87bf7eac9674765ae793478c50d3
Reflog: master@{0} (Scott Chacon <schacon@gmail.com>)
Reflog message: commit: Fix refs handling, add gc auto, update tests
Author: Scott Chacon <schacon@gmail.com>
Date:   Fri Jan 2 18:32:33 2009 -0800

    Fix refs handling, add gc auto, update tests

commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Reflog: master@{1} (Scott Chacon <schacon@gmail.com>)
Reflog message: merge phedders/rdocs: Merge made by recursive.
Author: Scott Chacon <schacon@gmail.com>
Date:   Thu Dec 11 15:08:43 2008 -0800

    Merge commit 'phedders/rdocs'

Важно отметить, что информация в журнале ссылок строго локальная — это лог того, что вы делали в вашем репозитории.
Ссылки не будут такими же в других копиях репозитория; а сразу после первоначального клонирования репозитория, у вас будет пустой журнал ссылок, так как никаких действий в вашем репозитории пока не производилось.
Команда git show HEAD@{2.months.ago} будет работать только если вы клонировали проект по крайней мере два месяца назад — если вы клонировали его пять минут назад, то не получите никаких результатов.

Подсказка

Воспринимайте reflog Git как историю командной строки

Если у вас есть опыт работы с UNIX или Linux, можете думать о reflog как об истории командной строки Git, которая подчеркивает, что то, что там есть, явно актуально только для вас и вашего «сеанса» и не имеет ничего общего с кем-либо ещё, кто может работать на той же машине.

Примечание

Экранирование фигурных скобок в PowerShell

При использовании PowerShell фигурные скобки, такие как { и }, являются специальными символами и должны быть экранированы.
Вы можете экранировать их с помощью апострофа ` или поместить ссылку на коммит в кавычки:

$ git show HEAD@{0}     # НЕ будет работать
$ git show HEAD@`{0`}   # OK
$ git show "HEAD@{0}"   # 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 <schacon@gmail.com>
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 <schacon@gmail.com>
Date:   Thu Dec 11 14:58:32 2008 -0800

    Add some blame and merge stuff

$ git show d921970^2
commit 35cfb2b795a55793d7cc56a6cc2060b4bb732548
Author: Paul Hedderly <paul+git@mjr.org>
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 <tom@mojombo.com>
Date:   Fri Nov 7 13:47:59 2008 -0500

    Ignore *.gem

То же самое можно записать как HEAD~~~, что также является первым родителем первого родителя первого родителя:

$ git show HEAD~~~
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
Author: Tom Preston-Werner <tom@mojombo.com>
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 какой коммит или коммиты вы хотите изучить.

Понравилась статья? Поделить с друзьями:
  • Как найти кубатуру трубы
  • Как найти аналог шрифта на кириллицу
  • Как найти загрузки в телефоне андроид редми
  • Как найти батут в майнкрафте
  • Как на сайте найти правильные ответы