Git grep main repo and special submodules

I have two submodules in the main repository that are closely related to the code in the main repository. So much so that when running git grep, I would like the main repo to be decommissioned along with these two specific submodules. I can’t make the full git foreach submodule "git grep ... || true" because I have other submodules that are very large, and grepping through these submodules can take up to 15-20 seconds for each of them.

So, I need a more specific solution than git subodule foreach, which allows me to specify specific grep submodules, although along with grepping my main repo.

My two submodules foo and submodules/bar

Here is my current solution. This allows me to say git gpx -i something.*interesting , etc. I'm still new to git alias creation, so I hope this solution can be improved.

 [alias] inr = "!f() { cd $1 && $2 ;}; f" gprs = "!f() { for r in $1; do git inr $r \"git grep $2\" | perl -pe \"s|^|$r/|\"; done ;}; f" gpx = "!f() { git grep $*; git gprs 'foo submodules/bar' \"$*\" ;}; f" 

EDIT: One of the problems I discovered is that I am losing the quotes around the regex, so I cannot name something like this: git gpx -i "foo bar" because it translates to this: git grep -i foo bar . I can't think of a clean way to avoid this.

+4
source share
1 answer

REDO . I made a hacked bash script with this script to do the paging (mentioned below), but noticed that your example is already a search path prefix. I changed your alias a bit and now find that this works for me:

 [alias] gpx = "!f() { list=$1; shift; for r in . $list; do ( cd $r; git grep $@ | perl -pe \"s|^|$r/|\"; ); done ;}; f" 

If you use a subshell, you can reset the functionality of "inr" (cd $ 1; cmd; ...) "(since it isolates chdir), and if you add". "then he will also look for a supermodule. I tested it with something like

 git --no-pager gpx 'foo submodules/bar' --color=always -nIE '\w+\(\w*\)' | less -R 

It seems to work well with escaping (was going to use git-rev-parse --sq-quote , but it looks like git is handling this for you already). This seems more elegant than the script elements listed below, and perhaps I could use your alias style with a function prefix and replace / simplify many of these functions. That said, thanks for showing it!

I tried to make another alias that gpx uses for the pager material, but it turned out to be a bit hairy with escaping, so I just made another alias:

 [alias] gpxp = "!f() { list=$1; shift; for r in . $list; do ( cd $r; git --no-pager grep --color=always $@ | perl -pe \"s|^|$r/|\"; ); done | less -R ;}; f" 

Then he becomes

 git gpxp 'foo submodules/bar' -nIE '\w+\(\w*\)' 

NOTE. If you get errors, they will appear in the grep text results.

ORIGINAL

I ran into similar problems with escaping and using git aliases.

I wrote a small extension to git-submodule that allows you to perform limited iteration. The help for this function is in git-submodule-ext foreach [-c | --constrain] git-submodule-ext foreach [-c | --constrain] ( help , implementation ). Installation instructions are here: README

If you want to limit the iteration to foo and something/bar , in your supermodule you can do

 git config scm.focusGroup 'foo something/bar' 

Then to execute your greppage

 git --no-pager submodule-ext foreach -t -r -c -k git grep 'expression' 

Or, if you install using aliases,

 git --no-pager tsfer -c -k git grep 'expression' 

The git --no-pager parameter is designed to prevent pulling up each submodule of $GIT_PAGER after each search. I added the --keep-going option to the script, so if grep returned nothing (the result is a non-zero state), it will not stop the iteration. Another solution is to make an example in the submodule documents using git tsfer -c -k 'git grep "expression" || :' git tsfer -c -k 'git grep "expression" || :' which work equivalently.

If your expression is complex, something like searching for function calls '\w+\(\w*\)' , you will need to enclose the entire expression in double quotes:

 git --no-pager tsferp -c -k "git grep -E '\w+\(\w*\)'" 

If escaping is a huge problem and you use bash, you export the function to use on iteration (script I extension using bash , not git standard /bin/sh )

 greppage() { git grep -E 'some(really)?complex.*\(expression\)' } export -f greppage git --no-pager tsfer -c -k greppage 

Hope this helps.

NOTE. The current drawback of this is that it can be difficult to determine which submodule matches, where the match is. A fix can be made somehow by adding the $name submodule, but I looked at git grep and couldn't find anything like it. I worked a little with the team and came up with this, well, "compact" command:

 git --no-pager sube -q foreach -t -r -c -k "echo [ \$name ]'\n'; git grep --color=always -E '\w+\(\w*\)'; echo '\n\n'" | less -R 

This makes the foreach silence quiet (suppresses "Enter" output) and adds some curly braces and newlines to make it easier to see divisions between submodules. Lemme see if I can make a function / alias for this to make it easier.

EDIT : a script is hacked here, which is not so elegant. I just made it a bash function to simplify things

 git-greps() { git --no-pager sube -q foreach -t -r -c -k "git grep --color=always $(git rev-parse --sq-quote " $@ ") | perl -pe \"s|^|\$name/|\"" | less -R; } 

Example

 git-greps -nIE '\w+\(\w*\)' 
+2
source

Source: https://habr.com/ru/post/1485739/


All Articles