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.


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”)]


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.


@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.


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.


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.