Как найти коммит Git, который ввел строку в любую ветку?

Я хочу, чтобы найти определенную строку, которая была введена в любом коммите в любая отрасль, как я могу это сделать? Я нашел что-то (что я изменил для Win32), но git whatchanged, похоже, не смотрит в разные ветки (игнорируйте кусок py3k, это просто исправление фида сообщений msys/win)

git whatchanged -- <file> | \
grep "^commit " | \
python -c "exec(\"import sys,msvcrt,os\nmsvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)\nfor l in sys.stdin: print(l.split()[1])\")" | \
xargs -i% git show origin % -- <file>

Не имеет значения, медленно ли ваше решение.

Ответ 1

Вы можете сделать:

git log -S <whatever> --source --all

Чтобы найти все фиксации, которые добавили или удалили фиксированную строку whatever. Параметр --all означает запуск из каждой ветки, а --source означает, чтобы показать, какая из этих ветвей привела к обнаружению этой фиксации. Часто бывает полезно добавить -p, чтобы показать патчи, которые каждая из этих коммитов также представила бы.

Версии git, так как 1.7.4 также имеют аналогичную опцию -G, которая принимает регулярное выражение. Это фактически имеет другую (и, скорее, более очевидную) семантику, объясненную в этом сообщении в блоге от Юнио Хамано.

Как thameera указывает на комментарии, вам нужно поместить цитаты вокруг поискового запроса, если они содержат пробелы или другие специальные символы, например:

git log -S 'hello world' --source --all
git log -S "dude, where my car?" --source --all

Вот пример использования -G, чтобы найти вхождения function foo() {:

git log -G "^(\s)*function foo[(][)](\s)*{$" --source --all

Ответ 2

- обратный также полезен, так как вы хотите, чтобы первое коммитирование сделало это изменение:

git log --all -p --reverse --source -S 'needle'

Таким образом, сначала появятся старшие коммиты.

Ответ 3

Ответ Mark Longairs превосходный, но я нашел эту более простую версию для работы для меня.

git log -S whatever

Ответ 4

Беседа с теми же ответами:

$ git config --global alias.find '!git log --color -p -S '
  • ! требуется, потому что иначе, git не правильно передает аргумент -S. См. этот ответ
  • - цвет и -p позволяет точно показать "whatchanged"

Теперь вы можете сделать

$ git find <whatever>

или

$ git find <whatever> --all
$ git find <whatever> master develop

Ответ 5

git log -S"string_to_search" # options like --source --reverse --all etc

Обратите внимание, чтобы не использовать пробелы между S и "string_to_search". В некоторых настройках (git 1.7.1) вы получите сообщение об ошибке:

fatal: ambiguous argument 'string_to_search': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions

Ответ 6

Хотя это прямо не отвечает на ваш вопрос, я думаю, что это может быть хорошим решением для вас в будущем. Я видел часть своего кода, что было плохо. Не знал, кто написал это или когда. Я мог видеть все изменения из файла, но было ясно, что код был перенесен из другого файла в этот. Я хотел найти, кто на самом деле добавил его в первую очередь.

Чтобы сделать это, я использовал Git bisect, который быстро позволил мне найти грешника.

Я запустил git bisect start, а затем git bisect bad, потому что в проверке исправления возникла проблема. Поскольку я не знал, когда возникла проблема, я нацелил первую фиксацию на "хороший", git bisect good <initial sha>.

Затем я просто продолжал искать репо для плохого кода. Когда я нашел его, я побежал git bisect bad, а когда его там не было: git bisect good.

В ~ 11 шагах я рассмотрел ~ 1000 коммитов и нашел точную фиксацию, где была введена проблема. Довольно здорово.

Ответ 7

Не уверен, почему принятый ответ не работает в моей среде, наконец, я запускаю команду ниже, чтобы получить то, что мне нужно

git log --pretty=format:"%h - %an, %ar : %s"|grep "STRING"