[Перевод] Итак, вы думаете, что знаете Git? Часть первая: старый добрый Git
Автор оригинала Скотт Чакон — сооснователь GitHub и основатель нового клиента GitButler. Этот клиент ставит во главу угла рабочий процесс и удобство разработки, в том числе код-ревью, и не является просто очередной обёрткой над CLI git.
В первом посте из этой короткой серии по Git я хотел начать с вещей, уже существующих какое-то время. При этом кажется, что многие люди о них не знают или не умеют ими пользоваться. В них нет ничего нового, но я нахожу их полезными и, возможно, не совсем освещёнными. Я просто хочу рассказать о:
Условная конфигурация
Многие из вас, вероятно, знают, что в Git есть маленькое классное хранилище «ключ-значение», вызываемое командой git config
. Его значения, которые подставляются при выполнении различных команд, Git проверяет в трёх местах.
Наверное, каждого пользователя Git при первой настройке попросили запустить что-то такое:
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
Команда добавляет значение user.name
в файл ~/.gitconfig
. Но также есть другие опции:
--system
, которой, возможно, никто не пользовался. Она записывает значение в общесистемный конфигурационный файл [прим. перев. — речь идёт о$(prefix)/etc/gitconfig
];--local
— по умолчанию. Она записывает значение в.git/config
любого проекта, где вы находитесь прямо сейчас.
В поиске значения Git смотрит в таком порядке:
- локальное;
- глобальное;
- системное.
Однако есть секретное четвёртое место, которое Git может посмотреть. Если вы добавите в свою глобальную конфигурацию что-то примерно такое:
[includeIf "gitdir:~/projects/oss"]
path = ~/.gitconfig-oss
Git поищет значение в ~/.gitconfig-oss
, только если проект, с которым вы сейчас работаете, находится в ~/projects/oss
.
Итак, у вас могли бы быть:
- каталог
work
со значениями, относящимися к конкретной работе (адрес электронной почты в компании, ключ GPG-подписи и т. д.); - каталог
oss
со значениями для проектов с открытым исходным кодом и т. д.
Но gitdir
— не единственный фильтр:
- через
onbranch
как включающий фильтр можно указать определённые названия ветки; - через
hasconfig: remote.*.url
можно включать файлы конфигурации, только если у текущего проекта есть удалённый сервер с определёнными URL.
Так что ставьте лайк, если у вас есть ключи для GitHub.org или что-то в этом роде. Подробности читайте в документации.
git blame
и git log
с диапазонами строк
Есть пара интересных опций git blame
, о которых большинство людей не знают, а в существующих GUI они почти не реализованы.
Одна из них -L
— диапазон строк. Если вы запускаете git blame
в CLI, часто вы просто просматриваете весь файл и находите ту часть, которую ищете. Но если вы хотите отобразить только подраздел файла, то можно задать диапазон строк, например git blame -L 28,43 путь/к/файлу
:
git blame -L
Чтобы дать Git шаблон для поиска начала блока и выполнить git blame
только для этого блока, можно воспользоваться синтаксисом :
. Так, в той же ситуации я могу получить такой же вывод, выполнив git blame -L : 'class LocalFile' gitbutler-ui/src/lib/vbranches/types.ts
. Вместо 'class LocalFile'
можно подставить имя функции или что-то ещё.
Другая вещь, которую можно сделать, чтобы увидеть похожую информацию по-другому, — запустить git log
с похожими параметрами. Это даст вам все коммиты, которые в последний раз касались заданной области файла.
Например, git log -L28,43:gitbutler-ui/src/lib/vbranches/types.ts
даст вам что-то вроде этого:
Вместо упорядочивания по строкам, опция -L
как будто собирает все коммиты git blame
, а затем показывает коммиты с кодом, в каждом из которых менялся заданный блок. В основном это те же данные, но в другом формате, больше похожем на рассказ, как этот код собирался воедино.
git blame
с отслеживанием
Одна на самом деле не очень хорошая штука в работе с blame через GUI заключается в том, что CLI обладает гораздо более мощными инструментами, чтобы найти что-то ближе к реальной истории, стоящей за вашим кодом. Есть много ситуаций, где это действительно ценно.
Первая — игнорирование изменений пробелов. Некоторые GUI игнорируют их, но не все. Если вы просто пойдёте и внедрите файл prettierrc
— бах, теперь вы владелец тонны строк кода. С опцией git blame -w
эти типы изменений пробельных символов игнорируются.
Другая отличная опция, которая отслеживает перемещение кода между файлами в коммите, — это-C
. Когда вы выполните рефакторинг функции из одного файла в другой, обычная команда git blame
просто покажет вас как автора нового файла, но опция -C
отследит движение кода и покажет последнего, кто изменил строки.
Любые из этих данных могут оказаться тем, что вы ищете, но я бы сказал, чаще всего возникает последняя ситуация. Если вы хотите, чтобы Git старался ещё усерднее (ищите движение в нескольких или во всех коммитах), то можете указать опцию -C
до трёх раз.
Кроме того, ваш GUI не делает этого (скорее всего, я не могу говорить обо всех). Давайте посмотрим на вывод git blame
из предыдущего примера в GitLens VS Code: git blame
в плагине VS Code GitLens
Ок, выглядит хорошо. Большую часть этого кода, кажется, написал Кирил. Теперь давайте посмотрим на тот же блок с git blame -w -C -C -C
:
git blame -C -C -C
Git следовал за этим куском кода от файла к файлу в течение нескольких переименований.
Кроме того, Кирил на самом деле владеет всего несколькими строками, большие его куски на самом деле написал Маттиас. Если захочется разузнать о них, гораздо лучше спросить Маттиаса, а не Кирила, как предполагает наш GUI.
git diff
по словам вместо строк
Это невероятно вторично, а в некоторых графических интерфейсах есть приятные версии. Я нахожу GitHub лучше того, что собираюсь показать, ведь он аккуратно выполняет команду в GUI и в CLI. Но если вы запускаете git diff
в CLI для строки с небольшим изменением, то можете изменить формат Git по умолчанию на слова, а не на строки, опцией--word-diff
:
нормальный, построчный git diff
особенно крутой git diff --word-diff
Память о разрешении конфликта
Наконец, если вы часто выполняете git rebase
или git cherry-pick
и сталкиваетесь с одним и тем же конфликтом чаще одного раза, то можно включить функцию запоминания и разрешения конфликта. Если Git дважды и более раз увидит один и тот же конфликт, то решит его автоматически.
Эту функцию можно легко включить настройкой конфигурации rerere.enabled
. Далее можно попросить Git настроить для вас автоматический стейджинг через rerere.autoUpdate
:
git config --global rerere.enabled true
git config --global rerere.autoUpdate true
Git навсегда запомнил конфликт
Затем, в следующий раз, когда вы столкнётесь с конфликтом, который решали раньше, — магия!
автоматическое исправление
Что дальше?
Опять же, всё это уже давно есть в Git, но если вы чего-то не знали, то теперь знаете. Далее — новые штуки в Git.
Пока я оставляю ссылку на оригинальное продолжение. Дальше будет интереснее!