Итак, я нашел вопрос о том, как просмотреть историю изменений файла, но история изменений этого конкретного файла огромна, и меня действительно интересуют только изменения определенного метода. Итак, можно ли увидеть историю изменений только для этого конкретного метода?
Я знаю, что для этого потребуется git для анализа кода и что анализ будет отличаться для разных языков, но объявления методов / функций выглядят очень похоже на большинстве языков, поэтому я подумал, что, возможно, кто-то реализовал эту функцию.
Язык, с которым я сейчас работаю, - Objective-C, а SCM, который я сейчас использую, - git, но мне было бы интересно узнать, существует ли эта функция для какого-либо SCM / языка.
Ответы:
В последних версиях
git log
выучили особую форму-L
параметра:Другими словами: если вы попросите Git
git log -L :myfunction:path/to/myfile.c
, он с радостью распечатает историю изменений этой функции.источник
Использование
git gui blame
трудно использовать в сценариях, и в то время ,git log -G
иgit log --pickaxe
каждый может показать вам , когда определение метода появилось или исчезло, я не нашел способ заставить их перечислить все изменения , внесенные в тело вашего метода.Тем не менее, вы можете использовать
gitattributes
иtextconv
свойство кусочки решения , которое делает именно это. Хотя эти функции изначально предназначались для помощи в работе с двоичными файлами, они работают и здесь.Ключ состоит в том, чтобы Git удалил из файла все строки, кроме тех, которые вам интересны, перед выполнением любых операций сравнения. Тогда
git log
,git diff
и т. Д. Будут видеть только интересующую вас область.Вот краткое описание того, что я делаю на другом языке; вы можете настроить его под свои нужды.
Напишите короткий сценарий оболочки (или другую программу), который принимает один аргумент - имя исходного файла - и выводит только интересную часть этого файла (или ничего, если ни один из них не интересен). Например, вы можете использовать
sed
следующее:#!/bin/sh sed -n -e '/^int my_func(/,/^}/ p' "$1"
Определите
textconv
фильтр Git для вашего нового скрипта. (См. Дополнительную информацию наgitattributes
странице руководства .) Имя фильтра и расположение команды могут быть любыми, как вам угодно.Скажите Git использовать этот фильтр перед вычислением различий для рассматриваемого файла.
$ echo "my_file diff=my_filter" >> .gitattributes
Теперь, если вы используете
-G.
(обратите внимание на.
), чтобы перечислить все коммиты, которые производят видимые изменения при применении вашего фильтра, у вас будут именно те коммиты, которые вас интересуют. Любые другие параметры, использующие процедуры сравнения Git, такие как--patch
, будут также получите это ограниченное представление.Вуаля!
Одно полезное улучшение, которое вы, возможно, захотите сделать, - это сделать так, чтобы ваш скрипт фильтра принимал имя метода в качестве первого аргумента (и файл в качестве второго). Это позволяет вам указать новый интересующий метод, просто вызвав его
git config
, а не редактировать скрипт. Например, вы можете сказать:$ git config diff.my_filter.textconv "/path/to/my_command other_func"
Конечно, сценарий фильтра может делать все, что угодно, принимать больше аргументов или что-то еще: есть большая гибкость, помимо того, что я показал здесь.
источник
В git log есть опция '-G', которую можно использовать для поиска всех различий.
Просто дайте ему правильное регулярное выражение имени функции, которая вам нужна. Например,
$ 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
источник
--oneline
на-p
Самое близкое, что вы можете сделать, - это определить положение вашей функции в файле (например, скажем, ваша функция
i_am_buggy
находится в строках 241-263foo/bar.c
), а затем запустить что-нибудь, чтобы добиться эффекта:git log -p -L 200,300:foo/bar.c
Это откроет меньше (или эквивалентный пейджер). Теперь вы можете ввести
/i_am_buggy
(или эквивалент на пейджере) и приступить к внесению изменений.Это может даже сработать, в зависимости от вашего стиля кода:
git log -p -L /int i_am_buggy\(/,+30:foo/bar.c
Это ограничивает поиск с первого попадания этого регулярного выражения (в идеале, объявления вашей функции) до тридцати строк после этого. Конечный аргумент также может быть регулярным выражением, хотя обнаружение этого с помощью регулярного выражения является более сомнительным предложением.
источник
-L ":int myfunc:foo/bar.c"
и ограничить функцию с этим именем. Это фантастика - спасибо за указатель! Если бы только обнаружение функций было немного более надежным ...Правильный способ - использовать,
git log -L :function:path/to/file
как описано в ответе eckes .Но кроме того, если ваша функция очень длинная, вы можете захотеть видеть только изменения, внесенные различными фиксациями, а не целые функциональные строки, включая неизмененные, для каждой фиксации, которая может касаться только одной из этих строк. Вроде нормальный
diff
.Обычно
git log
можно просматривать различия-p
, но это не работает-L
. Поэтому вам нужноgrep
git log -L
отображать только задействованные строки и заголовок коммитов / файлов, чтобы контекстуализировать их. Хитрость здесь в том, чтобы сопоставить только цветные линии терминала, добавив--color
переключатель, с регулярным выражением. В заключение:git log -L :function:path/to/file --color | grep --color=never -E -e "^(^[\[[0-9;]*[a-zA-Z])+" -3
Обратите внимание, что это
^[
должно быть фактическим, буквальным^[
. Вы можете ввести их, нажав ^ V ^ [в bash, то есть Ctrl+ V, Ctrl+ [. Ссылка здесь .Также последний
-3
переключатель позволяет печатать 3 строки контекста вывода до и после каждой совпадающей строки. Вы можете настроить его под свои нужды.источник
git blame показывает, кто последним изменил каждую строку файла; вы можете указать строки для проверки, чтобы избежать получения истории строк за пределами вашей функции.
источник
git gui blame
вы можете перемещаться по более ранним версиям.Показать историю функций,
git log -L :<funcname>:<file>
как показано в ответе eckes и git docЕсли ничего не отображается, обратитесь к разделу «Определение настраиваемого заголовка фрагмента», чтобы добавить
*.java diff=java
в.gitattributes
файл что-то подобное для поддержки вашего языка.Показать историю функций между коммитами с помощью
git log commit1..commit2 -L :functionName:filePath
Показать историю перегруженных функций (может быть много функций с тем же именем, но с разными параметрами) с
git log -L :sum\(double:filepath
источник