Reputation: 33385
A change in my working copy of a Git repository caused an error which mentions a variable foo
and I want to find which files and lines contain a changed line in my working copy which mentions foo
.
If I do git diff path/file
it launches a visual editor, so I can't grep in the shell. Even if that worked, it would omit the name of the file in question.
This answer seems closer to what I want, but it is overstuffed with irrelevant examples using terminology I don't really understand.
I don't want to search through any history (i.e. commits), I want to search for foo
within the changes that I currently made since the last checkout/commit.
"Hey, Git, what did I change which contains foo
and hasn't been committed yet? File names and line numbers, please."
How do I do this?
(I'd also appreciate being able to ask the same question of a visual diff editor, if you happen to know one on Linux which does this.)
Upvotes: 2
Views: 63
Reputation: 32444
The following script will do almost what you want:
Usage
GIT_EXTERNAL_DIFF="mygitdiff --grep foo" git diff
This will output those lines in you changes that contain foo
(including lines where foo
disappeared because of your changes).
Each output line starts with the following prefix:
filename: oldlinenum: newlinenum|
The script can also be used without the --grep
option, in which case it simply formats the full diff (i.e. providing full context) as described above.
Note that if you have both staged and unstaged changes, to achieve the desired effect you must run git diff
against HEAD
:
GIT_EXTERNAL_DIFF="mygitdiff --grep foo" git diff HEAD
mygitdiff
#!/bin/bash
my_diff()
{
diff --old-line-format="$1"':%6dn: |-%L' \
--new-line-format="$1"': :%6dn|+%L' \
--unchanged-line-format="$1"':%6dn:%6dn| %L' \
$2 $3
}
if [[ $1 == '--grep' ]]
then
pattern="$2"
shift 2
my_diff "$1" "$2" "$5"|grep --color=never '^[^|]\+|[-+].\+'"$pattern"'.*'
else
my_diff "$1" "$2" "$5"
fi
exit 0
CREDITS Scott Weldon helped to test this script and found a bug in its initial version. Thank you Scott!
Upvotes: 1
Reputation: 10217
A normal git diff
command will give you the file names and line numbers, so if we can limit it properly that should do the job. You could do:
git diff -G foo
But this will not work if you have staged changes. (You can use the --cached
argument to only check staged changes, but that won't include unstaged changes.)
This should work better:
git diff-index -G foo -p -U0 HEAD
Both of these commands will include all changes in matching files, not just changes containing foo
, but otherwise should do what you are asking.
Note also that both of these commands will include the patch output, so if you have a large set of changes it will require some extra scrolling. In addition, to get exact line numbers, you'll need to do some simple math if there are other changes in the same hunk. E.g. if you see this:
@@ -101,6 +103,8 @@
+ int bar = 1;
+ int baz = 2;
+ int foo = 3;
That means the top of the hunk was line 101, and is now line 103, and thus the foo
line is now line 105.
Upvotes: 2