Git: mostra tutte le varie modifiche a una singola riga in un file specificato nell'intera cronologia di git


112

Mi sono guardato intorno e non sono sicuro che sia possibile, ma ecco qui:

Ho un file (javascript) (ad esempio /lib/client.js) in cui ho un identificatore univoco assegnato a una variabile, in questo modo: var identifier = "SOME_IDENTIFIER";

Puoi pensare all'identificatore come a un numero di versione: periodicamente, cambieremo questa variabile con un nuovo identificatore.

Quello che vorrei fare è trovare tutti gli identificatori univoci che abbiamo mai usato. Come posso farlo con git?

Immagino che ci potrebbe essere un modo per cercare nella cronologia di git e stampare la corrispondenza di riga "var identifier =". Potrei eliminare questa lista manualmente.

Comunque, apprezzerei qualsiasi intuizione qui. Grazie.


Risposte:


106

A partire da git 1.8.4 , c'è un modo più diretto per rispondere alla tua domanda.

Supponendo che quella linea 110sia la linea che dice var identifier = "SOME_IDENTIFIER";, allora fai questo:

git log -L110,110:/lib/client.js

Questo restituirà ogni commit che ha toccato quella riga di codice.

[ Documentazione Git (vedere il parametro della riga di comando "-L")]


49

Vedere la pagina man per git-loge gitdiffcore. Credo che questo comando lo farebbe, ma potrebbe non essere del tutto corretto:

git log -G "var identifier =" file.js

EDIT: Ecco un inizio approssimativo per uno script bash per mostrare le linee effettive. Questo potrebbe essere più quello che stai cercando.

for c in $(git log -G "something" --format=%H -- file.js); do
    git --no-pager grep -e "something" $c -- file.js
done

Viene utilizzato git log -Gper trovare i commit interessanti, utilizzando --format=%Hper produrre un elenco di hash dei commit. Quindi itera su ogni commit interessante, chiedendo git grepdi mostrare le linee di quel commit e file che contengono la regex, preceduti dall'hash del commit.


EDIT: modificato per utilizzare -Ginvece di -Scome suggerito nei commenti.


@ Rob - grazie per questo - piccola modifica al tuo script però - mettendo solo il nome del file mostra solo i commit che interessano solo quel file - se un commit fa riferimento ad altri file non è elencato
Adrian Cornish

@AdrianCornish - Sono contento che sia stato utile. Penso che l'OP volesse solo guardare un file, ma hai ragione sul fatto che la rimozione del nome del file è probabilmente uno script più generalmente utile.
rapina il

Ho una situazione più difficile. Il file in questione è stato spostato da paht_a / file a path_b / file. Ora quando lo faccio in path_b mostra solo le modifiche fino a quando il file si sposta da path_a a path_b. Se lo faccio in path_a mi dice fatal: argomento ambiguo 'file': revisione sconosciuta o percorso non nell'albero di lavoro.
Andy Song

@AndySong - Se la stringa che stai cercando è abbastanza unica, forse puoi semplicemente omettere il nome del file e ottenere comunque ciò che stai cercando.
rapina il

Era più conveniente per me: inserisci una riga vuota dopo ogni commit, enumera le righe:sfile=path/to/some_file; sfind='string_to_find'; for c in $(git log -G $sfind --format=%H -- $sfile); do git --no-pager grep -e $sfind -n $c -- $sfile; echo; done
John_West,

14

Puoi farlo anche con gitk:

gitk file.js

Nel menu a discesa "commit", scegli "aggiunta / rimozione stringa:" e nella casella di testo accanto, inserisci "var identifier =" e qualsiasi commit che aggiunge o rimuove righe che contengono quella stringa verrà evidenziato.


Ciò ha aiutato a individuare il commit in cui è stata aggiunta la riga contenente "var identifier =", ma non mostra i commit successivi che hanno modificato questa riga.
findchris

2
Hai provato git blame file.jso git gui blame file.js?
Ethan Brown

1
So cosa fa il git blame; Sto cercando una cronologia completa delle revisioni, non una singola diff.
findchris

1
git gui blame file.jslo farà ... ti mostrerà tutte le revisioni di un file e chi lo ha modificato; puoi semplicemente fare clic all'indietro nella cronologia.
Ethan Brown

Ho finito per passare visivamente con gitk. Immagino che ci sia un'elegante tecnica git per farlo, ma gitk era abbastanza buono. Grazie.
findchris

9

Se adatti la risposta di @ rob solo un po ', git logfondamentalmente lo farà per te, se tutto ciò di cui hai bisogno è un confronto visivo:

git log -U0 -S "var identifier =" path/to/file

-U0significa output in modalità patch ( -p) e mostra zero linee di contesto attorno alla patch.

Puoi anche farlo attraverso i rami:

git log -U0 -S "var identifier =" branchname1 branchname2 -- path/to/file

Potrebbe esserci un modo per sopprimere l'intestazione del diff, ma non ne conosco uno.


Ha funzionato per me! Grazie.
Roberto Bonini

3

In magit , puoi farlo con

l, =L

Ti chiederà quindi il file e le righe di inizio e fine.

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.