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

1548

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

Я уже написал инструмент (используя hook из Git), в котором я могу вставлять workitemidentifiers в сообщение набора изменений Git.

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

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

Теги:
tfs
tfs-workitem
changeset

19 ответов

2156
Лучший ответ

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

git rev-parse HEAD

или

git rev-parse --verify HEAD

Sidenote: Если вы хотите повернуть ссылки (ветки и теги) в SHA-1, есть git show-ref и git for-each-ref.

  • 67
    --verify подразумевает, что: The parameter given must be usable as a single, valid object name. Otherwise barf and abort.
  • 564
    git rev-parse --short HEAD возвращает короткую версию хэша, на случай, если кому-то интересно.
Показать ещё 13 комментариев
340

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

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

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

  • 97
    Или, кажется, добавление --short к команде rev-parse выше работает.
  • 11
    Я думаю, что git log это фарфор, а git rev-parse это сантехника.
Показать ещё 3 комментария
124

Другой, используя git log:

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

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

  • 0
    И результат не в кавычках.
  • 0
    Это правильный ответ, так как он работает, даже если вы извлекаете конкретный коммит вместо HEAD .
72

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

$ git rev-parse HEAD
cbf1b9a1be984a9f61b79a05f23b19f66d533537

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

$ git rev-parse --short HEAD
cbf1b9a
  • 0
    Если вам нужны два git commit , например один из branch вы сейчас работаете, и master branch , вы также можете использовать git rev-parse FETCH_HEAD если вам нужен хеш для master commit который вы merge d в текущую branch , Например, если у вас есть branch es master и feature/new-feature для данного репо, в то время как в feature/new-feature вы можете использовать git fetch origin master && git merge FETCH_HEAD а затем git rev-parse --short FETCH_HEAD если вам нужно хеш commit от master вы просто merge d для любых скриптов, которые вы можете иметь.
68

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

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

cat .git/refs/heads/master

Update:

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

  • 7
    Это предполагает, что текущая ветвь является master , что не обязательно верно.
  • 11
    В самом деле. Вот почему я прямо сказал, что это для master .
Показать ещё 7 комментариев
38

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

john@eleanor:/dev/shm/mpd/ncmpc/pkg (master)$ git describe --always
release-0.19-11-g7a68a75
  • 13
    Git description возвращает первый TAG, доступный из коммита. Как это поможет мне получить SHA?
  • 35
    Мне нравится git describe --long --dirty --abbrev=10 --tags это даст мне что-то вроде 7.2.0.Final-447-g65bf4ef2d4 что составляет 447 коммитов после тэга 7.2.0.Final и первых 10 дайджестов глобального SHA-1 в текущем заголовке "65bf4ef2d4". Это очень хорошо для версий строк. При использовании параметра --long всегда добавляются счетчик (-0-) и хэш, даже если тег точно совпадает.
Показать ещё 1 комментарий
31

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

git show -s --format=%H

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

git show -s --format=%H

Нажмите здесь для более git show примеров.

26

Используйте git rev-list --max-count=1 HEAD

  • 3
    git-rev-list предназначен для генерации списка объектов коммитов; это git-rev-parse для перевода имени объекта (например, HEAD) в SHA-1
19

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

last_commit=$(git rev-parse HEAD)

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

last_commit=$(git rev-parse HEAD | cut -c1-10) 
  • 25
    Есть также параметры --short или --short=number для git rev-parse ; Не нужно использовать трубу и cut .
13

Самый сжатый способ, который я знаю:

git show --pretty=%h 

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

--abbrev=n
  • 14
    Хотя это технически работает, git show - это то, что известно как фарфоровая команда (то есть обращенная к пользователю), и поэтому его не следует использовать в сценариях, поскольку его выходные данные могут быть изменены. Ответ выше ( git rev-parse --short HEAD ) следует использовать вместо этого.
  • 4
    @ jm3 это задом наперед. «Фарфоровые» команды имеют стабильные выходные данные, предназначенные для скриптов. Поиск git help show для porcelain .
Показать ещё 3 комментария
11

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

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
  • 0
    не нужно устанавливать git, мне это нравится. (у моего образа сборки докера нет git)
  • 0
    также полезно, потому что вы можете легко запустить это из-за пределов git репо
Показать ещё 2 комментария
11

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

$ 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, чтобы показать последний хэш-код фиксации.

  • 3
    Адриен де Сентенак отмечает, что вместо того, чтобы вручную редактировать файл конфигурации git, вы можете просто сделать: git config --global alias.lastcommit "rev-parse HEAD"
  • 0
    @ Adrien спасибо, обновил соответственно.
6

Мне нужно было что-то немного другое: отобразите полный 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

  • 0
    Спасибо, просто спотыкаюсь об этом, и это избавляет меня от того или иного эха за это :)
  • 1
    Это работает для меня без --match "NOT A TAG" . Протестировано в git 2.18.0 и 2.7.4. Есть ли ситуация, когда нужен этот аргумент?
Показать ещё 1 комментарий
5

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

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

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

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

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

5
git show-ref --head --hash head

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

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

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

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

в файле home-dir в файле .gitconfig добавьте следующее

[alias]
sha = rev-parse HEAD

тогда вам будет легче запомнить:

$ git sha
59fbfdbadb43ad0b6154c982c997041e9e53b600
1

Вот шаги, которые помогли мне, используя хэш коммита:

  1. Войдите в свою ссылку на GIT HUB, например: https://github.<xyz.abc>.com
  2. После входа в систему в текстовом поле "Искать или перейти к..." введите как:

    hash:<GIT COMMIT HASH>
    
  3. Выберите между "Все GitHub Enterprise" или "В этой организации" в зависимости от ваших потребностей

  4. Нажмите Enter.
  • 0
    Кажется, что это отвечает на совершенно другой вопрос.
1

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

git log | grep -o '\w\{8,\}' | head -n 1
0

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню