Перейти к содержимому

11. GitHub/GitLab workflow

![Иллюстрация к уроку](/lessons/git-github-workflow.png)
Этот урок посвящен workflow, то есть рабочему процессу, который обычно используется при командной разработке с использованием Git и платформ вроде GitHub или GitLab. Мы рассмотрим, как эффективно взаимодействовать с репозиторием, чтобы избежать конфликтов и поддерживать чистоту кодовой базы.
## Что такое GitHub/GitLab workflow?
GitHub/GitLab workflow – это набор практик, которые команды используют для совместной работы над проектом. Он основан на ветках (branches), запросах на слияние (pull requests/merge requests) и code review. Главная цель – обеспечить плавную интеграцию изменений и избежать проблем, связанных с параллельной разработкой.
## Основные шаги workflow
1. **Создание ветки (branching):** Для каждой новой фичи, исправления бага или эксперимента создается отдельная ветка от основной ветки (обычно `main` или `master`).
```bash
git checkout -b feature/new-feature

Эта команда создаст и переключит вас на новую ветку с именем feature/new-feature.

  1. Разработка и коммиты (development & commits): В этой ветке вы пишете код, тестируете его и делаете коммиты.

    Окно терминала
    git add .
    git commit -m "Implement new feature"

    Важно писать понятные и информативные сообщения к коммитам.

  2. Отправка ветки на удаленный репозиторий (push): После завершения работы над фичей, ветку нужно отправить на GitHub/GitLab.

    Окно терминала
    git push origin feature/new-feature
  3. Создание запроса на слияние (pull request/merge request): На GitHub/GitLab создается запрос на слияние вашей ветки с основной.

  4. Code review: Другие разработчики просматривают ваш код, оставляют комментарии и предлагают улучшения.

  5. Внесение изменений (addressing feedback): Вы вносите необходимые изменения на основе code review и снова делаете коммиты.

    Окно терминала
    git add .
    git commit -m "Address feedback from code review"
    git push origin feature/new-feature
  6. Слияние (merging): После одобрения кода, запрос на слияние принимается, и ваш код объединяется с основной веткой.

    После слияния, локальную ветку можно удалить:

    Окно терминала
    git checkout main
    git pull origin main
    git branch -d feature/new-feature
    git push origin --delete feature/new-feature

Представьте, что вы разрабатываете веб-сайт. Один разработчик работает над новой формой обратной связи, а другой – над улучшением производительности. Каждый создает свою ветку, работает независимо, а затем отправляет запросы на слияние. Code review позволяет выявить ошибки и улучшить качество кода до того, как он попадет в основную ветку. Этот workflow применяется в разработке React, Vue, Angular, Django, Rails и других популярных фреймворков и библиотек. Команда, работающая над React, может использовать этот workflow для добавления новых компонентов или исправления ошибок в существующих.

  • Используйте ветки для каждой новой фичи или исправления.
  • Пишите информативные сообщения к коммитам.
  • Регулярно отправляйте свои изменения на удаленный репозиторий.
  • Внимательно относитесь к code review и вносите необходимые изменения.
  • Удаляйте ветки после слияния.
  • Регулярно обновляйте свою локальную основную ветку (main/master) с удаленного репозитория.
Окно терминала
git checkout main
git pull origin main
## Интерактивный пример
Жизненный цикл Pull Request:
<Playground client:load
template="vite-react"
files={{
"/App.jsx": `import { useState } from "react";
const steps = [
"Create feature branch",
"Write code & commit",
"Push to remote",
"Open Pull Request",
"CI/CD checks run",
"Code review by team",
"Address review comments",
"Approve PR",
"Merge to main",
"Delete feature branch",
];
export default function App() {
const [current, setCurrent] = useState(-1);
const next = () => setCurrent((c) => c >= steps.length - 1 ? -1 : c + 1);
const getStatus = (i) => {
if (current === -1) return "idle";
if (i < current) return "done";
if (i === current) return "active";
return "idle";
};
const colors = { idle: "#334155", done: "#22c55e", active: "#eab308" };
const bgs = { idle: "#1e293b", done: "#1e293b", active: "#1c1917" };
return (
<div style={{ fontFamily: "monospace", background: "#0f172a", color: "#e2e8f0", padding: 16, minHeight: "100vh" }}>
<h3 style={{ color: "#818cf8", marginBottom: 12 }}>GitHub PR Workflow</h3>
<div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
{steps.map((s, i) => {
const status = getStatus(i);
return (
<div key={i} style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 14px", background: bgs[status], borderRadius: 8, borderLeft: "3px solid " + colors[status], fontSize: 12, transition: "all .3s" }}>
<div style={{ width: 22, height: 22, borderRadius: "50%", background: colors[status], display: "flex", alignItems: "center", justifyContent: "center", fontSize: 10, fontWeight: 700, color: status === "idle" ? "#e2e8f0" : "#0f172a" }}>{i + 1}</div>
<span>{s}</span>
</div>
);
})}
</div>
<button onClick={next} style={{ marginTop: 10, padding: "7px 16px", borderRadius: 6, border: "none", cursor: "pointer", fontWeight: 700, fontSize: 12, background: "#6366f1", color: "#fff" }}>
{current >= steps.length - 1 ? "Reset" : "Next Step"}
</button>
</div>
);
}
`
}}
/>