Як шукати всі Git та Mercurial комісії у сховищі для певного рядка?


287

У мене є сховище Git з кількома гілками і звисаючими комітами. Я хотів би шукати всі такі коміти в сховищі для певного рядка.

Я знаю, як отримати журнал усіх комісій в історії, але вони не включають гілки чи звисаючі краплі, лише історію HEAD. Я хочу отримати їх усіх, щоб знайти конкретну комісію, яка потрапила в непридатність.

Я також хотів би знати, як це зробити в Mercurial, оскільки я розглядаю питання про перемикач.


Відповіді:


331

Ви можете бачити звисання комітетів git log -g.

-g, --walk-reflogs
 Instead of walking the commit ancestry chain, walk reflog entries from
 the most recent one to older ones. 

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

git log -g --grep=search_for_this

Крім того, якщо ви хочете шукати зміни в певній рядку, ви можете скористатись опцією пошуку pickaxe, "-S":

git log -g -Ssearch_for_this
# this also works but may be slower, it only shows text-added results
git grep search_for_this $(git log -g --pretty=format:%h)

Git 1.7.4 додасть параметр -G , що дозволить вам передати -G <regexp>, щоб знайти, коли перенесено рядок, що містить <regexp>, що -S не може зробити. -S повідомить вам лише про зміну загальної кількості рядків, що містять рядок (тобто додавання / видалення рядка).

Нарешті, ви можете використовувати gitk для візуалізації звисаючих комісій за допомогою:

gitk --all $(git log -g --pretty=format:%h)

А потім скористайтеся його пошуковими функціями, щоб шукати неправильно розміщений файл. Усі ці роботи, припускаючи, що відсутні документи не закінчилися, і зібрали сміття, що може статися, якщо воно бовтається протягом 30 днів, і ви закінчуєте відкладати чи виконувати команду, яка їх закінчує.


4
Можливо, замість того, щоб запускати "git grep" на (можливо, велику) кількість комітетів, у яких були б знайдені всі комітети, які мають "search_for_this" десь у проекті, використовуйте так званий пошук "pickaxe", тобто опцію "-S" для git log , який знаходить коміти, що ввели або видалили заданий рядок, або точніше, де кількість випадків даної рядки змінилася.
Якуб Нарбський

5
Ви можете вказати кілька гілок або скористатися опцією '--all', наприклад, 'git log --grep = "рядок у повідомленні про виконання
комісій

Це просто дозволило мені знайти втрачену комісію за роботу, що коштувала 2 дні. Повністю врятував мою дупу, дякую!
Майк Чемберлен

2
Я зіткнувся з деякими ситуаціями, коли я мав коміти в своїй базі даних, але не в рефлозі. Я не знаю, наскільки це поширене. Я пробував різні мости hg / git. Я думаю, що це може виникнути і при падінні стаси. У будь-якому випадку, цей псевдонім чудово працює, щоб наздогнати ці випадки:!git fsck --unreachable | sed -ne 's/^unreachable commit //p' | xargs git log --no-walk
сумнівний

Зауважте, що це не включає об’єкти пошуку приміток. Це ще не було реалізовано: git.661346.n2.nabble.com/…
Антоні Стаббс

54

У Mercurial ви використовуєте hg log --keywordдля пошуку ключових слів у повідомленнях фіксації та hg log --userпошуку певного користувача. Дивіться hg help logінші способи обмеження журналу.


36
Йосип написав, що розглядає можливість перейти на Меркуріал і також хотів би почути, як це робиться там.
Мартін Гейслер

1
hg log -kПошук виконує ім’я користувача та імена файлів також у наборах змін (я бачу, що в Commands.py:log), що є однією з небагатьох речей, які я не розумію в hg. Потрібні окремі варіанти пошуку в повідомленнях фіксування та іменах файлів. Здається, hg log --template '{desc}\n'|grepце вірний шлях.
Джеффрі Чжен

@GeoffreyZheng: є способи зробити це. Див. "Hg help revsets", esp функції desc (), user () та file (). Для більшості такої поведінки також є перемикачі журналу hg. На мій досвід, хоча -k / ключове слово () зазвичай є найбільш корисним способом пошуку речей.
Кевін Хорн

Як здійснюється пошук за допомогою фактично виконаного вмісту файлу ... різниці? Я знаю, що це був би повільний пошук, але я хочу зробити глибокий пошук відсутнього імені функції.
Джонатан

О ось це:hg grep --all <term>
Джонатан,

24

На додаток до богатирської відповіді щодо використання git log -g --grep=<regexp>або git grep -e <regexp> $(git log -g --pretty=format:%h): перегляньте наступні публікації в блозі від Джуніо С Хамано, поточного супровідника git


Підсумок

І мерзотник Grep і мерзотник журнал --grep є лінією орієнтованого , в тому , що вони шукають лінії , які відповідають заданим шаблоном.

Ви можете використовувати git log --grep=<foo> --grep=<bar>(або git log --author=<foo> --grep=<bar>внутрішньо перекладене на два --grep), щоб знайти коміти, які відповідають будь-якому з шаблонів (неявна АБО семантична).

З - за того , щоб бути лінія-орієнтованої, корисний і семантика використовувати git log --all-match --grep=<foo> --grep=<bar>для пошуку фіксації , яка має як відповідність рядка першої і другої лінії узгодження де - то.

З git grepви можете об'єднати декілька шаблонів (все , що повинні використовувати -e <regexp>форму) з --or(це значення за замовчуванням), --and, --not, (і ). Для grep --all-matchозначає, що у файлі повинні бути рядки, які відповідають кожній із альтернатив.


Ей, Якуб, маю на увазі інтегрувати цитати / резюме з цих публікацій блогу тут? Схоже, один із старовинних відповідей лише на посилання.
Натан Туггі

11

Спираючись на відповідь rq, я виявив, що цей рядок робить те, що я хочу:

git grep "search for something" $(git log -g --pretty=format:%h -S"search for something")

Котрий повідомить про ідентифікатор комісії, ім’я файлу та відобразить відповідний рядок, наприклад:

91ba969:testFile:this is a test

... Чи хтось згоден, що це було б непоганим варіантом бути включеним у стандартну команду git grep?


5

Будь-яка команда, яка сприймає посилання як аргументи, приймає --allпараметр, задокументований на довідковій сторінці git rev-listнаступним чином:

   --all
       Pretend as if all the refs in $GIT_DIR/refs/ are listed on the
       command line as <commit>.

Так, наприклад git log -Sstring --all, відображатимуться всі комітети, які згадуються, stringі доступні з гілки або з тегу (я припускаю, що ваші звисаючі комірки принаймні названі тегом).


3
Схоже, це не так git grep, де, як --allвидається, буде переведено в / використовується як --all-match. Це виглядає як помилка для мене .. за допомогою Git 1.7.2.3 (з використанням $(git rev-list --all)робіт).
синій

5

З Mercurial ви робите

$ hg grep "search for this" [file...]

Є й інші варіанти, які звужують діапазон змін, які шукаються.


1
Мені також подобається прапорhg grep --all
Джонатан

2

Не знаю про git, але в Mercurial я би просто передав вихід журналу hg на якийсь sed / perl / будь-який сценарій, щоб шукати все, що ви шукаєте. Ви можете налаштувати вихід журналу hg за допомогою шаблону чи стилю, щоб полегшити пошук, якщо хочете.

Сюди ввійдуть усі названі відділення репо. У Меркуріала немає щось подібне до звисаючих крапель afaik.


1
Я не розумію, наскільки ця відповідь відповідає вказаній проблемі.
jribeiro

3
Це відповідь на запитання для Mercurial, про яке задається оригінальне питання в останньому абзаці.
Курт Шельфут


1

Щоб додати ще одне ще не вказане рішення, я мав сказати, що використання графічного поля пошуку Gitg було для мене найпростішим рішенням. Він вибере перше виникнення, і ви можете знайти наступне за допомогою Ctrl-G.


1

Одна команда в git, на яку я думаю, що набагато простіше знайти рядок:

git log --pretty=oneline --grep "string to search"

працює в Git 2.0.4

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