Когда работаешь с Git каждый день, очень быстро понимаешь - больше всего времени уходит не на разработку, а на бесконечную рутину. git status, git pull, git add, git commit, git push и так по кругу десятки раз в день. Раньше такие вещи обычно автоматизировали bash-скриптами вроде gitpush.sh и gitpull.sh, но со временем подобный подход превращается в набор разрозненных костылей. Именно поэтому многие DevOps и инфраструктурные инженеры используют Makefile как единый интерфейс управления проектом. Вместо длинных команд появляется простой и понятный make push или make pull. Это не только ускоряет работу, но и уменьшает количество ошибок, особенно в больших проектах с Kubernetes, CI/CD и несколькими ветками разработки. В этой статье разберем, как превратить Makefile в удобную консоль для работы с Git, автоматизировать самые частые операции и сделать повседневную работу с репозиториями намного приятнее.
Есть два типа инженеров:
-
те, кто каждый раз вручную пишет git add . && git commit -m "fix" и потом забывает сделать git pull
-
и те, кто один раз нормально автоматизировал рутину и больше не страдает
Если вы каждый день работаете с Git, то очень быстро начинаете ненавидеть повторяющиеся действия:
git status
git add .
git commit -m "какой-то коммит"
git pull
git push
Особенно когда у тебя:
-
15 репозиториев
-
несколько веток
-
CI/CD
-
ArgoCD
-
Jenkins
-
и прод, который любит падать в пятницу вечером
Раньше многие решали это bash-скриптами:
-
gitpull.sh
-
gitpush.sh
Но в 2026 году это уже выглядит как старый сервер на CentOS 6, который "пока не трогайте, он работает".
Сегодня нормальный подход - использовать Makefile.
Почему?
Потому что:
-
он читаемый
-
легко расширяется
-
не требует делать chmod +x
-
отлично документируется
-
одинаково работает почти везде
-
превращает Git в набор удобных команд
И самое главное - Makefile становится вашей маленькой инженерной консолью для проекта.
Что такое Makefile и почему это удобно
Makefile - это файл с командами, которые можно запускать как:
make push
make pull
make deploy
make test
То есть вместо:
git add .
git commit -m "fix"
git push origin dev
вы пишете:
make push
Красота.
Особенно когда спустя полгода вы уже не помните:
-
в какую ветку пушить
-
какие теги использовать
-
какие проверки запускать перед коммитом
Базовый Makefile для Git
Создаем файл:
touch Makefile
И пишем:
BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
pull:
git pull origin $(BRANCH)
push:
@read -p "Commit message: " msg; \
git add . && \
git commit -m "$$msg" && \
git push origin $(BRANCH)
status:
git status
log:
git log --oneline --graph --decorate -20
branches:
git branch -a
Теперь можно делать:
make pull
make push
make status
И жизнь уже стала приятнее.
Немного магии - автоматическое определение ветки
Вот эта строка:
BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
автоматически определяет текущую ветку.
То есть:
-
сидите в main
-
работаете в dev
-
чините пожар в hotfix/payment-production-fire
Makefile сам поймет куда пушить.
Это уже сильно лучше, чем:
git push origin main
который случайно улетает не туда.
А Git потом смотрит на вас осуждающе.
Добавляем самые полезные Git-команды
Теперь превращаем Makefile в настоящий DevOps-швейцарский нож.
Красивый git status
status:
@git status -sb
Получаем компактный вывод:
## main...origin/main
M app.py
?? new_file.txt
Быстрый git pull --rebase
Обычный pull иногда превращает историю в макароны.
Поэтому лучше:
update:
git pull --rebase origin $(BRANCH)
Теперь:
make update
И история коммитов остается чистой.
Автоматический push с timestamp
Очень удобно для черновых коммитов.
quickpush:
git add . && \
git commit -m "auto: $$(date '+%Y-%m-%d %H:%M:%S')" && \
git push origin $(BRANCH)
Использование:
make quickpush
Да, message получится не очень красивый.
Но когда у тебя горит production - уже не до поэзии.
Просмотр последних коммитов
history:
@git log \
--graph \
--pretty=format:'%C(yellow)%h%Creset - %C(green)(%cr)%Creset %s %C(blue)<%an>%Creset' \
--abbrev-commit \
-15
Красивый вывод:
* 1fa32bc - (2 hours ago) fix ingress <alex>
* a82c123 - (5 hours ago) update ci <alex>
Очень удобно.
Проверка изменений перед коммитом
diff:
git diff
или:
diffcached:
git diff --cached
Создание новой ветки
newbranch:
@read -p "Branch name: " branch; \
git checkout -b $$branch
Теперь:
make newbranch
Переключение между ветками
checkout:
@read -p "Branch: " branch; \
git checkout $$branch
Удаление локальных веток
Очень полезно когда репозиторий превращается в кладбище feature-веток.
cleanbranches:
git branch --merged | \
egrep -v "(^\*|main|master|dev)" | \
xargs git branch -d
Git stash как нормальный человек
Потому что:
"я сейчас быстренько переключусь"
обычно заканчивается конфликтами.
stash:
git stash
unstash:
git stash pop
stashlist:
git stash list
Работа с тегами
Для релизов это вообще must-have.
tag:
@read -p "Tag: " tag; \
git tag $$tag && \
git push origin $$tag
Например:
make tag
Вводим:
v1.2.0
И тег улетает в репозиторий.
Git reset без боли
Иногда надо быстро откатить изменения.
reset:
git reset --hard HEAD
Но осторожно.
Это команда из разряда:
"либо починил, либо стало сильно интереснее"
Полезный production-safe push
Можно добавить подтверждение:
safe-push:
@read -p "Push to $(BRANCH)? [y/N]: " confirm; \
if [ "$$confirm" = "y" ]; then \
git push origin $(BRANCH); \
else \
echo "Canceled"; \
fi
Иногда спасает от:
-
случайного пуша в main
-
пуша в прод-ветку
-
плохих жизненных решений
Полный пример нормального Makefile для Git
BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
status:
@git status -sb
pull:
git pull origin $(BRANCH)
update:
git pull --rebase origin $(BRANCH)
push:
@read -p "Commit message: " msg; \
git add . && \
git commit -m "$$msg" && \
git push origin $(BRANCH)
quickpush:
git add . && \
git commit -m "auto: $$(date '+%Y-%m-%d %H:%M:%S')" && \
git push origin $(BRANCH)
history:
@git log \
--graph \
--pretty=format:'%C(yellow)%h%Creset - %C(green)(%cr)%Creset %s %C(blue)<%an>%Creset' \
--abbrev-commit \
-15
branches:
git branch -a
newbranch:
@read -p "Branch name: " branch; \
git checkout -b $$branch
checkout:
@read -p "Branch: " branch; \
git checkout $$branch
stash:
git stash
unstash:
git stash pop
stashlist:
git stash list
diff:
git diff
diffcached:
git diff --cached
tag:
@read -p "Tag: " tag; \
git tag $$tag && \
git push origin $$tag
cleanbranches:
git branch --merged | \
egrep -v "(^\*|main|master|dev)" | \
xargs git branch -d
reset:
git reset --hard HEAD
safe-push:
@read -p "Push to $(BRANCH)? [y/N]: " confirm; \
if [ "$$confirm" = "y" ]; then \
git push origin $(BRANCH); \
else \
echo "Canceled"; \
fi
Почему Makefile лучше bash-скриптов
Плюсы
1. Все команды в одном месте
Не нужно:
-
gitpull.sh
-
gitpush.sh
-
deploy.sh
-
ci.sh
Один Makefile.
2. Хорошо масштабируется
Сегодня:
make push
Завтра:
make deploy
make helm
make terraform
make k8s-restart
И внезапно у вас уже полноценная инженерная консоль проекта.
3. Удобно для команды
Новый инженер приходит в проект:
make help
и видит все доступные команды.
4. Отлично работает с Kubernetes
Очень быстро Makefile начинает выглядеть так:
deploy:
helm upgrade --install app ./helm
logs:
kubectl logs -f deploy/app
restart:
kubectl rollout restart deploy app
И вот вы уже живете в терминале как настоящий платформенный инженер.
Минусы
1. Makefile чувствителен к TAB
Да.
Не пробелы.
TAB.
Это древняя магия UNIX.
Если случайно поставить пробелы - Makefile развалится как старый Jenkins после обновления Java.
2. Сложная логика выглядит плохо
Если у вас:
-
циклы
-
условия
-
400 строк shell-кода
лучше:
-
вынести в bash/python
-
а Makefile использовать как точку входа
Итог
Makefile для Git - это одна из тех маленьких автоматизаций, которые:
-
экономят время
-
уменьшают количество ошибок
-
делают работу приятнее
-
превращают рутину в одну команду
А главное - после недели использования вы уже не захотите возвращаться к ручному вводу Git-команд.
Потому что инженер должен автоматизировать всё, что повторяется чаще двух раз.
Даже собственную лень.