Продвинутые Git команды из курса (часть 2)
Поиск по истории
Доступность комитов
Dot Dot notation
показывает комиты которые доступны из одой ветки, но не доступны из другой
git log feature..master
Dot Dot Dot notation
показывает комиты которые доступны для каждой из веток, но не для обоих сразу
(зачем это может быть нужно узнаете позже)
git log feature...master
Визуализация веток
git log master feature --graph
можем использовать команду show-branch, чтобы покзать только те ветки, которые нужны
git show-branch master feature expretimental
Проверка того какие бранчи вмержены в мастер, а какие нет производится командами
git branch --merged
git branch --no-merged
Посмотреть какие комиты между HEAD и другой невмерженной веткой (experimental)
git log HEAD..experimental
Также посмотреть невмерженные комиты можно при помощи
git show-branch --topic master feature experiment
Иногда мы хотим вмержить отдельный комит (например с помощью cherry pick) и нам нужно знать, является ли этот комит эквивалентным по содержанию комиту в нашей ветке (но имеет другой комит id). Такой комит называтся prime. Звучит сложно и непонятно (оно так и есть, но будет понятно позже).
git log --cherry-mark --left-right --no-merges master...experimental
Комиты, которые недоступны из ветки master в ветке experimental помечаются знком >, те что недоступны из ветки experimental знаком <, а те что эквивалентны помечаются знаком =
Можно использовать параметры --left-only и --right-only в зависимости от ветки, которая нас интересует
Три точки значит что мы указываем список комитов, который доступны из одной ветки или из другой, но не из обоих сразу, при этом фильтруем мерджи --no-merges.
git log --cherry-pick --left-right --no-merges master...experimental
показывает комиты без эквивалетности (только те, которых не хватает в какой либо ветке)
git log --cherry-pick --right-only --no-merges master...experimental
покажет только те комиты, которых не хватает в мастере
Короткая запись для этого git log --cherry master...experimental
Посмотреть список мерджей из фичи в мастер можно так
git log --merges feature..master
самый последний мердж комит можно глянуть так
git log --merges --ancestry-path feature..master
Поиск изменений в файлах
git log --follow filename
git log --follow --patch filename
- покажет изменения прямо в коде
Найти комит в котором удалена строка "calculator" можно командой -S
git log -Scalculator
Также можно использовать regex, который будет искать добвление или удаление строки (но не изменение)
git log -S".*is.*" --pickaxe-regex
Чтобы найти именно изменение, нужно использовать опцию -G
git log -Gcalculator
git log -Gcalculator --stat
- с более подробной инфой
Поиск изменений (например функции substract в файле calculator.с) с помощью опции -L (language-aware diff, git >= 1.8.4)
git log -L:substract:calculator.c
В git можно настроить языковые парсеры для разных языков программирования через .gitattributes файл в репозитории. Подробнее тут
Поиск по автору
git log --author="name"
git log --commiter="name"
git log --commiter="name" --since="1 week" --until="2 days ago"
- c фильтром по времени
git blame filename
- показывает авторов для каждой строки
git blame master..feature filename
- blame для комитов из feature branch
git blame filename -L:substract
- с поиском по фунции substract
Можно поигарться и посмотреть статистику по числу комитов топ 10 авторов репозитория:
git shortlog -s -n | head -10
-s - суммируем общее число комитов по автору
-n - сортировка по числу
Работа с ветками
Показать ветки:
git branch --all
git show-ref --heads
git branch -d experimental
удалят ветку с предупреждением, если есть незамерженные в master комиты
git branch -D experimental
удаляет без доп вопросов
По факту удаляется референс на эту бранч. Head ветки на самом деле переходит в статус dangling. Это значит что он больше недоступен из других комитов
Этот комит можно посмотреть с помощью команды
git fsck --dangling --no-progress
Все предки данного комита тоже становятся недоступными, но их можно посмотреть так git fsck --unreachable --no-progress
Восстановить ветку можно через
git branch experimental hash
- где hash - хеш комита из результата команды git fsck --dangling
Слияние
- Fast Forward - head одной бранчи является предком для другой бранчи и слияние можно произвести просто передвинув Head вперед
- True merge - когда есть комиты у одной бранчи недоступные для другой. Приходится делать мердж комит
- Ребейз - переносит изменения одной ветки относительно последнего комита другой ветки. Далее можно сделать fast forward merge
По факту rebase = merge, только не все комиты сразу, а по очереди по одному
FF
TM
Rebase
Можно сделать тру мердж даже если по идее есть возможность для фаст форварда
git merge feature --no-ff
Приемущества ff в линейности истории.
Недостаток - если есть косяки мержа, трудно понять где ошибка, а если бы это был тру мерж, то очевидно косяк в мерж комите.
Когда какой способ выбрать?
- если мержите 2 публичные ветки - то лучше тру мердж
- если приватную ветку с публичной - то лучше ребейз и фаст форвард, а если возникнут проблемы, то правило консистентности комитов должно помочь быстро найти ошибку
cherry-pick
cherry-pick позволяет смержить выбранный комит из ветки в другую
git cherry-pick feature
- смержит последний комит из feature в текущую ветку
можно смержить целый промежуток комитов через .. при этом первый указазнный не будет включен. Например чтобы смержить ВСЕ комиты с начала ветки через две точки нужно сделать так
git cherry-pck $(git merge-base master feature)..feature
Резрешение конфликтов
Чтобы отменить конфликтный мерж можно использовать
git merge --abort
Чтобы понять какой комит в ветках содержит конфликт можно посмотреть лог с параметрами --merge
git log --merge --name-only
Если все еще не понятно как разрешить конфликт, можно посмотреть все версии файла - в том числе и актуального родителя для обоих веток
git merge-base HEAD MEARGE_HEAD
Он выдаст наиболее актуальный базовый комит
Если есть общий родитель для этих веток, то можно сделать three way merge, который сравнивает изменения в файле не только между ветками, но и с общим родителем
git checkout --conflict=diff3 calclator.c
Он покажет еще изменения относительно base комита
Можно прописать в настройках чтобы git всегда добавлял base часть: merge.conflictStyle diff3
Если вы знаете какая версия должна быть выбрана при конфликте, то можно сразу выбрать опцию —ours или —theirs при checkout
git checkout —ours calculator.c
Сохраненные резолвы конфликтов
Например мы хотим понять, что наша фича ветка совместима с мастером. Мы хотим сделать тестовый мерж. При мерже появились конфликты и мы их зарезолвили и сделали комит. Не пушаем в master, нам достаточного и этого. Потом мы поняли что все окей и хотим сделать рябейз чтобы сохранить линейность истории. Ресетаем мастер, к исходному состоянию и делаем ребейз. Опять появляется конфликт, но в этот раз git говорит что уже знает как его резолвить, потому что мы резолвили эти же файлы в мерже!
Кстати, завел личный блог Sleepless Tech в Telegram про разработку и DIY, заходите!
И присоединяйтесь к каналам FrontEndDev и Web Stack в Telegram, чтобы не пропустить самое интересное из мира Web!