Comment récupérer le hachage pour le commit actuel dans Git?

1934

Je voudrais conserver (pour l'instant) la possibilité de lier les ensembles de modifications Git aux éléments de travail stockés dans TFS.

J'ai déjà écrit un outil (en utilisant un hook de Git) dans lequel je peux injecter des identifiants de travail dans le message d'un changeset Git.

Cependant, je voudrais également stocker l'identifiant de la validation Git (le hachage) dans un champ d'élément de travail TFS personnalisé. De cette façon, je peux examiner un élément de travail dans TFS et voir quels ensembles de modifications Git sont associés à l'élément de travail.

Comment puis-je récupérer facilement le hachage à partir du commit actuel de Git?

Sardaukar
la source

Réponses:

2810

Pour transformer une référence d'objet étendu arbitraire en SHA-1, utilisez simplement git-rev-parse , par exemple

git rev-parse HEAD

ou

git rev-parse --verify HEAD

Sidenote: Si vous voulez transformer des références ( branches et balises ) en SHA-1, il y agit show-refetgit for-each-ref.

Jakub Narębski
la source
81
--verifyimplique que:The parameter given must be usable as a single, valid object name. Otherwise barf and abort.
Linus Unnebäck
648
git rev-parse --short HEADrenvoie la version courte du hachage, juste au cas où quelqu'un se demanderait.
Thane Brimhall
55
En plus de ce que Thane a dit, vous pouvez également ajouter une longueur spécifique à --short, par exemple --short=12, pour obtenir un nombre spécifique de chiffres du hachage.
Tyson Phalp
32
@TysonPhalp: --short=Ncorrespond à un nombre minimal de chiffres; git utilise un plus grand nombre de chiffres si un raccourci ne se distingue pas d'un autre commit raccourci. Essayez par exemple git rev-parse --short=2 HEADou git log --oneline --abbrev=2.
Jakub Narębski
36
Ajoutant à ce que Thane, Tyson et Jakub ont dit, vous pouvez imprimer le hachage complet, mais mettez en surbrillance les hexits nécessaires pour identifier le bleu de validation avecgit rev-parse HEAD | GREP_COLORS='ms=34;1' grep $(git rev-parse --short=0 HEAD)
Zaz
424

Si vous souhaitez uniquement le hachage raccourci:

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

De plus, l'utilisation de% H est une autre façon d'obtenir le long hachage.

hors culture
la source
107
Ou, semble-t-il, l'ajout de --short à la commande rev-parse ci-dessus semble fonctionner.
outofculture
15
Je pense que git logc'est la porcelaine et la git rev-parseplomberie.
Amedee Van Gasse
L'un des avantages de cette méthode est qu'elle renverra la version courte du hachage avec la bonne longueur ajustée aux collisions de hachage qui se produisent pour les dépôts plus importants. Au moins dans les versions récentes de git.
Ilia Sidorenko
4
C'est une façon incorrecte / incorrecte de le faire car cette méthode vous donnera le mauvais hachage si vous avez une tête détachée. Par exemple, si le commit actuel est 12ab34 ... et le commit précédent était 33aa44 ... alors si je fais 'git checkout 33aa44' puis j'exécute votre commande, je reviendrai toujours 12ab34 ... malgré ma tête pointant à 33aa44 ...
theQuestionMan
3
@theQuestionMan Je ne ressens pas le comportement que vous décrivez; git checkout 33aa44; git log -n 1me donne 33aa44. Quelle version de git utilisez-vous?
outofculture
150

Un autre, en utilisant git log:

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

Il est très similaire à celui de @outofculture mais un peu plus court.

Paul Pladijs
la source
Et le résultat n'est pas simple.
crokusek
5
C'est la bonne réponse, car cela fonctionne même si vous extrayez un commit spécifique au lieu de HEAD.
Parsa
1
@Parsa: lorsque vous extrayez un commit spécifique, pointez HEADsur ce commit plutôt qu'une branche nommée connue sous le nom de tête détachée .
ChristofSenn
125

Pour obtenir le SHA complet:

$ git rev-parse HEAD
cbf1b9a1be984a9f61b79a05f23b19f66d533537

Pour obtenir la version raccourcie:

$ git rev-parse --short HEAD
cbf1b9a
Alexandre
la source
Si deux git commithachages sont nécessaires, comme l'un de celui branchavec lequel vous travaillez actuellement et un master branch, vous pouvez également l'utiliser git rev-parse FETCH_HEADsi vous avez besoin du hachage pour celui master commitque vous avez mergeajouté à votre courant branch. Par exemple, si vous avez branches masteret feature/new-featurepour un repo donné, alors feature/new-featurevous pouvez utiliser git fetch origin master && git merge FETCH_HEADet git rev-parse --short FETCH_HEADsi vous avez besoin du commithachage du mastervous venez de le merged pour tous les scripts que vous pourriez avoir.
EVAL
72

Pour être complet, puisque personne ne l'a encore suggéré. .git/refs/heads/masterest un fichier qui ne contient qu'une seule ligne: le hachage du dernier commit sur master. Vous pouvez donc le lire à partir de là.

Ou, comme commande:

cat .git/refs/heads/master

Mise à jour:

Notez que git prend désormais en charge le stockage de certaines références de tête dans le fichier pack-ref au lieu d'un fichier dans le dossier / refs / heads /. https://www.kernel.org/pub/software/scm/git/docs/git-pack-refs.html

Deestan
la source
10
Cela suppose que la branche actuelle est master, ce qui n'est pas nécessairement vrai.
gavrie
12
En effet. C'est pourquoi j'ai dit explicitement que c'était pour master.
Deestan
20
.git/HEADpointe généralement vers une référence, si vous avez un SHA1 dedans, vous êtes en mode tête détachée.
eckes
8
Ce n'est pas très robuste par rapport à d'autres approches, notamment parce qu'il suppose qu'il existe un .gitsous - répertoire, ce qui n'est pas forcément le cas. Voir le --separate-git-dirdrapeau dans la git initpage de manuel.
jub0bs
16
+1 parce que parfois vous ne voulez pas que l'exécutable git soit installé (par exemple dans votre Dockerfile)
wim
50

Valider le hachage

git show -s --format=%H

Hachage de validation abrégé

git show -s --format=%h

Cliquez ici pour plus d' git showexemples.

ecwpz91
la source
50

Il y en a toujours git describeaussi. Par défaut, cela vous donne -

john@eleanor:/dev/shm/mpd/ncmpc/pkg (master)$ git describe --always
release-0.19-11-g7a68a75
John Tyree
la source
18
Git describe renvoie le premier TAG accessible depuis une validation. Comment cela m'aide-t-il à obtenir le SHA?
Sardaukar
42
J'aime que git describe --long --dirty --abbrev=10 --tagscela me donne quelque chose comme 7.2.0.Final-447-g65bf4ef2d4447 commits après la balise 7.2.0.Final et les 10 premiers condensés du SHA-1 global à la HEAD actuelle sont "65bf4ef2d4". C'est très bon pour les chaînes de version. Avec --long, il ajoutera toujours le nombre (-0-) et le hachage, même si la balise correspond exactement.
eckes
14
S'il n'y a pas de balises git describe --always, "affichera l'objet de validation abrégé de manière unique comme solution de repli"
Ronny Andersson
J'utilise git describe --tags --first-parent --abbrev=11 --long --dirty --always. L' --alwaysoption signifie qu'elle fournit un résultat (hachage) même s'il n'y a pas de balises. Les --first-parentmoyens qu'il ne soit pas confondu par commits de fusion et suit uniquement les éléments sur la branche courante. Notez également que --dirtycela s'ajoutera -dirtyau résultat si la branche actuelle a des modifications non validées.
ingyhere
30

Utilisation git rev-list --max-count=1 HEAD

Robert Munteanu
la source
3
git-rev-list consiste à générer une liste d'objets de validation; c'est git-rev-parse pour traduire le nom de l'objet (par exemple HEAD) en SHA-1
Jakub Narębski
21

Si vous devez stocker le hachage dans une variable pendant un script, vous pouvez utiliser

last_commit=$(git rev-parse HEAD)

Ou, si vous ne voulez que les 10 premiers caractères (comme le fait github.com)

last_commit=$(git rev-parse HEAD | cut -c1-10) 
Henk
la source
26
Il y a aussi les paramètres --shortou --short=numberpour git rev-parse; pas besoin d'utiliser un tuyau et cut.
Julian D.
15

Si vous voulez le faire de manière super-hacky:

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

Fondamentalement, git stocke l'emplacement de HEAD dans .git / HEAD, sous la forme ref: {path from .git}. Cette commande lit cela, supprime le "ref:" et lit le fichier vers lequel il pointait.

Bien sûr, cela échouera en mode tête détachée, car HEAD ne sera pas "ref: ...", mais le hachage lui-même - mais vous savez, je ne pense pas que vous vous attendiez à autant d'intelligence dans votre bash one -liner. Si vous ne pensez pas que les points-virgules trichent, cependant ...

HASH="ref: HEAD"; while [[ $HASH == ref\:* ]]; do HASH="$(cat ".git/$(echo $HASH | cut -d \  -f 2)")"; done; echo $HASH
Fordi
la source
1
pas besoin d'installer git, j'aime ça. (mon image de construction de docker n'a pas de git)
Helin Wang
également utile car vous pouvez l'exécuter facilement depuis l'extérieur du
dépôt
J'ai officialisé cela en un script pour ma machine locale. Ensuite, j'ai pensé, hé: l'implémentation que j'ai faite est assez simple pour illustrer comment résoudre un problème sans rapport (analyse des arguments dans des scripts shell POSIX bruts sans programmes externes), mais assez complexe pour fournir une petite variation et exploiter la plupart des caractéristiques de sh. Une demi-heure de commentaires sur la documentation plus tard, et en voici un résumé
Fordi
En le regardant, j'ai fait une version plus étendue pour détecter Git et SVN, et saisir la révision git hash / svn. Pas une chaîne propre cette fois, mais facilement analysée en ligne de commande, et utilisable comme balise de version: gist.github.com/Fordi/8f1828efd820181f24302b292670b14e
Fordi
14

La manière la plus succincte que je connaisse:

git show --pretty=%h 

Si vous voulez un nombre spécifique de chiffres du hachage, vous pouvez ajouter:

--abbrev=n
Brian Peterson
la source
14
Bien que cela fonctionne techniquement, git showc'est ce qu'on appelle une commande porcelaine (c'est-à-dire accessible à l'utilisateur), et ne doit donc pas être utilisée dans les scripts car sa sortie est sujette à changement. La réponse ci-dessus ( git rev-parse --short HEAD) doit être utilisée à la place.
jm3
4
@ jm3 c'est à l'envers. Les commandes "Porcelaine" ont des sorties stables destinées aux scripts. Recherche git help showpour porcelain.
John Tyree
2
@JohnTyree C'est un sujet déroutant, mais jm3 avait raison: les commandes de porcelaine ne sont pas censées être analysées, mais plutôt être lisibles par l'homme. Dans le cas où vous devez utiliser une commande porcelain dans un script et que vous souhaitez avoir un format stable, il y a parfois (par exemple avec git status, push and blame) une option qui fait exactement cela. Malheureusement, cette option est appelée --porcelain, c'est pourquoi cela prête à confusion. Vous pouvez trouver les détails dans cette excellente réponse de VonC
Fabio dit de rétablir Monica le
1
cher dieu qui a décidé de nommer cette option - porcelaine, je veux les trouver et ... oh attendez, je devrais utiliser git pour les trouver
Britton Kerin
14

Peut-être que vous voulez un alias pour ne pas avoir à vous souvenir de tous les détails astucieux. Après avoir effectué l'une des étapes ci-dessous, vous pourrez simplement taper:

$ git lastcommit
49c03fc679ab11534e1b4b35687b1225c365c630

Pour donner suite à la réponse acceptée , voici deux façons de procéder:

1) Apprenez à git de manière explicite en éditant la configuration globale (ma réponse d'origine):

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

2) Ou si vous aimez un raccourci pour enseigner à git un raccourci, comme l'a récemment commenté Adrien:

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

À partir de là, utilisez git lastcommitpour afficher le hachage du dernier commit.

miraculixx
la source
3
Adrien de Sentenac note qu'au lieu de modifier manuellement le fichier de configuration git, vous pouvez simplement faire:git config --global alias.lastcommit "rev-parse HEAD"
cgmb
12

J'avais besoin de quelque chose d'un peu plus différent: afficher le sha1 complet du commit, mais ajouter un astérisque à la fin si le répertoire de travail n'est pas propre. À moins que je veuille utiliser plusieurs commandes, aucune des options des réponses précédentes ne fonctionne.

Voici la doublure qui le fait:
git describe --always --abbrev=0 --match "NOT A TAG" --dirty="*"
Résultat:f5366ccb21588c0d7a5f7d9fa1d3f85e9f9d1ffe*

Explication: décrit (à l'aide de balises annotées) la validation actuelle, mais uniquement avec des balises contenant "NOT A TAG". Étant donné que les balises ne peuvent pas avoir d'espaces, cela ne correspond jamais à une balise et puisque nous voulons afficher un résultat --always, la commande revient à afficher le full ( --abbrev=0) sha1 du commit et elle ajoute un astérisque si le répertoire de travail l'est --dirty.

Si vous ne souhaitez pas ajouter l'astérisque, cela fonctionne comme toutes les autres commandes des réponses précédentes:
git describe --always --abbrev=0 --match "NOT A TAG"
Résultat:f5366ccb21588c0d7a5f7d9fa1d3f85e9f9d1ffe

Rado
la source
Merci, juste en trébuchant dessus et cela m'épargne l'un ou l'autre écho pour ça :)
hakre
1
Cela fonctionne pour moi sans --match "NOT A TAG". Testé dans git 2.18.0 ainsi que 2.7.4. Y a-t-il une situation où cet argument est nécessaire?
Thomas
@Thomas, cela ne fonctionnera pas si vous avez une balise annotée n'importe où dans l'historique du commit actuel. La fausse balise s'assure que la commande describe n'utilise pas de balise pour décrire le commit,
Rado
8
git show-ref --head --hash head

Si vous optez pour la vitesse, l'approche mentionnée par Deestan

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

est nettement plus rapide que toute autre méthode répertoriée ici jusqu'à présent.

Dennis
la source
show-refme semble être la meilleure option pour les scripts, car il est une commande de plomberie et donc garantie (ou tout au moins très probable) de rester stable dans les prochaines versions: d' autres réponses utilisent rev-parse, show, describeou log, qui sont toutes les commandes de porcelaine. Et dans les cas où la vitesse n'est pas essentielle, la note de la show-refpage de manuel s'applique: 'L'utilisation de cet utilitaire est encouragée en faveur d'un accès direct aux fichiers sous le répertoire .git.'
Pont
6

Voici une ligne dans le shell Bash utilisant la lecture directe à partir de fichiers git:

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

Vous devez exécuter la commande ci-dessus dans votre dossier racine git.

Cette méthode peut être utile lorsque vous avez des fichiers de référentiel, mais que la gitcommande n'a pas été installée.

Si cela ne fonctionne pas, vérifiez dans le .git/refs/headsdossier quel type de têtes avez-vous présent.

kenorb
la source
5

dans votre répertoire personnel dans le fichier ".gitconfig", ajoutez ce qui suit

[alias]
sha = rev-parse HEAD

alors vous aurez une commande plus facile à retenir:

$ git sha
59fbfdbadb43ad0b6154c982c997041e9e53b600
jo_
la source
3

Sur git bash, exécutez simplement $ git log -1

vous verrez, ces lignes suivant votre commande.

commit d25c95d88a5e8b7e15ba6c925a1631a5357095db .. (info about your head)

d25c95d88a5e8b7e15ba6c925a1631a5357095db, is your SHA for last commit.
Batty
la source
0

Voici une autre implémentation à accès direct:

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

Cela fonctionne également sur http, ce qui est utile pour les archives de paquets locaux (je sais: pour les sites Web publics, il n'est pas recommandé de rendre le répertoire .git accessible):

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

Voici une autre façon de le faire avec :)

git log | grep -o '\w\{8,\}' | head -n 1
Marcelo Lazaroni
la source
0
cat .git/HEAD

Exemple de sortie:

ref: refs/heads/master

Analysez-le:

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

Si vous avez des fenêtres, vous pouvez envisager d'utiliser wsl.exe:

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

Production:

refs/heads/master

Cette valeur peut être utilisée pour git checkout plus tard, mais elle pointe vers son SHA. Pour faire pointer vers la branche actuelle réelle par son nom, procédez comme suit:

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

Les sorties:

master

Sergei
la source