Come trovo il commit git più recente che ha modificato un file?


180

Voglio trovare il commit più recente che ha modificato un file di origine.

Posso usare git blameper vedere tutte le date per i commit di ogni riga, ma è difficile vedere esattamente quale commit è stato l'ultimo a toccare il file.

Come posso trovare l'ultimo commit che ha toccato un determinato file nel mio repository git?

Risposte:


230

git log supporta la visualizzazione della cronologia di file (e directory) specifici, quindi puoi chiamarla così:

git log my/file.c

Se vuoi davvero elencare solo il commit più recente, ad esempio per usarlo in uno script, usa l' -n 1opzione:

git log -n 1 --pretty=format:%H -- my/file.c

--pretty=format:%hdice git logdi mostrare solo l'hash di commit. Il --separatore impedisce che il nome del file venga interpretato come nome di commit, nel caso in cui sia ambiguo.


12
Se vuoi sapere l'ultima volta che un file è stato modificato indipendentemente dal ramo, puoi considerare tutti i rami aggiungendo l' --allopzione.
KC

44

Se vuoi solo trovare il commit più recente, allora non vuoi git-log, vuoi git-rev-list, che elenca gli oggetti di commit cambiando quel file, in quel percorso di commit, iniziando con quello più recente (in ordine cronologico). In poche parole:

git rev-list -1 <commit> <filename>

Per git-rev-listnel tuo caso, è sufficiente fornire:

  • Il numero di commit da includere, o -1 solo per il più recente,
  • Il ramo (o commettono id) per iniziare la ricerca indietro da, HEAD se sei già su di esso, o --all se si desidera che tutti i commit noti e
  • Il percorso relativo al tuo file.

Questo restituisce solo l'ID commit più recente nel ramo corrente per modificare quel file, ad esempio: 215095e2e338525be0baeeebdf66bfbb304e7270

Per un esempio più complesso, è possibile utilizzare nomi di tag e persino riferimenti remoti e includere nomi di percorso relativi con caratteri jolly, ad esempio:

git rev-list origin/user/bob/testbranch -1 src/bfiles/*.txt

... Che ti direbbe quale è stata la modifica più recente alla corrispondenza con caratteri jolly nella storia di quel ramo. Le opzioni per rev-list sono estreme, è uno dei comandi idraulici più importanti, quindi puoi includere o escludere con qualsiasi criterio tu possa immaginare.

Naturalmente, consultare la pagina di manuale di git-rev-list (1) .


Non hai davvero spiegato perché l'utilizzo git-logsia inferiore.
Piotr Dobrogost,

7
Non direi inferiore, solo che fornisce informazioni estranee per impostazione predefinita. git-rev-list restituisce semplicemente l'ID commit, che è quello che vuoi se stai per alimentare la risposta in uno script o in un altro processo di automazione. git-log restituisce informazioni sui commit selezionati, prima usando git-rev-list per raccogliere gli ID di commit, quindi raccogliendo informazioni su ogni commit. Se hai intenzione di filtrare le informazioni di commit e utilizzare gli ID, allora puoi semplicemente usare git-rev-list. Poiché il registro si basa su rev-list, accetta la maggior parte degli stessi parametri di filtro.
Michael Erickson,

3
git-logè porcellana, git-rev-listè idraulico.
blitzen9872,

27

Se vuoi semplicemente ottenere l'hash dell'ultimo commit per modificare un set specifico di file (e vuoi evitare awk) puoi usare:

git log -n 1 --pretty=format:%h -- <path>

Questo può essere utile per ottenere l'hash di commit da utilizzare successivamente con git describe .

Ad esempio (nel caso sia utile a chiunque) ...

Creo un ID versione corrente considerando l'ultimo commit per modificare qualsiasi file di origine (supponendo che contrassegni le versioni con tag come mycode-1.2.1):

COMMIT=$(git log -n 1 --pretty=format:%h -- *.c *.h)
if VN=$(git describe --always --abbrev=5 --match "mycode-*" $COMMIT 2>/dev/null) &&
case "$VN" in
mycode-*)
    git update-index -q --refresh
    test -z "$(git diff-index --name-only HEAD *.c *.h)" ||
    VN="$VN-mod" ;;
*) VN="mycode-unknown-g$VN" ;;
esac
then
    continue
else
VN="mycode-unknown"
fi

Questo produce ID come:

  • mycode-1.2.1 - quando lo stato corrente dei file di origine corrisponde a una versione taggata
  • mycode-1.2.1-g3k7s2 - quando lo stato corrente dei file di origine corrisponde al commit dopo una versione taggata
  • mycode-1.2.1-g3k7s2-mod - quando lo stato corrente dei file di origine è stato modificato dall'ultimo commit dopo una versione taggata
  • mycode-unknown - quando non è stato ancora creato un tag versione

5
$VNsembra una specie di incubo non morto SVN
ThorSummoner,

10

Non sono sicuro se questo è quello che vuoi, ma se lo fai git log <thefile>per ottenere i commit che hanno modificato quel file. Puoi scegliere quello più in alto. Dovrebbe essere quello che stai cercando.


4
se si utilizza git log -n1 -- <thefile>(o reindirizza l'output a head -1se si desidera sprecare risorse) non è necessario selezionare manualmente la riga superiore (vedere la risposta di Jo Liss )
Tobias Kienzler,

4
Buon punto. Penso che puoi anche saltare -ne usare -1direttamente.
Noufal Ibrahim,

3

Per ottenere solo il riferimento su una riga, prova:

git log -n1 --oneline <path> | awk '{print $1;}'

2

Una volta che hai l'ID SHA del commit che vuoi guardare usando git log FILENAME, dovresti essere in grado di fare git show SHA_ID_HEREper vedere cosa hai fatto per quel particolare commit. Non è nemmeno necessario inserire l'intero ID; i primi 6 caratteri dovrebbero essere sufficienti.


4
questo è un po 'più di quanto richiesto dall'OP, ma, FYI, è possibile combinarlo in una sola riga:git show $(git log -1 --pretty="%H" -- FILENAME)
Tobias Kienzler,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.