Git: показать все различные изменения одной строки в указанном файле во всей истории git

112

Я огляделся и не уверен, возможно ли это, но вот что:

У меня есть файл (javascript) (скажем, /lib/client.js), в котором у меня есть уникальный идентификатор, присвоенный переменной, например: var identifier = "SOME_IDENTIFIER";

Вы можете думать об идентификаторе как о номере версии: периодически мы меняем эту переменную на новый идентификатор.

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

Я предполагаю, что есть способ выполнить поиск в истории git и распечатать соответствие строки "var identifier =". Я мог бы распаковать этот список вручную.

В любом случае, я был бы признателен за любое понимание здесь. Спасибо.

Findchris
источник

Ответы:

106

Начиная с git 1.8.4 , есть более прямой способ ответить на ваш вопрос.

Предполагая, что эта строка 110является строкой, говорящей var identifier = "SOME_IDENTIFIER";, сделайте следующее:

git log -L110,110:/lib/client.js

Это вернет каждую фиксацию, которая коснулась этой строки кода.

[ Документация Git (см. Параметр командной строки "-L")]

Александр Берд
источник
49

См. Справочную страницу для git-logи gitdiffcore. Я считаю, что эта команда сделает это, но это может быть не совсем правильно:

git log -G "var identifier =" file.js

РЕДАКТИРОВАТЬ: вот примерное начало сценария bash, чтобы показать фактические строки. Возможно, это именно то, что вы ищете.

for c in $(git log -G "something" --format=%H -- file.js); do
    git --no-pager grep -e "something" $c -- file.js
done

Он используется git log -Gдля поиска интересных коммитов, используя --format=%Hдля создания списка хэшей коммитов. Затем он выполняет итерацию по каждой интересной фиксации, прося git grepпоказать строки из этой фиксации и файла, содержащие регулярное выражение, с префиксом хэша фиксации.


РЕДАКТИРОВАТЬ: изменено на использование -Gвместо -Sпредложенного в комментариях.

грабить
источник
@Rob - спасибо за это - небольшое изменение вашего скрипта - размещение только имени файла показывает только коммиты, которые влияют только на этот файл - если коммит ссылается на другие файлы, его нет в списке
Адриан Корниш,
@AdrianCornish - Рад, что это было полезно. Я думаю, что OP хотел просто посмотреть на один файл, но вы совершенно правы, что удаление имени файла, вероятно, является более полезным скриптом.
ограбить
У меня более сложная ситуация. Рассматриваемый файл перемещен из paht_a / file в path_b / file. Теперь, когда я делаю это в path_b, он показывает только изменения до того момента, когда файл переместится с path_a на path_b. Если я сделаю это в path_a, он скажет мне фатальный: неоднозначный аргумент «файл»: неизвестная версия или путь не в рабочем дереве.
Энди Сонг
@AndySong - Если строка, которую вы ищете, достаточно уникальна, возможно, вы можете просто опустить имя файла и при этом получить то, что ищете.
rob
Мне было удобнее - ставить пустую строку после каждого коммита, перечислять строки:sfile=path/to/some_file; sfind='string_to_find'; for c in $(git log -G $sfind --format=%H -- $sfile); do git --no-pager grep -e $sfind -n $c -- $sfile; echo; done
John_West
14

Вы также можете сделать это с помощью gitk:

gitk file.js

В раскрывающемся списке «фиксация» выберите «добавление / удаление строки:» и в текстовом поле рядом с ней введите «var identifier =», и все фиксации, которые добавляют или удаляют строки, содержащие эту строку, будут выделены.

Итан Браун
источник
Это помогло точно определить фиксацию, в которую была добавлена ​​строка, содержащая "var identifier =", но не отображаются последующие фиксации, которые изменили эту строку.
findchris
2
Вы пробовали git blame file.jsили git gui blame file.js?
Итан Браун
1
Я знаю, что делает git blame; Я ищу полную историю изменений, а не единую разницу.
findchris
1
git gui blame file.jsсделает это ... он покажет вам все версии файла и кто их изменил; вы можете просто пролистать историю назад.
Итан Браун
Я закончил визуально с помощью gitk. Я полагаю, что для этого есть какая-то элегантная техника git, но gitk был достаточно хорош. Спасибо.
findchris
9

Если вы немного адаптируете ответ @ rob, git logон в основном сделает это за вас, если все, что вам нужно, это визуальное сравнение:

git log -U0 -S "var identifier =" path/to/file

-U0означает вывод в режиме исправления ( -p) и показывать нулевые строки контекста вокруг исправления.

Вы даже можете сделать это в разных ветках:

git log -U0 -S "var identifier =" branchname1 branchname2 -- path/to/file

Может быть способ подавить заголовок diff, но я его не знаю.

Андрей
источник
Сработало у меня! Спасибо.
Роберто Бонини
3

В Magit вы можете сделать это с помощью

l, =L

Затем он попросит вас указать файл и начальную, конечную строки.

трущобы
источник