oakazanin/content/posts/blog-part-4-git-workflow/index.md

418 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: "Блог на Hugo в K3s: часть 4 - выбор Git workflow"
date: 2026-02-16
draft: false
description: "Две папки или одна с переключением веток? Разбираем варианты организации работы с dev и production окружениями на практических примерах."
tags: ["git", "workflow", "devops", "hugo"]
categories: ["Веб-разработка", "DevOps практики"]
series: ["Блог на Hugo в K3s"]
series_order: 4
---
В части 3 мы развернули два окружения - production и development. Один репозиторий, две ветки (`main` и `dev`), два пайплайна.
Теперь встаёт вопрос: **как организовать работу локально?**
---
## Проблема
У нас есть:
- Репозиторий в Gitea
- Две ветки: `main` (production) и `dev` (development)
- Необходимость постоянно переключаться между ними
Как это делать на локальной машине? Два варианта.
---
## Вариант А: Две отдельные папки
Клонируем репозиторий дважды - в разные папки:
```
~/projects/
├── blog/ ← ветка main (production)
└── blog-dev/ ← ветка dev (development)
```
**Логика:** Хочу работать с dev - иду в `blog-dev`. Хочу что-то проверить в production - иду в `blog`. Без переключения веток.
### Кажущиеся преимущества
**Параллельная работа.** Можно держать открытыми два терминала - в одном `hugo server` для dev, в другом смотреть production код.
**Изоляция.** Каждая папка - своя песочница. Изменения в одной не влияют на другую.
**Простота навигации.** `cd blog-dev` вместо `git checkout dev`. Меньше команд.
**Привычный паттерн.** Многие админы и разработчики держат несколько клонов для разных задач.
### Реальные проблемы
#### Проблема 1: Рассинхронизация локальных ветокin
Работаю в `blog-dev` - пишу статьи, коммичу, пушу в `origin/dev`. Всё хорошо.
Но локальная ветка `dev` в папке `blog` при этом **не обновляется**. Она отстаёт от `origin/dev`.
Приходишь делать merge:
```bash
cd blog
git checkout main
git merge dev
# Already up to date. ← НО есть НЮАНС!
```
Git говорит "всё актуально", имея в виду **локальную** ветку `dev`, которая отстала на три коммита. Статьи не попадают в production.
Приходится помнить делать `git pull origin dev` перед каждым merge. Забыл - публикуешь устаревшую версию.
#### Проблема 2: Конфликты при merge
Редактируешь `config/params.toml` в обеих папках независимо:
- В `blog-dev` добавил Firebase конфиг
- В `blog` изменил название сайта
При merge Git честно сообщает о конфликте:
```
CONFLICT (content): Merge conflict in config/params.toml
```
И это повторяется **каждый раз** когда трогаешь конфигурацию. Потому что две папки - это две независимые истории изменений одного файла.
#### Проблема 3: Работа не в той папке
Несколько раз ловил себя на том что редактирую статьи прямо в `blog` - папке production. Это нарушает весь смысл раздельных окружений.
#### Проблема 4: Умственная нагрузка
Постоянный вопрос "в какой папке я сейчас?" Для простого блога это лишняя когнитивная нагрузка.
---
## Вариант Б: Одна папка с переключением веток
Один клон репозитория, работа через `git checkout`:
```
~/projects/
└── blog/ ← одна папка, две ветки: main и dev
```
### Как это работает
**Пишу статью:**
```bash
cd ~/projects/blog
# Переключаюсь на dev
git checkout dev
# Проверяю что dev актуален
git pull origin dev
# Запускаю локальный сервер
hugo server -D --bind 0.0.0.0
# Создаю статью
hugo new content posts/название/index.md
# Коммичу и пушу
git add .
git commit -m "feat: новая статья"
git push origin dev
```
**Публикую:**
```bash
# Убеждаюсь что dev актуален
git checkout dev
git pull origin dev
# Переключаюсь на main и мержу
git checkout main
git pull origin main
git merge dev
git push origin main
```
### Реальные преимущества
**Никакой рассинхронизации.** Все ветки в одном репозитории. `git pull` обновляет всё что нужно.
**Нет конфликтов из-за независимых изменений.** Когда работаешь в одной папке, `params.toml` существует в одном экземпляре. Все изменения делаются в `dev`, в `main` попадают только через merge.
Конфликт возможен только если кто-то редактирует `main` напрямую - а это нарушение workflow.
**Невозможно ошибиться с веткой.** `git branch` показывает где ты сейчас. Случайно отредактировать файлы в `main` - сложнее.
**Меньше места на диске.** Один клон вместо двух. Один `.git` вместо двух.
---
## Сравнение на практических примерах
### Пример 1: Обновление темы Blowfish
**Две папки:**
```bash
cd blog-dev
git submodule update --remote themes/blowfish
git add themes/blowfish
git commit -m "update: Blowfish theme"
git push origin dev
# Проверяешь на dev.blog.ru
# Если всё ок - мержишь
cd ../blog
git checkout dev
git pull origin dev # ← ЛЕГКО ЗАБЫТЬ
git checkout main
git merge dev
git push origin main
```
**Одна папка:**
```bash
cd blog
git checkout dev
git pull origin dev
git submodule update --remote themes/blowfish
git add themes/blowfish
git commit -m "update: Blowfish theme"
git push origin dev
# Проверяешь на dev.blog.ru
# Если всё ок - мержишь
git checkout main
git pull origin main
git merge dev
git push origin main
```
Меньше команд, меньше переходов между папками, меньше шансов забыть `git pull`.
### Пример 2: Правка опечатки в production
Нашёл опечатку на `blog.ru`. Нужно исправить быстро.
**Две папки:**
Опасность: хочется исправить прямо в `blog` (ветка `main`). Это нарушает workflow - все изменения должны идти через `dev`.
Правильно:
```bash
cd blog-dev
git checkout dev
# Исправляешь
git commit -m "fix: опечатка"
git push origin dev
cd ../blog
git checkout main
git pull origin dev # ← опять легко забыть
git merge dev
git push origin main
```
**Одна папка:**
```bash
cd blog
git checkout dev
git pull origin dev
# Исправляешь
git commit -m "fix: опечатка"
git push origin dev
git checkout main
git merge dev
git push origin main
```
Проще, меньше команд, понятнее.
### Пример 3: Долгая работа над статьёй
Пишешь большую статью несколько дней. Между сеансами работы кто-то (или ты сам) запушил другие изменения в `dev`.
**Две папки:**
```bash
cd blog-dev
# День 1: пишешь
git add .
git commit -m "wip: статья"
# День 2: продолжаешь
git pull origin dev # Подтягиваешь чужие изменения
# Пишешь дальше
git add .
git commit -m "feat: закончил статью"
git push origin dev
```
Всё так же как и с одной папкой. Разницы нет.
**Одна папка:**
```bash
cd blog
git checkout dev
# День 1: пишешь
git add .
git commit -m "wip: статья"
# День 2: продолжаешь
git pull origin dev # Подтягиваешь чужие изменения
# Пишешь дальше
git add .
git commit -m "feat: закончил статью"
git push origin dev
```
Идентично. Этот пример работает одинаково в обоих вариантах.
---
## Что выбрать?
**Если ты только начинаешь - сразу делай одну папку.**
Две папки кажутся удобными, но создают проблемы которые регулярно прерывают работу:
- Рассинхронизация веток
- Конфликты при merge
- Когнитивная нагрузка
Одна папка с переключением веток - стандартный Git workflow, проверенный миллионами разработчиков. Требует чуть больше дисциплины (`git checkout dev` вместо `cd blog-dev`), но избавляет от всех проблем выше.
**Золотое правило:** Никогда не редактировать файлы находясь на ветке `main`. Все изменения - через `dev`. Всегда.
---
## Миграция: если начал с двух папок
Если уже работаешь в двух папках - переход простой.
### Шаг 1: Убеждаемся что всё запушено
```bash
# Проверяем обе папки
cd ~/projects/blog-dev
git status
git push origin dev
cd ~/projects/blog
git status
git push origin main
```
### Шаг 2: Синхронизируем ветку dev в основной папке
```bash
cd ~/projects/blog
# Обновляем локальную ветку dev из remote
git checkout dev
git pull origin dev
# Проверяем что всё актуально
git log --oneline -5
# Возвращаемся на main
git checkout main
```
### Шаг 3: Удаляем вторую папку
```bash
# Убеждаемся что в blog-dev нет несохранённых изменений
cd ~/projects/blog-dev
git status
# Должно быть: nothing to commit, working tree clean
# Удаляем папку
cd ~/projects
rm -rf blog-dev
```
### Шаг 4: Проверяем что всё работает
```bash
cd ~/projects/blog
# Переключаемся на dev и запускаем сервер
git checkout dev
hugo server -D --bind 0.0.0.0
# Открываем http://localhost:1313/
# Видим dev версию сайта
```
---
## Новый workflow: шпаргалка
### Создаю статью
```bash
cd ~/projects/blog
git checkout dev
hugo new content posts/название/index.md
# Пишу, сохраняю, проверяю в hugo server
git add .
git commit -m "feat: название статьи"
git push origin dev # → dev.blog.ru
```
### Публикую статью
```bash
git checkout dev
git pull origin dev # Убеждаюсь что dev актуален
git checkout main
git pull origin main # Убеждаюсь что main актуален
git merge dev
git push origin main # → blog.ru
```
### Меняю конфигурацию
```bash
git checkout dev # ВСЕ изменения только через dev!
nano config/params.toml
git add .
git commit -m "feat: изменил конфиг"
git push origin dev # Проверяю на dev.blog.ru
# Если всё ок
git checkout main
git merge dev
git push origin main
```
---
## Что дальше
Workflow выбран, окружения работают. Можно писать статьи.
Но есть ещё одна тема которую стоит разобрать - что делать когда что-то сломалось. Как диагностировать проблемы когда сайт вдруг начал отдавать 503, или SSL перестал работать, или webhook не срабатывает.
В следующей части покажу процесс диагностики на реальном примере - как я чинил `blog.ru` когда он внезапно стал недоступен из интернета.
---
**Рекомендация этой части:**
- Одна папка `~/projects/blog`
- Переключение веток через `git checkout`
- Все изменения через `dev` → merge в `main`
- Никогда не редактировать находясь на `main`