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

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

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

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

6 ответов


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

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

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

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

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

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

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

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

-- reverse - это тоже полезно, Так как вы хотите первый коммит, который внес изменения:

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

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


Марк Longair это отлично, но я нашел эту более простую версию, чтобы работать на меня.

git log -S whatever

возиться с теми же ответами:

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

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

$ git find <whatever>

или

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

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

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

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

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

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

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