Чи можливо здійснити "греп-пошук" у всіх галузях проекту Git?


138

Чи можливо запуститись git grepу всі відділення проекту Git control? Або є інша команда для запуску?



Відповіді:


189

Питання " Як зібрати (шукати) вчинений код в історії git? ", Рекомендує:

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

Він здійснює пошук усіх комітетів, які повинні включати всі гілки.

Іншою формою буде:

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

Ви можете знайти ще більше прикладу в цій статті :

Я спробував вищезазначене на одному проекті досить великий, щоб git скаржився на розмір аргументу, тому якщо ви зіткнулися з цією проблемою, зробіть щось на кшталт:

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

(див. альтернативу в останньому розділі цієї відповіді нижче)

Не забувайте ці налаштування, якщо ви хочете їх:

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

Цей псевдонім також може допомогти:

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

Примітка: chernjie припустив, що git rev-list --allце надмір .

Більш вдосконаленою командою може бути:

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

Що дозволить шукати лише гілки (включаючи віддалені гілки)

Ви навіть можете створити псевдонім bash / zsh для цього:

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

Оновлення серпня 2016 року: RM рекомендує в коментарях

Я отримав " fatal: bad flag '->' used after filename" при спробі git branchверсії. Помилка була пов'язана з HEADпозначенням псевдоніму.

Я вирішив її, додавши sed '/->/d'в трубі, між trі в xargsкомандах.

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

Це є:

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

Це не дуже гарна ідея трубопроводу git branchв tr або sed; git branch- порцелянова команда, призначена для споживання людиною. Див. Stackoverflow.com/a/3847586/2562319 про кращі варіанти.
jbyler

@jbyler Добре. Як не дивно, я поставив відповідь на порцеляні задовго до цієї відповіді: stackoverflow.com/a/6978402/6309 . І я використовую його, наприклад, в stackoverflow.com/a/19206916/6309 .
VonC

Так, приємно. Переглядаючи інші відповіді, я думаю, що відповідь @errordeveloper є найчистішою: stackoverflow.com/a/21284342/2562319 : "git grep <regexp> $ (git for-every-ref --format = '% (refname) 'refs /) "
jbyler

1
Чи є спосіб показати назву гілки, яка відповідала пошуку?
франків

63

git log може бути більш ефективним способом пошуку тексту в усіх галузях, особливо якщо збігів багато, і ви хочете спочатку побачити новіші (відповідні) зміни.

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

Цей список команд журналу виконує комісії, які додають або видаляють задану пошукову рядок / регулярний вираз, (як правило, спочатку останній. Цей -pпараметр призводить до того, що відповідна різниця відображатиметься там, де шаблон був доданий чи видалений, тож ви можете бачити його в контексті.

Знайшовши відповідний документ, який додає шуканий текст (наприклад, 8beeff00d), знайдіть гілки, які містять коміти:

git branch -a --contains 8beeff00d

22

Я вважаю це найкориснішим:

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

Вам потрібно буде відрегулювати останні аргументи залежно від того, чи хочете ви дивитись лише на віддалені та локальні гілки, тобто:

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

Створений мною псевдонім виглядає приблизно так:

grep-refs = !sh -c 'git grep "$0" "$@" "$(git for-each-ref --format=\"%(refname)\"" refs/)'

1
Цікавий псевдонім. +1. Точніше, ніж у моїй відповіді.
VonC

Як змусити псевдонім працювати для пошуку фрази? Коли я передаю "foo bar" як параметр, я отримую: fatal: неоднозначний аргумент 'bar': невідома редакція або шлях не в робочому дереві. Використовуйте '-', щоб відокремити шляхи від модифікацій
jutky

Спробуйте вийти з місця: "foo \ bar"
Гаррі Гомес

Це явно буде прийнятою відповіддю; шукати більше, ніж, скажімо, 100 останніх з них). Для цього я оновив git for-each-refс --sort=-committerdate --count=100! Дякую за оригінальну ідею!
Vser

6

Це можна зробити двома поширеними способами: псевдоніми Bash або Git

Ось три команди:

  1. git grep-branch - Пошук у всіх галузях місцевих та віддалених
  2. git grep-branch-local - Пошук лише в місцевих відділеннях
  3. git grep-branch-remote - Тільки віддалені гілки

Використання те саме, що git grep

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

GREP з використанням: Git псевдонімів

Файл ~ / .gitconfig

Команди слід додавати до ~/.gitconfigфайлу вручну , оскільки git config --global aliasоцінюйте складний код, який ви додаєте, і змішуєте його.


[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 "

Примітка. Коли ви додаєте псевдоніми, і вони не запускаються - перевірте зворотні риски, \вони можуть вимагати додаткового скасування \\порівняно з командами bash .

  • git branch -a - Відобразити всі гілки;
  • sed -e 's/[ \\*]*//'- Обрізати пробіли (від branch -a) і * (назва активної гілки є);
  • grep -v -e '\\->'- Ігноруйте складні назви типу remotes/origin/HEAD -> origin/master;
  • grep '^remotes' - Отримати всі віддалені відділення;
  • grep -v -e '^remotes'- Отримати гілки, крім віддалених гілок;

Приклад git grep-branch-local -n getTastyCookies

-n Приставте номер рядка до відповідних рядків.

[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)

Поточна структура:

: - Роздільник

  1. Відділення: dev
  2. Номер рядка: 53
  3. Шлях файлу: modules/factory/getters.php
  4. Відповідна лінія: function getTastyCookies($user)

GREP з використанням: BASH

Як слід знати: команди Bash повинні зберігатися в .shсценаріях або виконуватись в оболонці.

Тільки місцеві відділення

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

Лише віддалені гілки

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

Місцеві та віддалені відділення

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

Звучить добре, але я отримав цю помилку з git grep-branch "find my text":fatal: ambiguous argument 'client': both revision and filename
nealmcb

Навіщо завжди використовувати -a, що показує всі гілки? Я б запропонував використовувати параметри git branchкоманди, щоб розділити брекети. Якщо дивитися на місцеві гілки, є лише одна *, тому не потрібно уникати її для sed. Отже: лише git branch | sed -e 's/*/ /' | xargs git grep "TEXT"для місцевих гілок, лише git branch -r | grep -v -- "->" | xargs git grep "TEXT"для віддалених гілок, а git branch -a | grep -v -- "->" | xargs git grep "TEXT"для всіх гілок
яланб


4

Якщо ви надаєте будь-яку фіксацію хеш-значення SHA-1, git grepви маєте його шукати в них замість робочої копії.

Для пошуку всіх гілок можна отримати всі дерева git rev-list --all. Покладіть все це

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

... і мати терпіння

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.