Jak odzyskać skrót dla bieżącego zatwierdzenia w Git?

1930

Chciałbym zachować (na razie) możliwość łączenia zestawów zmian Git z elementami roboczymi przechowywanymi w TFS.

Napisałem już narzędzie (używając haka z Git), w którym mogę wstrzykiwać identyfikatory robocze do wiadomości zestawu zmian Git.

Chciałbym jednak również zapisać identyfikator Git commit (skrót) w niestandardowym polu roboczym TFS. W ten sposób mogę zbadać element roboczy w TFS i zobaczyć, jakie zestawy zmian Git są powiązane z elementem roboczym.

Jak mogę łatwo pobrać skrót z bieżącego zatwierdzenia z Git?

Sardaukar
źródło

Odpowiedzi:

2807

Aby włączyć dowolny rozszerzony odniesienia do obiektu w SHA-1, należy po prostu git-rev parse np

git rev-parse HEAD

lub

git rev-parse --verify HEAD

Sidenote: Jeśli chcesz zamienić referencje ( oddziały i tagi ) w SHA-1, jest git show-refi git for-each-ref.

Jakub Narębski
źródło
81
--verifyoznacza, że:The parameter given must be usable as a single, valid object name. Otherwise barf and abort.
Linus Unnebäck
647
git rev-parse --short HEADzwraca krótką wersję skrótu, na wypadek, gdyby ktoś się zastanawiał.
Thane Brimhall
54
Dodając do tego, co powiedział Thane, możesz również dodać określoną długość --short, na przykład --short=12, aby uzyskać określoną liczbę cyfr z skrótu.
Tyson Phalp
31
@TysonPhalp: --short=Njest o minimalnej liczbie cyfr; git używa większej liczby cyfr, jeśli skrócona jedna byłaby nie do odróżnienia od skróconej drugiej zmiany. Spróbuj np . git rev-parse --short=2 HEADLub git log --oneline --abbrev=2.
Jakub Narębski
36
Dodając do tego, co powiedzieli Thane, Tyson i Jakub, możesz wydrukować pełny skrót, ale wyróżnij szesnastki niezbędne do zidentyfikowania niebieskiego zatwierdzenia za pomocągit rev-parse HEAD | GREP_COLORS='ms=34;1' grep $(git rev-parse --short=0 HEAD)
Zaz
423

Jeśli chcesz tylko skrócony skrót:

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

Ponadto użycie% H jest innym sposobem na uzyskanie długiego skrótu.

outofculture
źródło
106
Lub wydaje się, że dodanie --short do powyższej komendy rev-parsowania wydaje się działać.
outofculture 30.09.11
15
Myślę, że git logto porcelana i git rev-parsehydraulika.
Amedee Van Gasse
Jedną z zalet tej metody jest to, że zwróci krótką wersję skrótu o odpowiedniej długości dostosowanej do kolizji skrótu, które zdarzają się w przypadku większych repozytoriów. Przynajmniej w najnowszych wersjach git.
Ilia Sidorenko,
4
Jest to zły / niepoprawny sposób robienia tego, ponieważ ta metoda da ci zły hash, jeśli masz odłączoną głowę. Na przykład, jeśli bieżące zatwierdzenie to 12ab34 ... a poprzednie zatwierdzenie to 33aa44 ... to jeśli zrobię 'git checkout 33aa44', a następnie uruchomię polecenie, nadal będę wracał do 12ab34 ... pomimo mojej głowy do 33aa44 ...
theQuestionMan
3
@ theQuestionMan Nie doświadczam opisywanego zachowania; git checkout 33aa44; git log -n 1daje mi 33aa44. Jakiej wersji git używasz?
outofculture
150

Kolejny, używając git log:

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

Jest bardzo podobny do @outofculture, choć nieco krótszy.

Paul Pladijs
źródło
A wynik nie jest cytowany.
crokusek
5
To jest poprawna odpowiedź, ponieważ działa, nawet jeśli kasujesz konkretne zatwierdzenie zamiast HEAD.
Parsa
1
@Parsa: podczas sprawdzania konkretnego zatwierdzenia HEADwskazuje to zatwierdzenie, a nie nazwany branche znany jako odłączona głowa .
ChristofSenn
124

Aby uzyskać pełną SHA:

$ git rev-parse HEAD
cbf1b9a1be984a9f61b79a05f23b19f66d533537

Aby uzyskać skróconą wersję:

$ git rev-parse --short HEAD
cbf1b9a
Alexander
źródło
Jeśli git commitpotrzebne są dwa skróty, na przykład jeden z branchaktualnie master branchużywanego i a , możesz także użyć, git rev-parse FETCH_HEADjeśli potrzebujesz skrótu dla tego master commit, co merged w bieżącym branch. np. jeśli masz branches masteri feature/new-featuredla danego repo., podczas gdy feature/new-featuremożna go użyć, git fetch origin master && git merge FETCH_HEADa następnie, git rev-parse --short FETCH_HEADjeśli potrzebujesz commitskrótu z po masterprostu merged dla wszystkich skryptów, które możesz mieć.
EVAL
72

Dla kompletności, ponieważ nikt jeszcze tego nie zasugerował. .git/refs/heads/masterto plik zawierający tylko jedną linię: skrót najnowszego zatwierdzenia master. Więc możesz po prostu przeczytać to stamtąd.

Lub jako polecenie:

cat .git/refs/heads/master

Aktualizacja:

Zauważ, że git obsługuje teraz przechowywanie niektórych odniesień do głowy w pliku pack-ref zamiast jako pliku w folderze / refs / heads /. https://www.kernel.org/pub/software/scm/git/docs/git-pack-refs.html

Deestan
źródło
10
Zakłada się, że obecna gałąź jest master, co niekoniecznie jest prawdą.
gavrie
12
W rzeczy samej. Dlatego wyraźnie powiedziałem, że to jest master.
Deestan
20
.git/HEADzazwyczaj wskazuje na ref, jeśli masz tam SHA1, jesteś w trybie odłączonej głowy.
eckes
8
Nie jest to bardzo solidne w porównaniu z innymi podejściami, w szczególności dlatego, że zakłada istnienie .gitpodkatalogu, co niekoniecznie ma miejsce. Zobacz --separate-git-dirflagę na git initstronie man.
jub0bs
16
Because1, ponieważ czasami nie chcesz instalować git wykonywalnego (np. W Dockerfile)
wim
50

Zatwierdź skrót

git show -s --format=%H

Skrót skrótu zatwierdzenia

git show -s --format=%h

Kliknij tutaj, aby uzyskać więcej git showprzykładów.

ecwpz91
źródło
50

Zawsze git describeteż jest. Domyślnie daje ci -

john@eleanor:/dev/shm/mpd/ncmpc/pkg (master)$ git describe --always
release-0.19-11-g7a68a75
John Tyree
źródło
18
Git description zwraca pierwszą TAG dostępną z zatwierdzenia. W jaki sposób pomaga mi to uzyskać SHA?
Sardaukar,
42
Podoba mi się, git describe --long --dirty --abbrev=10 --tagsże da mi coś takiego, 7.2.0.Final-447-g65bf4ef2d4co wynosi 447 zatwierdzeń po tagu 7.2.0.Final i pierwsze 10 skrótów globalnego SHA-1 w bieżącym HEAD to „65bf4ef2d4”. Jest to bardzo dobre dla ciągów wersji. Z opcją --long zawsze doda liczbę (-0-) i skrót, nawet jeśli tag pasuje dokładnie.
eckes
14
Jeśli nie istnieją żadne tagi, wówczas git describe --always„pokaże unikalny skrót obiektu zatwierdzenia jako rezerwowego”
Ronny Andersson,
Używam git describe --tags --first-parent --abbrev=11 --long --dirty --always. Ta --alwaysopcja oznacza, że ​​zapewnia wynik (skrót), nawet jeśli nie ma żadnych tagów. Te --first-parentśrodki nie zobowiązuje się mylić scalania i wyłącznie następujące elementy na bieżącej gałęzi. Zauważ też, że --dirtyzostanie dołączony -dirtydo wyniku, jeśli bieżąca gałąź ma niezatwierdzone zmiany.
ingyhere
30

Posługiwać się git rev-list --max-count=1 HEAD

Robert Munteanu
źródło
3
git-rev-list dotyczy generowania listy obiektów zatwierdzania; git-rev-parse tłumaczy nazwę obiektu (np. HEAD) na SHA-1
Jakub Narębski
21

Jeśli chcesz przechowywać skrót w zmiennej podczas skryptu, możesz użyć

last_commit=$(git rev-parse HEAD)

Lub jeśli chcesz tylko pierwszych 10 znaków (jak robi to github.com)

last_commit=$(git rev-parse HEAD | cut -c1-10) 
Henk
źródło
26
Istnieją również parametry --shortlub ; nie ma potrzeby używania rury i . --short=numbergit rev-parsecut
Julian D.
15

Jeśli chcesz zrobić super-hacky sposób:

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

Zasadniczo git przechowuje lokalizację HEAD w .git / HEAD, w formie ref: {path from .git}. To polecenie czyta to, oddziela „ref:” i odczytuje wskazany plik.

To oczywiście zawiedzie w trybie odłączonej głowy, ponieważ HEAD nie będzie „ref: ...”, ale sam hash - ale wiesz, nie sądzę, że spodziewasz się tyle mądrości w twoim bashu -linery. Jeśli nie uważasz, że średniki oszukują ...

HASH="ref: HEAD"; while [[ $HASH == ref\:* ]]; do HASH="$(cat ".git/$(echo $HASH | cut -d \  -f 2)")"; done; echo $HASH
Fordi
źródło
1
nie ma potrzeby instalowania gita, podoba mi się. (mój obraz kompilacji dokera nie ma git)
Helin Wang
przydatne, ponieważ możesz to łatwo uruchomić spoza repozytorium git
samaspin
Sformalizowałem to w skrypcie dla mojego komputera lokalnego. Potem pomyślałem, hej: implementacja, którą wykonałem, jest na tyle prosta, że ​​ilustruje, jak rozwiązać niepowiązany problem (analizowanie argumentów w surowych skryptach powłoki POSIX bez programów zewnętrznych), ale na tyle złożona, aby zapewnić niewielką różnorodność i wykorzystać większość cechy sh. Pół godziny komentarzy do dokumentacji później, a oto streszczenie
Fordi
Patrząc na to, stworzyłem bardziej rozbudowaną wersję do wykrywania Git i SVN i pobierania wersji Git Hash / SVN. Tym razem nie jest to czysty ciąg, ale łatwo go przeanalizowano i można go użyć jako tagu wersji: gist.github.com/Fordi/8f1828efd820181f24302b292670b14e
Fordi
14

Najbardziej zwięzły sposób, jaki znam:

git show --pretty=%h 

Jeśli chcesz określoną liczbę cyfr skrótu, możesz dodać:

--abbrev=n
Brian Peterson
źródło
14
Chociaż technicznie to działa, git showjest to tak zwane polecenie porcelanowe (tj. Skierowane do użytkownika), dlatego nie powinno się go używać w skryptach, ponieważ jego wyniki mogą ulec zmianie. git rev-parse --short HEADZamiast tego należy użyć powyższej odpowiedzi ( ).
jm3
4
@ jm3 wstecz. Polecenia „Porcelana” mają stabilne wyjścia przeznaczone dla skryptów. Szukaj git help showdla porcelain.
John Tyree,
2
@JohnTyree To mylący temat, ale jm3 miał rację: polecenia porcelany nie mają być analizowane, ale raczej czytelne dla człowieka. W przypadku, gdy musisz użyć polecenia skryptu z porcelany i chcesz mieć stabilny format, czasami jest (na przykład ze statusem git, push and win) opcja, która właśnie to robi. Niestety ta opcja jest wywoływana --porcelain, dlatego jest to mylące. Możesz znaleźć szczegóły w tej wspaniałej odpowiedzi VonC
Fabio mówi Przywróć Monikę
1
drogi Boże, który postanowił nazwać tę opcję - Porcelana Chcę je znaleźć i ... och, czekam, muszę użyć git, aby je znaleźć nieważne
Britton Kerin
14

Być może potrzebujesz aliasu, abyś nie musiał pamiętać wszystkich fajnych szczegółów. Po wykonaniu jednego z poniższych kroków będziesz mógł po prostu wpisać:

$ git lastcommit
49c03fc679ab11534e1b4b35687b1225c365c630

W odpowiedzi na przyjętą odpowiedź , oto dwa sposoby skonfigurowania tego:

1) Naucz git jawnie, edytując globalną konfigurację (moja oryginalna odpowiedź):

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

2) Lub jeśli lubisz skrót, aby nauczyć go, jak ostatnio skomentował Adrien:

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

Odtąd użyj, git lastcommitaby pokazać skrót ostatniego zatwierdzenia.

miraculixx
źródło
3
Adrien de Sentenac zauważa, że ​​zamiast ręcznie edytować plik konfiguracyjny git, możesz po prostu zrobić:git config --global alias.lastcommit "rev-parse HEAD"
cgmb,
12

Potrzebowałem czegoś nieco innego: wyświetl pełny sha1 zatwierdzenia, ale dodaj gwiazdkę na końcu, jeśli katalog roboczy nie jest czysty. O ile nie chcę używać wielu poleceń, żadna z opcji z poprzednich odpowiedzi nie działa.

Oto jedna wkładka, która:
git describe --always --abbrev=0 --match "NOT A TAG" --dirty="*"
Wynik:f5366ccb21588c0d7a5f7d9fa1d3f85e9f9d1ffe*

Objaśnienie: opisuje (przy użyciu tagów z adnotacjami) bieżące zatwierdzenie, ale tylko z tagami zawierającymi „NOT A TAG”. Ponieważ znaczniki nie mogą mieć spacji, to nigdy nie pasuje do znacznika, a ponieważ chcemy pokazać wynik --always, polecenie cofa się, wyświetlając pełny ( --abbrev=0) sha1 zatwierdzenia i dodaje gwiazdkę, jeśli katalog roboczy to--dirty .

Jeśli nie chcesz dodawać gwiazdki, działa to tak, jak wszystkie inne polecenia z poprzednich odpowiedzi:
git describe --always --abbrev=0 --match "NOT A TAG"
Wynik:f5366ccb21588c0d7a5f7d9fa1d3f85e9f9d1ffe

Rado
źródło
Dzięki, tylko się o to
potknąłem
1
Działa dla mnie bez --match "NOT A TAG". Testowane w git 2.18.0 oraz 2.7.4. Czy jest jakaś sytuacja, w której ten argument jest potrzebny?
Thomas
@ Thomas nie zadziała, jeśli w dowolnym miejscu w historii bieżącego zatwierdzenia masz tag z adnotacjami. Fałszywy znacznik upewnia się, że polecenie Opis nie używa znacznika do opisania zatwierdzenia,
Rado
8
git show-ref --head --hash head

Jeśli zależy ci na prędkości, podejście wspomniane przez Deestana

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

jest znacznie szybszy niż jakakolwiek inna metoda tu wymieniona.

Dennis
źródło
show-refWydaje mi się, że najlepszym rozwiązaniem dla skryptów, ponieważ jest to komenda instalacji wodociągowej, a tym samym gwarantuje (lub przynajmniej bardzo prawdopodobne), aby pozostać stabilne w przyszłych wydaniach: inne odpowiedzi użyć rev-parse, show, describelub log, które są wszystkie polecenia porcelany. A w przypadkach, w których szybkość nie jest istotna, obowiązuje uwaga ze strony show-refpodręcznika: „Zachęcamy do korzystania z tego narzędzia na rzecz bezpośredniego dostępu do plików w katalogu .git”.
Pont
6

Oto jednowierszowy w powłoce Bash przy użyciu bezpośredniego odczytu z plików git:

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

Musisz uruchomić powyższą komendę w folderze głównym git.

Ta metoda może być przydatna, gdy masz pliki repozytorium, ale gitpolecenie nie zostało zainstalowane.

Jeśli nie zadziała, sprawdź w .git/refs/headsfolderze, jakie masz głowice.

kenorb
źródło
5

w swoim katalogu domowym w pliku „.gitconfig” dodaj:

[alias]
sha = rev-parse HEAD

będziesz miał łatwiejsze do zapamiętania polecenie:

$ git sha
59fbfdbadb43ad0b6154c982c997041e9e53b600
jo_
źródło
3

Na git bash po prostu uruchom $ git log -1

zobaczysz te wiersze po twoim poleceniu.

commit d25c95d88a5e8b7e15ba6c925a1631a5357095db .. (info about your head)

d25c95d88a5e8b7e15ba6c925a1631a5357095db, is your SHA for last commit.
Zwariowany
źródło
0

Oto kolejna implementacja bezpośredniego dostępu:

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

Działa to również na http, co jest przydatne w lokalnych archiwach pakietów (wiem: w przypadku publicznych stron internetowych nie jest zalecane, aby katalog .git był dostępny):

head="$(curl -s "$baseurl/.git/HEAD")"
while [ "$head" != "${head#ref: }" ]; do
  head="$(curl -s "$baseurl/.git/${head#ref: }")"
done
Daniel Alder
źródło
0

Oto inny sposób na zrobienie tego z :)

git log | grep -o '\w\{8,\}' | head -n 1
Marcelo Lazaroni
źródło
0
cat .git/HEAD

Przykładowe dane wyjściowe:

ref: refs/heads/master

Parsuj to:

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

Jeśli masz system Windows, możesz rozważyć użycie wsl.exe:

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

Wynik:

refs/heads/master

Tej wartości można użyć do późniejszego pobrania kasy, ale wskazuje ona na jej SHA. Aby wskazywał na aktualną gałąź według nazwy, wykonaj następujące czynności:

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

Wyjścia:

master

Siergiej
źródło