Sto provando a fare cose fantasiose qui con i ganci Git, ma non so davvero come farlo (o se è possibile).
Quello che devo fare è: in ogni commit voglio prendere il suo hash e quindi aggiornare un file nel commit con questo hash.
Qualche idea?
Sto provando a fare cose fantasiose qui con i ganci Git, ma non so davvero come farlo (o se è possibile).
Quello che devo fare è: in ogni commit voglio prendere il suo hash e quindi aggiornare un file nel commit con questo hash.
Qualche idea?
Risposte:
Consiglierei di fare qualcosa di simile a quello che hai in mente: posizionare SHA1 in un file non tracciato , generato come parte del processo di compilazione / installazione / distribuzione. È ovviamente facile da fare ( git rev-parse HEAD > filename
o forse git describe [--tags] > filename
), ed evita di fare qualcosa di folle come finire con un file diverso dal tracciamento di Git.
Il codice può quindi fare riferimento a questo file quando è necessario il numero di versione o un processo di generazione potrebbe incorporare le informazioni nel prodotto finale. Quest'ultimo è in realtà il modo in cui git stesso ottiene i suoi numeri di versione: il processo di compilazione estrae il numero di versione dal repository, quindi lo crea nell'eseguibile.
È impossibile scrivere l'hash di commit corrente: se riesci a pre-calcolare l'hash di commit futuro - cambierà non appena modifichi qualsiasi file.
Tuttavia, ci sono tre opzioni:
pre-commit
, archivia l' hash di commit precedente :) Non modificare / inserire i commit nel 99,99% dei casi, quindi, funzionerà. Nel peggiore dei casi è ancora possibile identificare la revisione della fonte.Sto lavorando a uno script hook, lo pubblicherò qui 'quando avrà finito', ma comunque - prima che Duke Nukem Forever venga rilasciato :))
Aggiornamento : codice per .git/hooks/pre-commit
:
#!/usr/bin/env bash
set -e
#=== 'prev-commit' solution by o_O Tync
#commit_hash=$(git rev-parse --verify HEAD)
commit=$(git log -1 --pretty="%H%n%ci") # hash \n date
commit_hash=$(echo "$commit" | head -1)
commit_date=$(echo "$commit" | head -2 | tail -1) # 2010-12-28 05:16:23 +0300
branch_name=$(git symbolic-ref -q HEAD) # http://stackoverflow.com/questions/1593051/#1593487
branch_name=${branch_name##refs/heads/}
branch_name=${branch_name:-HEAD} # 'HEAD' indicates detached HEAD situation
# Write it
echo -e "prev_commit='$commit_hash'\ndate='$commit_date'\nbranch='$branch'\n" > gitcommit.py
Ora l'unica cosa di cui abbiamo bisogno è uno strumento che converta la prev_commit,branch
coppia in un vero hash di commit :)
Non so se questo approccio sia in grado di distinguere gli impegni di fusione. Lo verificherò presto
Qualcuno mi ha indicato la sezione "man gitattributes" su ident, che ha questo:
ident
Quando l'attributo ident è impostato per un percorso, git sostituisce $ Id $ nell'oggetto BLOB con $ Id :, seguito dal nome dell'oggetto BLOB esadecimale di 40 caratteri, seguito da un simbolo di dollaro $ al momento del pagamento. Qualsiasi sequenza di byte che inizia con $ Id: e termina con $ nel file worktree viene sostituita con $ Id $ al momento del check-in.
Se ci pensate, questo è ciò che fanno anche CVS, Subversion, ecc. Se guardi il repository, vedrai che il file nel repository contiene sempre, ad esempio, $ Id $. Non contiene mai l'espansione di quello. È solo alla cassa che il testo viene espanso.
ident
è l'hash per il file stesso, non l'hast del commit. Da git-scm.com/book/en/… : "Tuttavia, quel risultato è di uso limitato. Se hai utilizzato la sostituzione di parole chiave in CVS o Subversion, puoi includere un datestamp: lo SHA non è poi così utile, perché è abbastanza casuale e non si può dire se uno SHA è più vecchio o più recente di un altro. " filter
funziona, ma può ottenere le informazioni di commit in (e fuori) da un file.
Ciò può essere ottenuto utilizzando l' filter
attributo in gitattributes . Dovresti fornire un smudge
comando che inserisce l'id di commit e un clean
comando che lo rimuova, in modo tale che il file in cui è inserito non cambierà solo a causa dell'ID di commit.
Pertanto, l'ID commit non viene mai archiviato nel BLOB del file; è appena stato ampliato nella tua copia di lavoro. (L'inserimento effettivo dell'ID commit nel BLOB diventerebbe un compito infinitamente ricorsivo. ☺) Chiunque cloni questo albero dovrebbe impostare gli attributi per se stesso.
Pensa fuori dagli schemi!
inseriscilo nei file hook / post-checkout
#!/bin/sh
git describe --all --long > config/git-commit-version.txt
La versione sarà disponibile ovunque tu la usi.
Permettetemi di esplorare perché questo è un problema difficile usando gli interni git. È possibile ottenere lo sha1 del commit corrente da
#!/bin/bash
commit=$(git cat-file commit HEAD) #
sha1=($((printf "commit %s\0" $(echo "$commit" | wc -c); echo "$commit") | sha1sum))
echo ${sha1[0]}
Essenzialmente si esegue un checksum sha1 sul messaggio restituito da git cat-file commit HEAD
. Due cose saltano immediatamente fuori come un problema quando si esamina questo messaggio. Uno è l'albero sha1 e il secondo è il tempo di commit.
Ora è possibile gestire facilmente il tempo di commit modificando il messaggio e indovinando quanto tempo ci vuole per effettuare un commit o una pianificazione per eseguire il commit in un momento specifico. Il vero problema è l'albero sha1, da cui è possibile ottenere git ls-tree $(git write-tree) | git mktree
. Essenzialmente stai facendo un checksum sha1 sul messaggio da ls-tree, che è un elenco di tutti i file e il loro checksum sha1.
Pertanto il checksum commit sha1 dipende dal checksum sha1 dell'albero, che dipende direttamente dai file checksum sha1 dei file, che completa il cerchio e dipende dal commit sha1. Quindi hai un problema circolare con le tecniche a mia disposizione.
Con checksum meno sicuri , è stato dimostrato che è possibile scrivere il checksum del file nel file stesso tramite forza bruta; tuttavia, non conosco alcun lavoro che abbia portato a termine questo compito con sha1. Questo non è impossibile, ma quasi impossibile con la nostra attuale comprensione (ma chissà forse tra un paio d'anni sarà banale). Tuttavia, è ancora più difficile forzare la forza poiché è necessario scrivere il checksum (commit) di un checksum (albero) di un checksum (BLOB) nel file.