I set *.py diff=python
in .git/info/attributes
. So Git knows where function boundaries. git diff -W can even make sure the whole function is shown.
But is there a way to limit the output of a git diff to just a particular function (or more than one)?
(Failing that, I guess it's awk...)
EDIT This would also be useful for git log
and git rev-list
: don't show me every commit that modifies views.py, show me commits that modify a certain function in it. (Yes, in an ideal world, views.py wouldn't be a 2000 line behemoth frequently modified by 8 different developers...)
Ok, thanks to Birei, we have a solution.
Use the awk script in that answer, combined with a bit of bash:
~/scripts/grit:
#!/bin/bash
cmd=$1
shift 1
if [ "$cmd" = "" ]; then
git
# other commands not relevant to this question go here
elif [ $cmd = "funcdiff" ]; then
git show "$1:$3" | awk -f ~/scripts/getfunc.awk -v f=$4 > /tmp/.tmp1
git show "$2:$3" | awk -f ~/scripts/getfunc.awk -v f=$4 > /tmp/.tmp2
git diff -W --no-index /tmp/.tmp1 /tmp/.tmp2
else
git $cmd $@
fi
Example usage: grit funcdiff 009e75 8b7a14 ./staging.py write_uploaded
This could also be added as a git alias in ~/.gitconfig
I didn't find any other option (other than the --function-context
or its -W
short option, already mentioned) able to restrict a diff output to a single function.
And even that -W
option isn't always enough, knowing that a 'function' can vary greatly from language to language, as illustrated in this blog post:
I’ve found this option rather unreliable, at least within a large PHP class.
My tests found--function-context
often results in displaying almost all of the original file, and git appears ignorant of PHP’s function boundaries.
The number of context lines before and after a change seem random, and the diff doesn’t necessarily always show all lines of the function, either.The original patch message that introduced this change sheds some light:
This implementation has the same shortcoming as the one in grep, namely that there is no way to explicitly find the end of a function.
That means that a few lines of extra context are shown, right up to the next recognized function begins.So it appears detecting a function’s boundaries is difficult for git.
It seems in this instance, git never detects a function boundary and gives us the context of the entire file.
As the OP Steve Bennett points out, a potential solution would be to define a git alias which would extract the function in the revision before and after modification, in order to diff on those 2 'temp' files.
Example in "Creating Git Aliases" and "Bash script to select a single Python function from a file".
This is an ad-hoc solution which will be able to parse the specific type of source the OP happens to work with in his repo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With