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

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

Вот почему в этой статье я представляю несколько команд, которые пригодятся при поиске чего-либо в Git. Статья разбита на примеры из реальной жизни, чтобы сделать ее более практичной и простой в использовании.

Где находится фиксация с сообщением, в котором упоминается…?

Это один из наиболее распространенных сценариев. Вы знаете, что видели фиксацию, в которой упоминается, скажем, MessageBus, но вы не знаете, когда она была зафиксирована или даже в какой ветви. Или, может быть, вы просто ищете все коммиты, в которых упоминается какой-то тикет Jira. Кроме того, вам может быть интересно узнать, сколько исправлений было в истории вашего проекта.

Во всех этих примерах лучше всего использовать команду git log. Эта команда настолько мощная и универсальная, что в той или иной форме является решением для большинства случаев использования, представленных в этой статье.

Решение:

git log [-i] [--all] --grep ‹phrase›

-i - игнорировать регистр; используйте его для поиска без учета регистра

--all - поиск по всем ссылкам; используйте его для поиска всех коммитов, а не только тех, которые доступны из текущей ветки

Пример:

git log -i --all --grep MessageBus

Что… делали в прошлом месяце?

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

Решение:

git log [--pretty = fuller] --author ‹имя автора› --after ‹startDate› --before ‹endDate›

--pretty = fuller - параметры после и до фиксируются по дате автора, но в журнале по умолчанию отображается дата фиксации; используйте параметр pretty, чтобы отобразить дату автора и дату фиксации

Пример:

git log --pretty = fuller --author «Junio ​​C Hamano» - после «2021-01-01T00: 00: 00 + 01: 00» - до «2021-02-01T00: 00: 00+» 01:00 ”

Кто и когда изменял файл в последний раз?

Иногда нам нужно знать, был ли просматриваемый файл изменен недавно, или нам просто нужно знать, когда он последний раз редактировался и кто это делал.

Решение:

git log -1 ‹filePath›

- ‹n› - количество отображаемых коммитов

Пример:

git log -1 docs / README.md

Какова история файла?

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

Это решение является просто обобщением предыдущего: нам просто нужно отказаться от параметра количества коммитов.

Решение:

git log ‹filePath›

Пример:

git log docs / README.md

Какова история файла, включая переименования?

Предыдущее решение отлично работает, но у него есть один недостаток: оно показывает историю файла только с момента его последнего переименования.

К счастью, эту проблему легко решить: нам просто нужно добавить в команду один параметр --follow.

Решение:

git log [--summary] --follow ‹filePath›

--summary - показать больше информации о коммитах, в данном случае о переименовании

--follow - продолжить перечисление коммитов даже после переименования файла

Пример:

git log --summary --follow scripts / scripts.js

Какова история удаленного файла?

Если мы попытаемся использовать предыдущую команду, чтобы просмотреть историю файла, который больше не существует, Git ответит ошибкой:

›Git log deletedFile

фатальный: неоднозначный аргумент «удаленный файл»: неизвестная ревизия или путь не в рабочем дереве.
Используйте «-», чтобы отделить пути от ревизий, например:
'git ‹command› [‹revision›… ] -- […]'

Git сообщает нам, что не может понять, что такое «удаленный файл». Это потому, что он не может найти его в рабочем каталоге, чтобы убедиться, что мы пытаемся указать имя файла. В конце концов, мы могли бы также передать имя ветки. Поэтому нам нужно использовать -, чтобы отделить ревизию от пути.

Вот хороший пример, который может помочь понять необходимость -. Представьте, что у вас есть файл и ветка с одинаковым именем, например, dev. Если вы хотите вывести список всех коммитов из ветки dev, вы должны использовать следующую команду:

git log dev -

Но если вы хотите перечислить все коммиты, в которых был изменен dev файл, команда будет такой:

git log - разработчик

Решение:

git log - ‹filePath›

Пример:

git log - scripts / script.js

Какова история удаленного файла по пути, который я не помню?

Предыдущее решение работает как чудо, если известно точный путь к удаленному файлу. Однако обычно мы запоминаем только имя файла или только его часть.

К счастью, git log также принимает регулярные выражения, поэтому мы можем использовать шаблон вместо полного пути.

Решение:

git log - ‹regex›

Пример:

git log - * script.js

Кто написал эту строку !?

Пусть тот, кто никогда не выкрикивал эти слова в гневе, бросит первый камень. На этот раз у Git снова есть отличная команда для поиска ответа на этот вопрос.

Укоризненно звучащая команда git blame показывает нам содержимое выбранного файла с информацией о последнем редактировании для каждой его строки - с автором, датой и хешем фиксации.

Решение:

git blame ‹filePath›

Пример:

git blame index.html

Какие коммиты добавили или удалили эту строку / регулярное выражение?

Бывают случаи, когда git blame не оправдывает ожиданий - например, мы могли бы проверять, когда (а также кем и почему) была добавлена ​​некоторая критическая строка, только для того, чтобы узнать, что последняя модифицирующая ее фиксация была исправлением отступа.

Здесь на помощь приходит так называемая команда pickaxe. Когда мы предоставляем параметр -S вместе с фразой, Git покажет нам все коммиты, которые были добавлены и / или удалены. строки, содержащие эту фразу.

Однако при использовании кирки есть два улова:

  • он не покажет фиксацию, если количество вхождений фразы не изменилось (например: если фиксация добавила одну строку с этой фразой и удалила другую с той же фразой),
  • он не работает с регулярными выражениями.

Решение этих двух недостатков очень простое: просто используйте -G вместо -S.

Обратите внимание, что обе команды выполняются довольно медленно. Поэтому, если у нас есть представление о конкретном файле (или пути), в котором встречается фраза, мы можем сузить область поиска, указав путь в конце команды.

Решение:

git log -S ‹phrase› [‹filePath›]
git log -G ‹regex› [‹filePath›]

Примеры:

git log -S делегировать GameViewController.swift
git log -G UI * Делегировать GameViewController.swift

Есть ли строка… в проекте?

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

Решение:

git grep [-i] ‹phrase›

-i - игнорировать регистр; используйте его для поиска без учета регистра

Пример:

git grep MyP4ssw0rd

Была ли строка… в проекте?

Кроме того, мы могли бы захотеть проверить, появлялась ли данная фраза когда-либо в нашем проекте.

Зная, что git grep принимает список коммитов для поиска и что для получения хэшей всех коммитов мы используем:

git rev-list - все

Мы могли бы использовать следующую команду:

git grep ‹phrase› $ (git rev-list - все)

К сожалению, если ваш репозиторий имеет долгую историю, это не сработает и приведет к следующей ошибке:

список аргументов слишком длинный: git

Это связано с тем, что git grep может принимать только определенное количество аргументов, а git rev-list --all может легко дать результат, превышающий этот предел. Чтобы обойти это ограничение, нам нужно использовать xargs.

Решение:

git rev-list --all | xargs git grep [-i] ‹phrase›

Пример:

git rev-list --all | xargs git grep MyP4ssw0rd

Мы также можем использовать команду кирки для этого сценария, но если нас больше беспокоят if и where, а не when git grep даст нам несколько лучше представленные результаты.

Какова история этого метода?

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

Решение:

git log -L ‹startLine›, ‹endLine›: ‹filePath›

Пример:

git log -L 119 233: index.html

Резюме

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

Я действительно надеюсь, что вы чему-то научились и что в будущем вы еще больше воспользуетесь потенциалом поиска в репозитории с помощью команд Git. Или, по крайней мере, что я помог вам найти решение, которое вы искали.