Ivar
Ivar

Reputation: 5732

Using Git, how could I search for a string across all branches?

Using Git, how could I search within all files in all local branches for a given string?

GitHub specific: is it possible to perform the above search across all GitHub branches? (There are several remote branches on my remote GitHub repository that ideally I wouldn't have to bring down for this search...)

Upvotes: 345

Views: 170661

Answers (11)

Hoàng Trần
Hoàng Trần

Reputation: 11

Highly customizable terminal script:

git branch -r | grep "/master$" | xargs -I{} git --no-pager grep -E -n "(search string 1|search string 2...)" {} -- "*.js" "*.ts" "*.kt" "*.swift" "*.json"

This command will help you search for specific strings (can be regex) in files of various programming languages (optional) within branches name ended with "/master" (optional) in a Git repository.

git brach -r: List of all branches name

grep "/master$": (optional) filter branch name using regex, only search branches that end with /master

git grep: Main program to search

  • --no-pager: (optional) Display all result at once, not using pager program (scroll to display more).

  • -E: This option enables extended regular expression syntax for the search strings.

  • -n: This option displays line numbers along with the matching lines.

"(search string 1|search string 2...)": you can you regex here

-- "*.js" "*.ts" "*.kt" "*.swift" "*.json": (optional) Search with specific file types, add or remove as you want

Upvotes: 1

Gabriel Staples
Gabriel Staples

Reputation: 53165

Here's a multi-process way that dramatically increases the speed of the search by spawning one git grep process per branch or commit:

# ---------------------------------------------
# 1. Search all local branches
# ---------------------------------------------
# Search only these files and folders in all local branches
time git branch | awk '{print $NF}' \
    | xargs -P "$(nproc)" -I {} git --no-pager grep -n 'my regex search' {} \
    -- "path/to/my_file.c" "path/to/my_folder"

# ---------------------------------------------
# 2. Search all remote branches of all remotes
# ---------------------------------------------
# Search only these files and folders in all remote branches
time git branch -r | awk '{print $NF}' \
    | xargs -P "$(nproc)" -I {} git --no-pager grep -n 'my regex search' {} \
    -- "path/to/my_file.c" "path/to/my_folder"

# ---------------------------------------------
# 3. Search all local **and** remote branches
# ---------------------------------------------
# Search only these files and folders in all local and remote branches
time git branch -a | awk '{print $NF}' \
    | xargs -P "$(nproc)" -I {} git --no-pager grep -n 'my regex search' {} \
    -- "path/to/my_file.c" "path/to/my_folder"

# ---------------------------------------------
# Search **all commits** in the entire repository
# ---------------------------------------------
# Search only these files and folders in all commits (reachable from any branch 
# or tag) in the whole repository
time git rev-list --all \
    | xargs -P "$(nproc)" -I {} git --no-pager grep -n 'my regex search' {} \
    -- "path/to/my_file.c" "path/to/my_folder"

For a full explanation of each command, and a ton more info., see my full answer here: All about searching (via grep or similar) in your git repositories.

Upvotes: 0

Karim Barrane
Karim Barrane

Reputation: 23

For me it is :

git branch | xargs git grep -c "string_to_search"

git branch : looks for branchs in local.

git grep -c : looks for the strings in a given branch.

| xargs : a pipe and xargs to give the branches as inputs to the previous command.

Upvotes: 1

joydeba
joydeba

Reputation: 1255

To ignore case use -i:

git log -i --all --grep='word1 Word2'

Upvotes: 0

Kasthuri Shravankumar
Kasthuri Shravankumar

Reputation: 679

To display the branch name along with the search results, you can use a loop to search each branch separately, like this:

for branch in $(git branch | awk '{print $1}'); do
    echo "Branch: $branch"
    git grep "SEARCH_WORD" $(git rev-parse $branch)
done

This loop uses git branch to list all branches, and awk to extract just the branch names. Then, it uses git rev-parse to get the commit hash of each branch, and git grep to search for the string "deleteTemplateDocument" in that branch. The output will show the branch name and the matching results for each branch.

git log -S <search string> --source --all

https://stackoverflow.com/a/5816177/5368856

Revert a commit, commit id may not be at HEAD

git revert commit_id

Upvotes: 1

Anibal Anto
Anibal Anto

Reputation: 157

Following @peter-mortensen & manojlds's solution, I use git for-each-ref as subcommand to list only branches with name.

git grep "string/regexp" $(git for-each-ref --format='%(refname:short)' refs/heads)

This accomplish a better visualization, showing only named braches and making only one result for each branch.

Upvotes: 7

hIpPy
hIpPy

Reputation: 5125

There are a few issues with the solutions listed here (even accepted).

You do not need to list all the hashes as you'll get duplicates. Also, it takes more time.

It builds on this where you can search a string "test -f /" on multiple branches master and dev as

git grep "test -f /" master dev

which is same as

printf "master\ndev" | xargs git grep "test -f /"

So here goes.

This finds the hashes for the tip of all local branches and searches only in those commits:

git branch -v --no-abbrev | awk -F' *' '{print $3}' | xargs git grep "string/regexp"

If you need to search in remote branches too then add -a:

git branch -a -v --no-abbrev | awk -F' *' '{print $3}' | xargs git grep "string/regexp"

Further:

# Search in local branches
git branch | cut -c3- | xargs git grep "string"

# Search in remote branches
git branch -r | cut -c3- | xargs git grep "string"

# Search in all (local and remote) branches
git branch -a | cut -c3- | cut -d' ' -f 1 | xargs git grep "string"

# Search in branches, and tags
git show-ref | grep -v "refs/stash" | cut -d' ' -f2 | xargs git grep "string"

Upvotes: 48

Zitrax
Zitrax

Reputation: 20334

In many cases git rev-list --all can return a huge number of commits, taking forever to scan. If you, instead of searching through every commit on every branch in your repository history, just want to search all branch tips, you can replace it with git show-ref -s --heads. So in total:

git grep "string" `git show-ref -s --heads`

or:

git show-ref -s --heads | xargs git grep "string"

Tip: You can write output in file to view in an editor:

nano ~/history.txt
git show-ref -s --heads | xargs git grep "search string here" >> ~/history.txt

Upvotes: 150

teastburn
teastburn

Reputation: 3508

If you use @manojlds Git grep command and get an error:

-bash: /usr/bin/git: Argument list too long" 

then you should use xargs:

git rev-list --all | xargs git grep "string/regexp"

Also see How to grep (search through) committed code in the Git history

Upvotes: 220

manojlds
manojlds

Reputation: 301527

You can do this on a Git repository:

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

GitHub advanced search has code search capability:

The code search will look through all of the code publicly hosted on GitHub. You can also filter by:

  • the language: language:
  • the repository name (including the username): repo:
  • the file path: path:

Upvotes: 296

Victor Choy
Victor Choy

Reputation: 4256

You can try this:

git log -Sxxxx  # Search all commits
git log -Sxxxx  --branches[=<pattern>]   # Search branches

Upvotes: 25

Related Questions