Więc znalazłem pytanie, jak wyświetlić historię zmian pliku, ale historia zmian tego konkretnego pliku jest ogromna i tak naprawdę interesują mnie tylko zmiany konkretnej metody. Czy byłoby możliwe wyświetlenie historii zmian tylko dla tej konkretnej metody?
Wiem, że wymagałoby to gita do przeanalizowania kodu i że analiza byłaby inna dla różnych języków, ale deklaracje metod / funkcji wyglądają bardzo podobnie w większości języków, więc pomyślałem, że może ktoś zaimplementował tę funkcję.
Językiem, z którym obecnie pracuję, jest Objective-C, a SCM, którego obecnie używam, to git, ale chciałbym wiedzieć, czy ta funkcja istnieje dla dowolnego SCM / języka.
Odpowiedzi:
Najnowsze wersje
git log
nauczyły się specjalnej postaci-L
parametru:Innymi słowy: jeśli poprosisz o to Gita
git log -L :myfunction:path/to/myfile.c
, teraz z radością wydrukuje historię zmian tej funkcji.źródło
Korzystanie
git gui blame
jest trudne do wykorzystania w skryptach, a jednocześniegit log -G
igit log --pickaxe
każdy może pokazać, kiedy pojawiła się definicja metoda lub zniknął, nie znalazłem żadnego sposobu, aby je wymienić wszystkie zmiany dokonane w ciele swojej metody.Możesz jednak użyć
gitattributes
itextconv
właściwości, aby złożyć w całość rozwiązanie, które właśnie to robi. Chociaż te funkcje były pierwotnie przeznaczone do pomocy w pracy z plikami binarnymi, działają tutaj równie dobrze.Kluczem jest to, aby Git usunął z pliku wszystkie linie z wyjątkiem tych, którymi jesteś zainteresowany, przed wykonaniem jakichkolwiek operacji porównywania. Następnie
git log
,git diff
itp będą widzieć tylko obszar, który Cię interesuje.Oto zarys tego, co robię w innym języku; możesz go dostosować do własnych potrzeb.
Napisz krótki skrypt powłoki (lub inny program), który pobiera jeden argument - nazwę pliku źródłowego - i wyświetla tylko interesującą część tego pliku (lub nic, jeśli żaden z nich nie jest interesujący). Na przykład możesz użyć
sed
w następujący sposób:#!/bin/sh sed -n -e '/^int my_func(/,/^}/ p' "$1"
Zdefiniuj
textconv
filtr Git dla nowego skryptu. (Zobaczgitattributes
stronę podręcznika po więcej szczegółów.) Nazwa filtru i lokalizacja polecenia mogą być dowolne.Powiedz Gitowi, aby użył tego filtru przed obliczeniem różnic dla danego pliku.
$ echo "my_file diff=my_filter" >> .gitattributes
Teraz, jeśli używasz
-G.
(uwaga.
) notować wszystkie rewizje, które wywołują widocznych zmian, gdy filtr jest stosowany, trzeba będzie dokładnie te rewizje, że jesteś zainteresowany. Wszelkie inne opcje, które wykorzystują procedury diff git, takich jak--patch
, będzie również ten ograniczony widok.Voilà!
Jednym z przydatnych ulepszeń, które możesz chcieć zrobić, jest ustawienie przez skrypt filtru nazwy metody jako pierwszego argumentu (i pliku jako drugiego). Pozwala to określić nową interesującą metodę tylko przez wywołanie
git config
, zamiast konieczności edytowania skryptu. Na przykład możesz powiedzieć:$ git config diff.my_filter.textconv "/path/to/my_command other_func"
Oczywiście skrypt filtrujący może robić, co chcesz, przyjmować więcej argumentów lub cokolwiek: poza tym, co tutaj pokazałem, jest dużo elastyczności.
źródło
git log ma opcję „-G”, która może być użyta do znalezienia wszystkich różnic.
Po prostu nadaj mu odpowiednie wyrażenie regularne nazwy funkcji, na której Ci zależy. Na przykład,
$ git log --oneline -G'^int commit_tree' 40d52ff make commit_tree a library function 81b50f3 Move 'builtin-*' into a 'builtin/' subdirectory 7b9c0a6 git-commit-tree: make it usable from other builtins
źródło
--oneline
z-p
Najbliższą rzeczą, jaką możesz zrobić, jest określenie pozycji Twojej funkcji w pliku (np. Powiedzmy, że twoja funkcja
i_am_buggy
znajduje się w wierszach 241-263foo/bar.c
), a następnie uruchom coś, co spowoduje:git log -p -L 200,300:foo/bar.c
Spowoduje to otwarcie mniej (lub równoważnego pagera). Teraz możesz wpisać
/i_am_buggy
(lub odpowiednik pagera) i rozpocząć przechodzenie przez zmiany.To może nawet zadziałać, w zależności od twojego stylu kodu:
git log -p -L /int i_am_buggy\(/,+30:foo/bar.c
Ogranicza to wyszukiwanie od pierwszego trafienia tego wyrażenia regularnego (najlepiej deklaracji funkcji) do kolejnych trzydziestu wierszy. Argumentem końcowym może być również wyrażenie regularne , chociaż wykrycie tego za pomocą wyrażenia regularnego jest bardziej niepewne.
źródło
-L ":int myfunc:foo/bar.c"
i ograniczyć do funkcji o tej nazwie. To fantastyczne - dzięki za wskazówkę! Gdyby tylko wykrywanie funkcji było trochę bardziej niezawodne ...Prawidłowym sposobem jest użycie tego,
git log -L :function:path/to/file
co wyjaśniono w odpowiedzi eckes .Ale dodatkowo, jeśli twoja funkcja jest bardzo długa, możesz chcieć zobaczyć tylko zmiany, które wprowadziły różne zatwierdzenia, a nie całe linie funkcji, w tym niezmodyfikowane, dla każdego zatwierdzenia, które może dotyczyć tylko jednej z tych linii. Jak normalny
diff
.Zwykle
git log
można wyświetlać różnice-p
, ale to nie działa-L
. Musisz więcgrep
git log -L
pokazać tylko zaangażowane linie i nagłówki zatwierdzeń / plików, aby je kontekstualizować. Sztuczka polega na tym, aby dopasować tylko kolorowe linie terminala, dodać--color
przełącznik, z wyrażeniem regularnym. Wreszcie:git log -L :function:path/to/file --color | grep --color=never -E -e "^(^[\[[0-9;]*[a-zA-Z])+" -3
Zauważ, że
^[
powinno to być rzeczywiste, dosłowne^[
. Możesz je wpisać naciskając ^ V ^ [w bash, czyli Ctrl+ V, Ctrl+ [. Odniesienie tutaj .Również ostatni
-3
przełącznik pozwala wydrukować 3 wiersze kontekstu wyjściowego, przed i po każdej dopasowanej linii. Możesz chcieć dostosować go do swoich potrzeb.źródło
git blame pokazuje, kto ostatnio zmienił każdą linię pliku; możesz określić wiersze do zbadania, aby uniknąć pobierania historii wierszy poza twoją funkcję.
źródło
git gui blame
tobą możesz nawigować po starszych wersjach.Pokaż historię funkcji za pomocą,
git log -L :<funcname>:<file>
jak pokazano w odpowiedzi eckes i git docJeśli nic nie pokazuje, zobacz Definiowanie niestandardowego nagłówka porcji, aby dodać coś podobnego
*.java diff=java
do.gitattributes
pliku, aby obsługiwać twój język.Pokaż historię funkcji między zatwierdzeniami z
git log commit1..commit2 -L :functionName:filePath
Pokaż historię przeciążonych funkcji (może być wiele funkcji o tej samej nazwie, ale z różnymi parametrami) za pomocą
git log -L :sum\(double:filepath
źródło