Як отримати хеш для поточного комітету в Git?


1931

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

Я вже написав інструмент (використовуючи гачок від Git), за допомогою якого я можу вставити workitemidentifiers у повідомлення набору змін Git.

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

Як я можу легко отримати хеш з поточного комітету від Git?

Відповіді:


2808

Щоб включити довільну розширену посилання на об'єкт в SHA-1, використовувати просто ГИТ-Rev-розбір , наприклад

git rev-parse HEAD

або

git rev-parse --verify HEAD

Сторінка: Якщо ви хочете перетворити посилання ( гілки та теги ) в SHA-1, єgit show-refіgit for-each-ref.


81
--verifyмається на увазі, що:The parameter given must be usable as a single, valid object name. Otherwise barf and abort.
— Linus Unnebäck

647
git rev-parse --short HEADповертає коротку версію хешу, про всяк випадок, коли хтось задумався.
— Thane Brimhall

54
Додавши до сказаного Тайн, ви також можете додати певну довжину --short, наприклад --short=12, щоб отримати певну кількість цифр з хеша.
— Тайсон Фелп

31
@TysonPhalp: --short=Nце приблизно мінімальна кількість цифр; git використовує більшу кількість цифр, якщо скорочена одна не відрізнятиметься від скороченої іншої коми. Спробуйте, наприклад, git rev-parse --short=2 HEADабо git log --oneline --abbrev=2.
— Якуб Нарбський

36
Додавши до того, що сказав Тайн, Тайсон та Якуб, ви можете надрукувати повний хеш, але виділити шестикутники, необхідні для ідентифікації синього кольоруgit rev-parse HEAD | GREP_COLORS='ms=34;1' grep $(git rev-parse --short=0 HEAD)
— Заз

423

Якщо ви хочете лише скорочений хеш:

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

Крім того, використання% H - це ще один спосіб отримати довгий хеш.


106
Або, здається, додавання --ort в команду rev-синтаксизу, здається, працює.
— ауткультура

15
Я думаю git log, що фарфор і git rev-parseсантехніка.
— Амеді Ван Гассе

Однією з переваг цього методу є те, що він поверне коротку версію хеша з правильною довжиною, пристосованою до колізійних зіткнень, які трапляються для більшого репосту. Принаймні, в останніх версіях git.
— Ілля Сидоренко

4
Це поганий / неправильний спосіб зробити це, оскільки цей метод дасть вам неправильний хеш, якщо у вас відірвана голова. Наприклад, якщо поточна комісія - 12ab34 ... а попередня комісія - 33aa44 ... тоді, якщо я виконую "git checkout 33aa44", а потім я запускаю вашу команду, я все одно повернусь 12ab34 ... незважаючи на те, що моя голова фактично вказує до 33aa44 ...
— theQuestionMan

3
@theQuestionMan Я не відчуваю поведінки, яку ви описуєте; git checkout 33aa44; git log -n 1дає мені 33aa44. Яку версію git ви використовуєте?
— ауткультура

150

Ще один із використанням git log:

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

Він дуже схожий на @outofculture, хоча трохи коротший.


І результат не одноцитований.
— crokusek

5
Це правильна відповідь, оскільки вона працює навіть у тому випадку, якщо ви перевіряєте певну комісію замість HEAD.
— Парса

1
@Parsa: під час перевірки конкретних фіксів HEADвказує на це зобов’язання, а не на ім'я розгалужених знань як відокремлену голову .
— КрістофСенн

124

Щоб отримати повну SHA:

$ git rev-parse HEAD
cbf1b9a1be984a9f61b79a05f23b19f66d533537

Щоб отримати скорочену версію:

$ git rev-parse --short HEAD
cbf1b9a

Якщо вам git commitпотрібні два хеші, наприклад, один із того, з яким branchви зараз працюєте, і a master branch, ви також можете використовувати, git rev-parse FETCH_HEADякщо вам потрібен хеш для того, master commitщо ви будете мати mergeв поточному 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вас, просто ви знайдете mergeбудь-які сценарії.
— EVAL

72

Для повноти, оскільки ніхто ще не запропонував цього. .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


10
Це передбачає, що поточна галузь є master, що не обов'язково відповідає дійсності.
— gavrie

12
Справді. Тому я прямо сказав, що це за master.
— Деестан

20
.git/HEADяк правило, вказує на перелік, якщо у вас там є SHA1, ви перебуваєте в режимі відокремленої голови.
— eckes

8
Це не дуже надійно порівняно з іншими підходами, зокрема, оскільки передбачає, що існує .gitпідкаталог, що не обов'язково. Дивіться --separate-git-dirпрапор на git initсторінці людини.
— jub0bs

16
+1, оскільки іноді ви не хочете встановити виконуваний файл git (наприклад, у своєму Dockerfile)
— wim

50

Зробіть хеш

git show -s --format=%H

Скорочений фіш хеш

git show -s --format=%h

Клацніть тут, щоб отримати більше git showприкладів.


50

Так само завжди git describeє. За замовчуванням він дає вам -

john@eleanor:/dev/shm/mpd/ncmpc/pkg (master)$ git describe --always
release-0.19-11-g7a68a75

18
Git description повертає перший TAG, доступний з комітів. Як це допомагає мені отримати SHA?
— Сардаукар

42
Мені подобається, що git describe --long --dirty --abbrev=10 --tagsце дасть мені щось на зразок 7.2.0.Final-447-g65bf4ef2d4447 фіксованих знаків після 7.2.0. Фінальний тег і перші 10 дайджестів глобального SHA-1 в поточній ГЛАВІ "65bf4ef2d4". Це дуже добре для рядків версій. З - довгий, він завжди додаватиме кількість (-0-) та хеш, навіть якщо тег точно збігається.
— eckes

14
Якщо немає тегів, то git describe --always"відображатиметься однозначно скорочений об'єкт фіксації як резервний"
— Ronny Andersson,

Я використовую git describe --tags --first-parent --abbrev=11 --long --dirty --always. --alwaysОпція означає , що він забезпечує результат (хеш) , навіть якщо немає тегів. Це --first-parentозначає, що його не плутають комісії злиття, а лише слідують за пунктами на поточній гілці. Зауважте також, що --dirtyдодасться -dirtyдо результату, якщо поточна гілка змінила зміни.
— ingyhere

30

Використовуйте git rev-list --max-count=1 HEAD


3
git-rev-list - це створення списку об'єктів комісій; це git-rev-parse для перекладу імені об’єкта (наприклад, HEAD) на SHA-1
— Jakub Narębski

21

Якщо вам потрібно зберігати хеш у змінній під час сценарію, ви можете використовувати

last_commit=$(git rev-parse HEAD)

Або якщо ви хочете лише перших 10 символів (як це робить github.com)

last_commit=$(git rev-parse HEAD | cut -c1-10) 

26
Є також параметри --shortабо --short=numberдля git rev-parse; не потрібно використовувати трубу і cut.
— Джуліан Д.

15

Якщо ви хочете, як це зробити супер-хакі:

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

В основному, git зберігає розташування HEAD у форматі .git / HEAD у формі ref: {path from .git}. Ця команда читає це, відрізає "ref:" і зчитує будь-який файл, на який він вказував.

Це, звичайно, не вдасться в режимі з відстороненою головою, оскільки HEAD не буде "ref: ...", але сам хеш - але ви знаєте, я не думаю, що ви очікуєте, що так багато розумних у вашому башті -лінії. Якщо ви не вважаєте, що крапки з комою обманюють, хоча ...

HASH="ref: HEAD"; while [[ $HASH == ref\:* ]]; do HASH="$(cat ".git/$(echo $HASH | cut -d \  -f 2)")"; done; echo $HASH

1
не потрібно встановлювати git, мені це подобається. (у мого зображення для створення докерів немає git)
— Хелін Ван

також корисно, тому що ви можете легко запустити це за межами git repo
— samaspin

Я формалізував це під сценарій для своєї локальної машини. Тоді, я подумав, ей: реалізація, яку я зробив, є досить простою, що ілюструє вирішення непов'язаної проблеми (розбір аргументів у необроблених скриптах оболонки POSIX без зовнішніх програм), але достатньо складна, щоб забезпечити невелику варіацію та використовувати більшість особливості sh. Півгодини документації коментарі пізніше, і ось суть
— Fordi

Дивлячись на це, я створив більш обширну версію для виявлення Git та SVN та захоплення версії git hash / svn. Цього разу не чистий рядок, але легко розбирається командний рядок і може використовуватися як тег версії: gist.github.com/Fordi/8f1828efd820181f24302b292670b14e
— Fordi

14

Найкоротший спосіб, який я знаю:

git show --pretty=%h 

Якщо вам потрібна конкретна кількість цифр хеша, ви можете додати:

--abbrev=n

14
Хоча це технічно працює, git showте, що відоме як порцелянова команда (тобто орієнтоване на користувача), і тому не повинно використовуватися в сценаріях, оскільки його вихід може змінюватися. Відповідь вище ( git rev-parse --short HEAD) слід використовувати замість цього.
— jm3

4
@ jm3, це назад. Команди "Porcelain" мають стабільні виходи, призначені для сценаріїв. Пошук git help showпо porcelain.
— Джон Тайрі

2
@JohnTyree Це заплутаний предмет, але jm3 був правильний: порцелянові команди призначені не для розбору, а для того, щоб прочитати людину. Якщо вам потрібно використовувати порцелянову команду в скрипті, і ви хочете мати стабільний формат, іноді (наприклад, зі статусом git, push і звинувачення) є варіант, який робить саме це. На жаль, такий варіант називається --porcelain, тому це заплутано. Подробиці ви можете знайти у цій чудовій відповіді VonC
— Фабіо каже, що

1
шановний бог, який вирішив назвати цей варіант - порцеляновий, я хочу їх знайти і ... о, зачекайте, мені потрібно буде використовувати git, щоб знайти їх неважливо
— Бріттон Керін

14

Можливо, ви хочете псевдонім, тому вам не доведеться пам’ятати всі чудові деталі. Зробивши один із наведених нижче кроків, ви зможете просто набрати:

$ 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 config --global alias.lastcommit "rev-parse HEAD"

З цього git lastcommitмоменту використовуйте, щоб показати хеш останньої комісії.


3
Адріан де Сентенак зазначає, що замість того, щоб вручну редагувати файл git config, ви могли просто зробити:git config --global alias.lastcommit "rev-parse HEAD"
— cgmb

12

Мені потрібно було дещо інше: відобразити повний sha1 комітету, але додати зірочку до кінця, якщо робочий каталог не чистий. Якщо я не хотів використовувати декілька команд, жоден із варіантів попередніх відповідей не працює.

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

Пояснення: описує (використовуючи помічені теги) поточну комісію, але лише з тегами, що містять "NOT TAG". Оскільки в тегах не може бути пробілів, це ніколи не відповідає тегу, і оскільки ми хочемо показати результат --always, команда опускається, відображаючи повний ( --abbrev=0) sha1 комітету, і додає зірочку, якщо робочий каталог--dirty .

Якщо ви не хочете додати зірочку, це працює, як і всі інші команди в попередніх відповідях:
git describe --always --abbrev=0 --match "NOT A TAG"
Результат:f5366ccb21588c0d7a5f7d9fa1d3f85e9f9d1ffe


Дякую, просто наткнувшись на це, і це
— позбавить

1
Це працює для мене без --match "NOT A TAG". Тестували в git 2.18.0, а також 2.7.4. Чи є якась ситуація, коли цей аргумент потрібен?
— Томас

@Thomas не працюватиме, якщо у вас є дедалі помічені теги десь в історії поточного комітету. Підроблений тег переконує, що команда description не використовує тег для опису фіксації,
— Rado

8
git show-ref --head --hash head

Якщо ви їдете на швидкість, підхід, згаданий Deestan

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

є значно швидшим, ніж будь-який інший перерахований тут метод.


show-refмені здається, найкращим варіантом для написання сценаріїв, так як це команда водопровідної і , таким чином , гарантується (або , по крайней мере , досить імовірно) , щоб залишатися стабільними в майбутніх версіях: інші відповіді використовувати rev-parse, show, describeабо log, що всі команди порцеляни. І у випадках, коли швидкість не є show-refсуттєвою, застосовується примітка на сторінці сторінки : "Застосовується використання цієї утиліти на користь прямого доступу до файлів у каталозі .git."
— Понт

6

Ось один вкладиш в оболонці Bash з використанням прямого зчитування з файлів git:

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

Вам потрібно запустити вище команду у вашій кореневій папці git.

Цей метод може бути корисним, коли у вас є файли репозиторію, але git команда не була встановлена.

Якщо нічого не вийде, перевірте в .git/refs/headsпапці, які голови у вас є.


5

у своєму домашньому режимі у файл ".gitconfig" додайте наступне

[alias]
sha = rev-parse HEAD

тоді у вас буде легша команда запам'ятати:

$ git sha
59fbfdbadb43ad0b6154c982c997041e9e53b600

3

На git bash просто запустіть $ git log -1

ви побачите, ці рядки слідують за вашою командою.

commit d25c95d88a5e8b7e15ba6c925a1631a5357095db .. (info about your head)

d25c95d88a5e8b7e15ba6c925a1631a5357095db, is your SHA for last commit.

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


0
cat .git/HEAD

Приклад виводу:

ref: refs/heads/master

Розберіть його:

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

Якщо у вас є вікна, ви можете скористатися wsl.exe:

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

Вихід:

refs/heads/master

Це значення може бути використане для того, щоб пізніше отримати порядок, але воно вказує на його SHA. Щоб вказати фактичну поточну гілку за її назвою:

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

Виходи:

master

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.