Git: Pokaż wszystkie różne zmiany w jednej linii w określonym pliku w całej historii git

112

Rozejrzałem się i nie jestem pewien, czy jest to możliwe, ale oto:

Mam plik (javascript) (powiedzmy /lib/client.js), w którym mam przypisany do zmiennej unikalny identyfikator, na przykład: var identifier = "SOME_IDENTIFIER";

Możesz myśleć o identyfikatorze jak o numerze wersji: okresowo będziemy zmieniać tę zmienną na nowy identyfikator.

Chciałbym znaleźć wszystkie unikalne identyfikatory, których kiedykolwiek używaliśmy. Jak mogę to zrobić z git?

Wyobrażam sobie, że może istnieć sposób na przeszukanie historii git i wydrukowanie dopasowania linii "var identifier =". Mógłbym ręcznie usunąć duplikaty tej listy.

W każdym razie byłbym wdzięczny za wszelkie wglądy. Dzięki.

findchris
źródło

Odpowiedzi:

106

Od wersji git 1.8.4 istnieje bardziej bezpośredni sposób odpowiedzi na twoje pytanie.

Zakładając, że ta linia 110jest linią mówiącą var identifier = "SOME_IDENTIFIER";, zrób to:

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

To zwróci każde zatwierdzenie, które dotknęło tej linii kodu.

[ Dokumentacja Git (zobacz paramenter wiersza poleceń „-L”)]

Alexander Bird
źródło
49

Zobacz stronę podręcznika dla git-logi gitdiffcore. Wierzę, że to polecenie by to zrobiło, ale może nie być całkiem poprawne:

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

EDYCJA: Oto przybliżony początek skryptu bash, który pokazuje rzeczywiste linie. To może być bardziej tym, czego szukasz.

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

Używa git log -Gdo znajdowania interesujących zatwierdzeń, używając --format=%Hdo tworzenia listy skrótów zatwierdzeń. Następnie iteruje po każdym interesującym zatwierdzeniu, prosząc git grepo pokazanie wierszy z tego zatwierdzenia i pliku, które zawierają wyrażenie regularne, poprzedzone hashem zatwierdzenia.


EDYCJA: Zmieniono, aby używać -Gzamiast -Ssugerowanych w komentarzach.

obrabować
źródło
@Rob - dzięki za to - jednak niewielka edycja skryptu - umieszczenie tylko nazwy pliku pokazuje tylko zatwierdzenia, które mają wpływ na ten plik - jeśli zatwierdzenie odwołuje się do innych plików, nie ma go na liście
Adrian Cornish
@AdrianCornish - Cieszę się, że to było pomocne. Myślę, że OP chciał tylko spojrzeć na jeden plik, ale masz całkowitą rację, że usunięcie nazwy pliku jest prawdopodobnie bardziej użytecznym skryptem.
okraść
Mam trudniejszą sytuację. Plik, o którym mowa, został przeniesiony z paht_a / file do path_b / file. Teraz, gdy robię to w path_b, pokazuje tylko zmiany do momentu, gdy plik zostanie przeniesiony ze path_a do path_b. Jeśli zrobię to w path_a, powie mi, że jest to fatalne: niejednoznaczny argument „plik”: nieznana wersja lub ścieżka nie znajduje się w drzewie roboczym.
Andy Song
@AndySong - Jeśli szukany ciąg jest wystarczająco unikalny, być może możesz po prostu zostawić nazwę pliku i nadal uzyskać to, czego szukasz.
okradł
Było dla mnie wygodniejsze - umieść pustą linię po każdym zatwierdzeniu, 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
wylicz
14

Możesz to również zrobić za pomocą gitk:

gitk file.js

W menu „zatwierdzenie” wybierz „dodawanie / usuwanie ciągu:” iw polu tekstowym obok niego wpisz „identyfikator zmiennej =”, a wszelkie zatwierdzenia, które dodają lub usuwają wiersze zawierające ten ciąg, zostaną podświetlone.

Ethan Brown
źródło
Pomogło to wskazać zatwierdzenie, w którym dodano linię zawierającą „var identifier =”, ale nie pokazuje kolejnych zatwierdzeń, które modyfikowały tę linię.
findchris
2
Czy próbowałeś git blame file.js lub git gui blame file.js?
Ethan Brown
1
Wiem, co robi drań; Szukam pełnej historii zmian, a nie jednej różnicy.
findchris
1
git gui blame file.jszrobi to ... pokaże Ci wszystkie wersje pliku i kto go zmienił; możesz po prostu przewijać historię wstecz.
Ethan Brown,
Skończyło się na wizualnym przejściu przez gitk. Wyobrażam sobie, że jest do tego jakaś elegancka technika git, ale gitk był wystarczająco dobry. Dzięki.
findchris
9

Jeśli trochę dostosujesz odpowiedź @ rob, w git logzasadzie zrobię to za Ciebie, jeśli potrzebujesz tylko wizualnego porównania:

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

-U0oznacza wyjście w trybie patch ( -p) i pokazuje zero linii kontekstu wokół łatki.

Możesz to zrobić nawet w różnych oddziałach:

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

Może istnieć sposób na zablokowanie nagłówka diff, ale nie znam go.

Andrzej
źródło
Pracował dla mnie! Dzięki.
Roberto Bonini
3

W magii możesz to zrobić za pomocą

l, =L

Następnie zapyta cię o plik oraz początek i koniec linii.

slumos
źródło