Как получить хеш текущего коммита в Git?

Я хотел бы сохранить (пока) возможность связывать наборы изменений Git с рабочими элементами, хранящимися в TFS.

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

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

Как я могу легко получить хеш из текущего коммита из Git?


person Sardaukar    schedule 04.06.2009    source источник


Ответы (20)


Чтобы превратить произвольную ссылку на расширенный объект в SHA-1, используйте просто git-rev-parse, например

git rev-parse HEAD

or

git rev-parse --verify HEAD

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

git rev-parse --short HEAD

Примечания. Если вы хотите преобразовать ссылки (ветви и теги) в SHA -1, есть git show-ref и git for-each-ref.

person Jakub Narębski    schedule 04.06.2009
comment
--verify означает, что: The parameter given must be usable as a single, valid object name. Otherwise barf and abort. - person Linus Unnebäck; 24.07.2011
comment
git rev-parse --short HEAD возвращает короткую версию хэша, на всякий случай, если кому-то интересно. - person Thane Brimhall; 26.10.2012
comment
Добавляя к тому, что сказал Тейн, вы также можете добавить определенную длину к --short, например --short=12, чтобы получить определенное количество цифр из хеша. - person Tyson Phalp; 21.02.2014
comment
@TysonPhalp: --short=N - это примерно минимальное количество цифр; git использует большее количество цифр, если сокращенная одна будет неотличима от сокращенной другой фиксации. Попробуйте, например, git rev-parse --short=2 HEAD или git log --oneline --abbrev=2. - person Jakub Narębski; 21.02.2014
comment
Добавляя к тому, что сказали Тейн, Тайсон и Якуб, вы можете распечатать полный хэш, но выделите гекситы, необходимые для идентификации фиксации синим цветом с помощью git rev-parse HEAD | GREP_COLORS='ms=34;1' grep $(git rev-parse --short=0 HEAD) - person Zaz; 05.08.2014
comment
Аккуратный трюк Заз. Похоже, это не работает с grep на моем Mac, но я заменил ack на аналогичный эффект! - person XP84; 24.07.2015
comment
@Zaz Это тоже не сработало для меня, но просто git rev-parse HEAD | grep --color $(git rev-parse --short=0 HEAD) работает. - person Theodore Murdock; 31.12.2015
comment
Есть ли способ сделать это, но для каждого каталога? Например, допустим, мне нужен последний хэш определенного каталога. Мне нужно сделать git log <directory> и проанализировать его, чтобы получить хеш? - person Aaron; 10.05.2016
comment
@Aaron: грубо говоря да, нужно запустить git log <options> -- <directory>; но вы можете настроить git-log так, чтобы он возвращал только хеш. - person Jakub Narębski; 11.05.2016
comment
Добавляя к тому, что сказал @ThaneBrimhall, вы можете получить полную ссылку на SHA-1 из короткой версии хэша, используя git rev-parse ca003ae. - person Halil; 24.05.2016
comment
Этот способ работает, если у вас есть тег с именем HEAD? ›:) - person Sap; 03.08.2016
comment
@EdRandall: git rev-parse основная цель - анализировать параметры и возвращать ревизии, поэтому --short означает сокращенный SHA-1 ревизии. git log возвращает дополнительную информацию, включая SHA-1 ревизий, которая может быть сокращена с помощью --abbrev или --abbrev-commit. - person Jakub Narębski; 07.09.2016
comment
git rev-parse HEAD | pbcopy отлично подходит для быстрого создания буфера обмена на Mac - person Kirk Strobeck; 07.09.2017
comment
Прохладный! Я даже добавил его в псевдоним: git config --global alias.sha 'rev-parse HEAD'. Теперь я могу просто использовать git sha. - person milkovsky; 11.01.2018
comment
Это не всегда правильный ответ! Если ГОЛОВА не находится в фиксации вашей проверки (отделенная голова), то, что вы получаете обратно, неверно. Только git status даст вам правильный хеш фиксации. - person sschueller; 05.06.2018
comment
Я считаю, что это не работает с тегами без аннотации. Если у вас есть неаннотированный тег, указывающий на голову, git rev-parse --short HEAD должен дать вам тот же результат, что и git show-ref -s7 <tag>, и при этом у меня нет двух разных хешей. Это связано с тем, что облегченные теги будут показывать только свой ref-хеш, а не хеш фиксации, на которую они указывают. Для этого нужно сделать git rev-parse --short '<tag>^{}'. - person Cheruvim; 17.08.2020
comment
Когда мне понадобится --verify? - person xjcl; 10.12.2020
comment
@xjcl параметр --verify полезен, если вы используете git rev-parse вместе с чем-то переменным, например git rev-parse --verify $branch. Для git rev-parse --verify HEAD он гарантирует, что HEAD можно превратить в SHA-1 / идентификатор объекта (и, например, вы не находитесь в нерожденной ветке). - person Jakub Narębski; 10.12.2020
comment
Если вы передадите это в pbcopy на Mac, чтобы скопировать в буфер обмена, вы получите новую строку в конце. Чтобы избавиться от него, используйте git rev-parse HEAD | tr -d '\n' | pbcopy - person squall3d; 18.05.2021

Если вам нужен только сокращенный хеш фиксации:

git log --pretty=format:'%h' -n 1

Кроме того, использование %H - это еще один способ получить длинный хеш фиксации, и вместо -n 1 можно использовать просто -1.

person outofculture    schedule 30.09.2011
comment
Или кажется, что добавление --short к команде rev-parse выше работает. - person outofculture; 01.10.2011
comment
Я думаю, git log фарфор, а git rev-parse сантехника. - person Amedee Van Gasse; 29.01.2016
comment
Одним из преимуществ этого метода является то, что он возвращает короткую версию хэша с правильной длиной, скорректированной с учетом коллизий хэша, которые происходят для больших репозиториев. По крайней мере, в последних версиях git. - person Ilia Sidorenko; 22.12.2016
comment
Это плохой / неправильный способ сделать это, потому что этот метод даст вам неправильный хеш, если у вас есть отдельная голова. Например, если текущая фиксация - 12ab34 ... и предыдущая фиксация была 33aa44 ... тогда, если я сделаю 'git checkout 33aa44', а затем запущу вашу команду, я все равно получу 12ab34 ... несмотря на то, что моя голова фактически указывает кому: 33aa44 ... - person theQuestionMan; 17.07.2017
comment
@theQuestionMan Я не испытываю того поведения, которое вы описываете; git checkout 33aa44; git log -n 1 дает мне 33aa44. Какую версию git вы используете? - person outofculture; 19.07.2017
comment
@AmedeeVanGasse, если git log фарфор, а git rev-parse водопровод, что такое git status --porcelain? :П - person Patrick L; 14.01.2021
comment
@PatrickL Я не знаю, это вопрос четырехлетней давности, и мне не хочется возвращаться к тому, что осталось позади. Я рекомендую вам открыть новый вопрос о переполнении стека. - person Amedee Van Gasse; 15.01.2021
comment
@AmedeeVanGasse, ах! Я НЕ ИДЕИ, это аналогия с туалетом! Я много лет видел porcelain на страницах git man, но понятия не имел, что это имел в виду туалет! Фарфор - это унитаз, и он ближе к пользователю (который, образно говоря, сидит на этом унитазе), чем сантехника, которая находится ниже и дальше от пользователя, то есть ниже фарфора! Разум взорван. - person Gabriel Staples; 21.02.2021
comment
@PatrickL, я бы сказал, git status это пластиковое сиденье для унитаза. Он ближе к пользователю, чем фарфор, где фарфор относится к фарфоровой чаше под сиденьем унитаза. Итак, git status и git log пластиковые. git log --pretty=format фарфор, git status --porcelain тоже фарфор, git rev-parse водопровод. - person Gabriel Staples; 21.02.2021
comment
Полные параметры красивого формата: git-scm.com/docs / pretty-sizes # Documentation / - person cdalxndr; 30.03.2021

Еще один, используя git log:

git log -1 --format="%H"

Он очень похож на @outofculture, но немного короче.

person Paul Pladijs    schedule 21.11.2011
comment
И результат не является одинарным. - person crokusek; 01.03.2017
comment
Это правильный ответ, поскольку он работает, даже если вы проверяете конкретный коммит вместо HEAD. - person Parsa; 22.02.2019
comment
@Parsa: при проверке конкретной фиксации HEAD указывает на эту фиксацию, а не на именованную ветвь, известную как оторванная голова. - person ChristofSenn; 28.01.2020
comment
Из командной строки, чтобы избежать пейджера: git --no-pager log -1 --format="%H" - person ederag; 09.05.2021

Чтобы получить полный SHA:

$ git rev-parse HEAD
cbf1b9a1be984a9f61b79a05f23b19f66d533537

Чтобы получить сокращенную версию:

$ git rev-parse --short HEAD
cbf1b9a
person Alexander    schedule 29.07.2016
comment
Если требуются два git commit хэша, например один из branch, с которым вы в настоящее время работаете, и master branch, вы также можете использовать git rev-parse FETCH_HEAD, если вам нужен хеш для master commit, который вы merged в свой текущий branch. например если у вас есть branches master и feature/new-feature для данного репо., в то время как на feature/new-feature вы можете использовать git fetch origin master && git merge FETCH_HEAD, а затем git rev-parse --short FETCH_HEAD, если вам нужен commit хеш из master, вы просто merged для любых сценариев, которые у вас могут быть. - person EVAL; 04.09.2018

Для полноты, поскольку еще никто не предлагал. .git/refs/heads/master - это файл, содержащий только одну строку: хэш последней фиксации на master. Так что вы можете просто прочитать это оттуда.

Или, как команда:

cat .git/refs/heads/master

Обновлять:

Обратите внимание, что git теперь поддерживает сохранение некоторых ссылок на головы в файле pack-ref, а не в виде файла в папке / refs / Heads /. https://www.kernel.org/pub/software/scm/git/docs/git-pack-refs.html.

person Deestan    schedule 16.10.2012
comment
Предполагается, что текущая ветвь master, что не обязательно верно. - person gavrie; 23.10.2012
comment
Действительно. Вот почему я прямо сказал, что это для master. - person Deestan; 23.10.2012
comment
Есть .git/HEAD, который представляет собой файл, содержащий 1 строку с SHA1 HEAD. Думаю, вы это имели в виду. - person kynan; 07.11.2012
comment
.git/HEAD обычно указывает на ссылку, если у вас есть SHA1, вы находитесь в режиме отдельной головы. - person eckes; 09.04.2013
comment
Это не очень надежно по сравнению с другими подходами, в частности потому, что предполагает наличие подкаталога .git, что не всегда так. См. Флаг --separate-git-dir на git init странице руководства. - person jub0bs; 29.12.2014
comment
+1, потому что иногда вы не хотите, чтобы исполняемый файл git устанавливался (например, в вашем Dockerfile) - person wim; 07.04.2015
comment
Для поиска SHA-хеша ветки .git/refs/heads/<branch-name> - person pushya; 07.04.2015
comment
+1 - и - если вы не хотите обязательно извлекать / перебазировать / объединять, а просто хотите получить хэш пост-выборки cat .git/refs/remotes/origin/master - person nhed; 24.05.2016
comment
cat .git / $ (cat .git / HEAD | awk '{print $ 2;}') тогда должен работать? - person xiay; 27.09.2017
comment
Это менее надежно, потому что .git всегда может быть файлом, содержащим имя реального каталога .git. - person Carlo Wood; 03.02.2020
comment
+1, потому что это может быть быстрее и проще, поскольку вам не нужно вызывать bash только для отображения хэша фиксации в нижнем колонтитуле графического интерфейса. - person sijanec; 05.05.2020

Зафиксировать хеш

git show -s --format=%H

Сокращенный хеш фиксации

git show -s --format=%h

Флаг -s аналогичен флагу --no-patch и означает "Подавить вывод различий".

Нажмите здесь, чтобы увидеть другие git show примеры.

person ecwpz91    schedule 27.03.2017

Всегда есть git describe. По умолчанию это дает вам -

john@eleanor:/dev/shm/mpd/ncmpc/pkg (master)$ git describe --always
release-0.19-11-g7a68a75
person John Tyree    schedule 26.08.2011
comment
Git description возвращает первый тег, доступный из фиксации. Как это помогает мне получить SHA? - person Sardaukar; 09.09.2011
comment
Мне нравится git describe --long --dirty --abbrev=10 --tags, это даст мне что-то вроде 7.2.0.Final-447-g65bf4ef2d4, что составляет 447 коммитов после тега 7.2.0. Final, а первые 10 дайджестов глобального SHA-1 в текущем HEAD - это 65bf4ef2d4. Это очень хорошо для строк версии. С --long он всегда будет добавлять счетчик (-0-) и хэш, даже если тег точно совпадает. - person eckes; 09.04.2013
comment
Если тегов не существует, git describe --always будет показывать однозначно сокращенный объект фиксации как резервный. - person Ronny Andersson; 18.09.2014
comment
Я использую git describe --tags --first-parent --abbrev=11 --long --dirty --always. Параметр --always означает, что он предоставляет результат (хэш), даже если тегов нет. --first-parent означает, что его не путают коммиты слияния, и он следует только за элементами в текущей ветке. Также обратите внимание, что --dirty добавит -dirty к результату, если текущая ветвь имеет незафиксированные изменения. - person ingyhere; 31.01.2020

Используйте 1_

person Robert Munteanu    schedule 04.06.2009
comment
git-rev-list предназначен для создания списка объектов фиксации; это git-rev-parse для перевода имени объекта (например, HEAD) в SHA-1 - person Jakub Narębski; 04.06.2009

Если вам нужно сохранить хэш в переменной во время скрипта, вы можете использовать

last_commit=$(git rev-parse HEAD);

Или, если вам нужны только первые 10 символов (например, github.com)

last_commit=$(git rev-parse --short=10 HEAD);
person Henk    schedule 15.07.2012

Если вам нужен супер-хакерский способ сделать это:

cat .git/`cat .git/HEAD | cut -d \  -f 2`

По сути, git хранит местоположение HEAD в .git / HEAD в форме ref: {path from .git}. Эта команда считывает это, отсекает «ref:» и считывает любой файл, на который она указывала.

Это, конечно, потерпит неудачу в режиме отдельной головы, так как HEAD будет не "ref: ...", а будет сам хеш - но вы знаете, я не думаю, что вы ожидаете такого большого умения в своем bash. -лайнеры. Если вы не думаете, что точки с запятой обманывают ...

HASH="ref: HEAD"; while [[ $HASH == ref\:* ]]; do HASH="$(cat ".git/$(echo $HASH | cut -d \  -f 2)")"; done; echo $HASH
person Fordi    schedule 14.10.2015
comment
не нужно устанавливать git, мне это нравится. (в моем образе сборки докеров нет git) - person Helin Wang; 15.02.2016
comment
также полезно, потому что вы можете легко запустить это вне репозитория git - person samaspin; 22.06.2016
comment
Я формализовал это в скрипте для моей локальной машины. Затем я подумал: эй: реализованная мною реализация достаточно проста, чтобы показать, как решить несвязанную проблему (анализ аргументов в необработанных сценариях оболочки POSIX без внешних программ), но достаточно сложна, чтобы обеспечить небольшую вариацию и использовать большую часть особенности sh. Полчаса комментариев к документации спустя, и вот их суть: gist.github.com/Fordi/29f168d6d6d1ef - person Fordi; 29.06.2016
comment
Глядя на это, я сделал более обширную версию для обнаружения Git и SVN и взял ревизию git hash / svn. На этот раз не чистая строка, но ее легко анализировать в командной строке и использовать в качестве тега версии: gist.github .com / Fordi / 8f1828efd820181f24302b292670b14e - person Fordi; 29.06.2016

Самый емкий из известных мне способов:

git show --pretty=%h 

Если вам нужно определенное количество цифр хеша, вы можете добавить:

--abbrev=n
person Brian Peterson    schedule 07.02.2014
comment
Хотя это технически работает, git show - это так называемая команда porcelain (то есть обращенная к пользователю), и поэтому ее не следует не использовать в сценариях, потому что ее вывод может быть изменен. Вместо этого следует использовать ответ выше (git rev-parse --short HEAD). - person jm3; 16.03.2014
comment
@ jm3 наоборот. Команды Porcelain имеют стабильные выходные данные, предназначенные для сценариев. Найдите git help show для porcelain. - person John Tyree; 07.07.2015
comment
@JohnTyree Это сбивающая с толку тема, но jm3 был прав: фарфоровые команды предназначены не для анализа, а для удобства чтения. Если вам нужно использовать команду фарфора в скрипте и вы хотите иметь стабильный формат, иногда (например, с git status, push and blame) есть опция, которая делает именно это. К сожалению, эта опция называется --porcelain, поэтому это сбивает с толку. Вы можете найти подробности в этом замечательном ответе VonC - person Fabio says Reinstate Monica; 14.01.2019

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

$ git lastcommit
49c03fc679ab11534e1b4b35687b1225c365c630

Следуя принятому ответу, вот два способа настроить это:

1) Научите git явным образом, отредактировав глобальную конфигурацию (мой исходный ответ):

 # open the git config editor
 $ git config --global --edit
 # in the alias section, add
 ...
 [alias]
   lastcommit = rev-parse HEAD
 ...

2) Или, если вам нравится ярлык для обучения git ярлыку, как недавно прокомментировал Адриен:

$ git config --global alias.lastcommit "rev-parse HEAD"

С этого момента используйте git lastcommit, чтобы показать хеш последнего коммита.

person miraculixx    schedule 09.10.2015

Мне нужно было что-то немного другое: отобразить полный sha1 коммита, но добавить звездочку в конец, если рабочий каталог не чистый. Если я не хотел использовать несколько команд, ни один из вариантов в предыдущих ответах не работает.

Вот один лайнер, который делает:
git describe --always --abbrev=0 --match "NOT A TAG" --dirty="*"
Результат: f5366ccb21588c0d7a5f7d9fa1d3f85e9f9d1ffe*

Объяснение: описывает (используя аннотированные теги) текущую фиксацию, но только с тегами, содержащими «NOT A TAG». Поскольку в тегах не может быть пробелов, это никогда не соответствует тегу, и поскольку мы хотим показать результат --always, команда откатывает отображение полного (--abbrev=0) sha1 фиксации и добавляет звездочку, если рабочий каталог --dirty.

Если вы не хотите добавлять звездочку, это работает так же, как и все другие команды в предыдущих ответах:
git describe --always --abbrev=0 --match "NOT A TAG"
Результат: f5366ccb21588c0d7a5f7d9fa1d3f85e9f9d1ffe

person Rado    schedule 17.02.2018
comment
Спасибо, просто наткнулся на это и избавил меня от того или иного эха :) - person hakre; 23.02.2018
comment
У меня работает без --match "NOT A TAG". Протестировано как в git 2.18.0, так и в 2.7.4. Есть ли ситуация, когда этот аргумент нужен? - person Thomas; 07.08.2018
comment
@Thomas не сработает, если у вас есть аннотированный тег где-нибудь в истории текущего коммита. Поддельный тег гарантирует, что команда description не использует тег для описания фиксации, - person Rado; 08.08.2018

git show-ref --head --hash head

Если вы стремитесь к скорости, подход, упомянутый Дистаном

cat .git/refs/heads/<branch-name>

значительно быстрее, чем любой другой перечисленный здесь метод.

person Dennis    schedule 30.04.2015
comment
show-ref кажется мне лучшим вариантом для написания сценариев, поскольку это команда сантехники и, таким образом, гарантированно (или, по крайней мере, очень вероятно) останется стабильной в будущих выпусках: в других ответах используются rev-parse, show, describe или log, которые все фарфоровые команды. А в случаях, когда скорость не важна, применяется примечание из show-ref справочной страницы: «Использование этой утилиты приветствуется в пользу прямого доступа к файлам в каталоге .git». - person Pont; 08.10.2018

Вот однострочник в оболочке Bash с использованием прямого чтения из файлов git:

(head=($(<.git/HEAD)); cat .git/${head[1]})

Вам нужно запустить указанную выше команду в корневой папке git.

Этот метод может быть полезен, если у вас есть файлы репозитория, но команда git не установлена.

Если не получится, проверьте в папке .git/refs/heads, какие у вас головы.

person kenorb    schedule 05.10.2017

в вашем домашнем каталоге в файле ".gitconfig" добавьте следующее

[alias]
sha = rev-parse HEAD

тогда вам будет проще запомнить команду:

$ git sha
59fbfdbadb43ad0b6154c982c997041e9e53b600
person jo_    schedule 18.02.2016

В git bash просто запустите $ git log -1

вы увидите эти строки после вашей команды.

commit d25c95d88a5e8b7e15ba6c925a1631a5357095db .. (info about your head)

d25c95d88a5e8b7e15ba6c925a1631a5357095db, is your SHA for last commit.
person Batty    schedule 26.11.2019

git rev-parse HEAD делает свое дело.

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

cat .git/HEAD

Пример вывода:

ref: refs/heads/master

Разбери это:

cat .git/HEAD | sed "s/^.\+ \(.\+\)$/\1/g"`

Если у вас Windows, вы можете рассмотреть возможность использования wsl.exe:

wsl cat .git/HEAD | wsl sed "s/^.\+ \(.\+\)$/\1/g"

Выход:

refs/heads/master

Это значение можно использовать позже для git checkout, но оно становится указывающим на его SHA. Чтобы он указывал на текущую ветку по ее имени, выполните:

wsl cat .git/HEAD | wsl sed "s/^.\+ \(.\+\)$/\1/g" | wsl sed "s/^refs\///g"  | wsl sed "s/^heads\///g"

Выход:

master
person Serg    schedule 04.11.2019

Вот еще одна реализация прямого доступа:

head="$(cat ".git/HEAD")"
while [ "$head" != "${head#ref: }" ]; do
  head="$(cat ".git/${head#ref: }")"
done

Это также работает через http, что полезно для локальных архивов пакетов (я знаю: для общедоступных веб-сайтов не рекомендуется делать каталог .git доступным):

head="$(curl -s "$baseurl/.git/HEAD")"
while [ "$head" != "${head#ref: }" ]; do
  head="$(curl -s "$baseurl/.git/${head#ref: }")"
done
person Daniel Alder    schedule 04.11.2016

Вот еще один способ сделать это с помощью :)

git log | grep -o '\w\{8,\}' | head -n 1
person Marcelo Lazaroni    schedule 10.02.2017