Is it possible to perform a 'grep search' in all the branches of a Git project?

后端 未结 6 2054
深忆病人
深忆病人 2020-12-02 04:54

Is it possible to run git grep inside all the branches of a Git control sourced project? Or is there another command to run?

相关标签:
6条回答
  • 2020-12-02 05:29

    git log can be a more effective way of searching for text across all branches, especially if there are many matches, and you want to see more recent (relevant) changes first.

    git log -p --all -S 'search string'
    git log -p --all -G 'match regular expression'
    

    These log commands list commits that add or remove the given search string/regex, (generally) more recent first. The -p option causes the relevant diff to be shown where the pattern was added or removed, so you can see it in context.

    Having found a relevant commit that adds the text you were looking for (eg. 8beeff00d), find the branches that contain the commit:

    git branch -a --contains 8beeff00d
    
    0 讨论(0)
  • 2020-12-02 05:33

    It's possible to do it in two common ways: Bash or Git aliases

    Here are three commands:

    1. git grep-branch - Search in all branches local & remote
    2. git grep-branch-local - Search in local branches only
    3. git grep-branch-remote - Remote branches only

    Usage is the same as git grep

    git grep-branch "find my text"
    git grep-branch --some-grep-options "find my text"
    

    GREP using: Git aliases

    File ~/.gitconfig

    Commands should be added manually to ~/.gitconfig file, because git config --global alias evaluate complex code you add and mess it up.

    
    [alias]
        grep-branch        = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' | xargs git grep $@; };f "
        grep-branch-remote = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' | grep '^remotes' | xargs git grep $@; };f"
        grep-branch-local  = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' -e '^remotes' | xargs git grep $@;  };f "
    

    Note: When you add aliases and they fail to run - check backslashes \ they may require additional escape \\ in compare to bash commands.

    • git branch -a - Display all branches;
    • sed -e 's/[ \\*]*//' - Trim spaces (from branch -a) and * (active branch name have it);
    • grep -v -e '\\->' - Ignore complex names likeremotes/origin/HEAD -> origin/master;
    • grep '^remotes' - Get all remote branches;
    • grep -v -e '^remotes' - Get branches except remote branches;

    Example git grep-branch-local -n getTastyCookies

    -n Prefix the line number to matching lines.

    [user@pc project]$ git grep-branch-local -n getTastyCookies
    
    dev:53:modules/factory/getters.php:function getTastyCookies($user);
    master:50:modules/factory/getters.php:function getTastyCookies($user)
    

    The current structure is:

    : - Separator

    1. Branch: dev
    2. Line number: 53
    3. File path: modules/factory/getters.php
    4. Matching line: function getTastyCookies($user)

    GREP using: BASH

    As you should know: Bash commands should be stored in .sh scripts or run in a shell.

    Local branches only

    git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' -e '^remotes' | xargs git grep "TEXT"
    

    Remote branches only

    git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' | grep '^remotes' | xargs git grep "TEXT"
    

    Local & remote branches

    git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' | xargs git grep "TEXT"
    
    0 讨论(0)
  • 2020-12-02 05:39

    The question "How to grep (search) committed code in the git history?" recommends:

     git grep <regexp> $(git rev-list --all)
    

    That searches through all the commits, which should include all the branches.

    Another form would be:

    git rev-list --all | (
        while read revision; do
            git grep -F 'yourWord' $revision
        done
    )
    

    You can find even more example in this article:

    I tried the above on one project large enough that git complained about the argument size, so if you run into this problem, do something like:

    git rev-list --all | (while read rev; do git grep -e <regexp> $rev; done)
    

    (see an alternative in the last section of this answer, below)

    Don't forget those settings, if you want them:

    # Allow Extended Regular Expressions
    git config --global grep.extendRegexp true
    # Always Include Line Numbers
    git config --global grep.lineNumber true
    

    This alias can help too:

    git config --global alias.g "grep --break --heading --line-number"
    

    Note: chernjie suggested that git rev-list --all is an overkill.

    A more refined command can be:

    git branch -a | tr -d \* | xargs git grep <regexp>
    

    Which will allow you to search only branches (including remote branches)

    You can even create a bash/zsh alias for it:

    alias grep_all="git branch -a | tr -d \* | xargs git grep"
    grep_all <regexp>
    

    Update August 2016: R.M. recommends in the comments

    I got a "fatal: bad flag '->' used after filename" when trying the git branch version. The error was associated with a HEAD aliasing notation.

    I solved it by adding a sed '/->/d' in the pipe, between the tr and the xargs commands.

     git branch -a | tr -d \* | sed '/->/d' | xargs git grep <regexp>
    

    That is:

    alias grep_all="git branch -a | tr -d \* | sed '/->/d' | xargs git grep"
    grep_all <regexp>
    
    0 讨论(0)
  • 2020-12-02 05:39

    Here's how I do it:

    git for-each-ref --format='%(*refname)' | xargs git grep SEARCHTERM
    
    0 讨论(0)
  • 2020-12-02 05:40

    I found this most useful:

    git grep -i foo `git for-each-ref --format='%(refname)' refs/`
    

    You'd need to adjust the last arguments depending on whether you want to only look at remote vs. local branches, i.e.:

    • git grep -i foo $(git for-each-ref --format='%(refname)' refs/remotes)
    • git grep -i foo $(git for-each-ref --format='%(refname)' refs/heads)

    The alias I created looks like this:

    grep-refs = !sh -c 'git grep "$0" "$@" "$(git for-each-ref --format=\"%(refname)\"" refs/)'
    
    0 讨论(0)
  • 2020-12-02 05:44

    If you give any commit a SHA-1 hash value to git grep you have it search in them, instead of the working copy.

    To search all branches, you can get all the trees with git rev-list --all. Put it all with

    git grep "regexp" $(git rev-list --all)
    

    ... and have patience

    0 讨论(0)
提交回复
热议问题