Знакомы ли вы с системой Git? Практическое руководство по системе контроля версий

Git
Oleksandr Vykhor
78
25-09-2026 15:40:29


Знакомы ли вы с системой Git? Практическое руководство по системе контроля версий

«Знакомы ли вы с Git?» — один из самых частых вопросов на собеседованиях разработчиков, и не зря. Сегодня Git используется почти в каждом программном проекте, от небольшого личного блога до ядра Linux. В этой статье разберём, что такое Git, как он устроен внутри, какими командами пользуются каждый день, как команды организуют с ним работу и что делать, если что-то пошло не так.

Что такое Git?

Git — это распределённая система контроля версий. Он записывает историю изменений проекта, позволяет вернуться к любому предыдущему состоянию, параллельно работать над несколькими задачами и объединять работу многих разработчиков.

Git создал Линус Торвальдс в 2005 году для разработки ядра Linux. Главными целями были скорость, надёжность и поддержка большой распределённой команды.

Централизованные и распределённые системы контроля версий

  • Централизованные системы (например, SVN) хранят историю на одном центральном сервере. Разработчики получают только текущую версию файлов, а большинство операций требует подключения к серверу.
  • Распределённые системы (Git, Mercurial) дают каждому разработчику полную копию репозитория со всей историей. Коммитить, смотреть историю, создавать ветки и сравнивать версии можно без интернета. Удалённый сервер вроде GitHub или GitLab — просто ещё одна копия, которая используется для обмена.

Также важно не путать Git и GitHub. Git — это инструмент, который работает на вашем компьютере. GitHub, GitLab и Bitbucket — это сервисы, которые хранят Git-репозитории и добавляют pull request'ы, код-ревью, CI/CD и трекер задач.

Как работает Git: ключевые понятия

Снимки, а не разницы

Каждый коммит в Git — это снимок всего проекта в определённый момент времени, плюс автор, дата, сообщение и ссылка на родительский коммит. Неизменённые файлы не копируются заново: Git просто ссылается на уже сохранённую версию. У каждого коммита есть уникальный идентификатор — хеш вроде a1b2c3d.

Три области

Чтобы понимать Git, нужно понимать, где находятся ваши изменения:

  1. Рабочая директория (working directory) — файлы, которые вы редактируете прямо сейчас.
  2. Индекс (staging area) — изменения, которые вы выбрали для следующего коммита с помощью git add.
  3. Репозиторий — сохранённая история коммитов в папке .git.

Индекс позволяет закоммитить только часть изменений — например, отделить исправление бага от рефакторинга, даже если вы сделали и то и другое в одном файле.

Ветки и HEAD

Ветка в Git — это просто лёгкий указатель на коммит. Создание ветки происходит мгновенно и почти ничего не стоит, поэтому разработчики создают отдельную ветку для каждой задачи или исправления. HEAD — указатель на ветку (или коммит), на которой вы сейчас находитесь.

Команды на каждый день

# Однократная настройка
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git config --global init.defaultBranch main

# Создать проект или скопировать существующий
git init
git clone git@github.com:user/project.git

# Посмотреть, что изменилось
git status
git diff            # изменения, ещё не добавленные в индекс
git diff --staged   # изменения, которые попадут в следующий коммит

# Сохранить изменения
git add app/models/user.rb
git commit -m "Add email validation to User"

# История
git log --oneline --graph --all

Работа с ветками

git switch -c feature/user-avatars   # создать ветку и переключиться на неё
git switch main                      # вернуться обратно
git branch                           # список локальных веток
git branch -d feature/user-avatars   # удалить слитую ветку

Старая команда git checkout делает то же самое и не только, но git switch (для веток) и git restore (для файлов) понятнее и безопаснее.

Работа с удалённым репозиторием

git remote -v                          # список удалённых репозиториев
git fetch                              # скачать изменения, не применяя их
git pull                               # fetch + merge (или rebase) в текущую ветку
git push -u origin feature/user-avatars  # опубликовать ветку

Merge или rebase

Перенести изменения из одной ветки в другую можно двумя способами:

  • Merge (git merge) объединяет ветки и создаёт коммит слияния. История остаётся ровно такой, какой была, но может стать запутанной.
  • Rebase (git rebase) переносит ваши коммиты поверх другой ветки, давая чистую линейную историю. Однако он переписывает коммиты, создавая новые хеши.
# Обновить свою ветку свежим main
git switch feature/user-avatars
git fetch origin
git rebase origin/main

# Или сделать merge
git merge origin/main

Золотое правило: не делайте rebase коммитов, на которых другие люди уже построили свою работу, например общей ветки main. Rebase своей локальной ветки задачи — нормальная практика.

Разрешение конфликтов

Конфликт возникает, когда две ветки меняют одни и те же строки одного файла. Git останавливается и помечает проблемное место:

<<<<<<< HEAD
  validates :email, presence: true
=======
  validates :email, presence: true, uniqueness: true
>>>>>>> feature/unique-emails

Вы редактируете файл, оставляя правильный вариант, удаляете маркеры, затем выполняете git add и продолжаете через git commit (при merge) или git rebase --continue (при rebase). Если всё слишком запуталось, git merge --abort или git rebase --abort вернёт всё в состояние до начала операции.

Отмена изменений

Умение исправлять ошибки — то, что отличает уверенного пользователя Git от новичка:

git restore config/routes.rb         # отменить неиндексированные изменения в файле
git restore --staged config/routes.rb  # убрать файл из индекса, сохранив изменения

git commit --amend                   # исправить последний коммит (сообщение или содержимое)

git reset --soft HEAD~1              # отменить последний коммит, изменения остаются в индексе
git reset --hard HEAD~1              # отменить последний коммит и УДАЛИТЬ изменения

git revert a1b2c3d                   # создать новый коммит, отменяющий a1b2c3d
  • Используйте git revert для коммитов, которые уже отправлены на сервер: он не переписывает историю, поэтому безопасен для общих веток.
  • Используйте git reset и --amend только для локальных коммитов, которых больше ни у кого нет.
  • Осторожно с --hard: незакоммиченные изменения будут потеряны.

И спасательный круг: git reflog показывает все места, где побывал HEAD, включая коммиты, «потерянные» после reset или неудачного rebase. Работу, которая хоть раз была закоммичена, почти всегда можно восстановить.

git reflog
git reset --hard HEAD@{2}   # вернуться к состоянию двумя перемещениями ранее

Полезные команды, которые стоит знать

  • git stash — временно убрать незаконченные изменения, например чтобы переключиться на срочный баг. Вернуть их можно через git stash pop.
  • git cherry-pick <hash> — скопировать конкретный коммит в текущую ветку.
  • git blame <file> — посмотреть, кто последним менял каждую строку и в каком коммите.
  • git bisect — бинарный поиск по истории, чтобы найти коммит, в котором появился баг.
  • git tag v1.2.0 — отметить релиз.
  • git rebase -i HEAD~3 — интерактивный rebase, чтобы объединить, переупорядочить или переименовать свои последние локальные коммиты перед созданием pull request'а.

Командные подходы к работе

  • GitHub Flow: main всегда готов к деплою; каждое изменение проходит через короткоживущую ветку задачи и pull request с код-ревью. Простой и популярный подход для веб-приложений.
  • Git Flow: отдельные ветки develop, release/* и hotfix/*. Подходит для продуктов с плановыми релизами, но тяжеловат для непрерывного деплоя.
  • Trunk-based development: все очень часто интегрируют небольшие изменения в main, используя feature flags. Хорошо работает при сильном автоматическом тестировании.

Git в Rails-проекте

Новое Rails-приложение уже содержит .gitignore. Важно не допустить попадания в репозиторий секретов и генерируемых файлов:

# .gitignore (ключевые строки)
/config/master.key
/config/credentials/*.key
/log/*
/tmp/*
/storage/*
/public/assets
/node_modules
.env
  • Никогда не коммитьте config/master.key и файлы .env. Зашифрованный credentials.yml.enc коммитить можно, а ключ нужно передавать на сервер отдельно.
  • Коммитьте Gemfile.lock и db/schema.rb, чтобы у всех разработчиков и серверов были одинаковые версии гемов и структура базы.
  • Держите миграцию и зависящий от неё код в одном коммите или pull request'е.

Если секрет попал в коммит по ошибке, недостаточно удалить файл новым коммитом: он останется в истории. Немедленно смените секрет, а затем при необходимости очистите историю.

Хорошие сообщения коммитов

Хорошая история коммитов — это документация для вас в будущем и для вашей команды:

  • Пишите короткую первую строку (примерно до 50 символов) в повелительном наклонении: «Add avatar upload», а не «Added avatars».
  • При необходимости добавьте пустую строку и подробное объяснение, почему было сделано изменение.
  • Каждый коммит — одно логическое изменение. Не смешивайте форматирование, рефакторинг и новую функциональность.
git commit -m "Fix N+1 query on articles index" -m "Preload authors and comments counts to cut page load from 40 to 3 queries."

Лучшие практики

  1. Коммитьте часто, пушьте регулярно. Небольшие коммиты проще ревьюить, откатывать и понимать.
  2. Работайте в ветках и сливайте их через pull request'ы с код-ревью.
  3. Делайте pull перед началом работы и держите свою ветку актуальной, чтобы избежать больших конфликтов.
  4. Не переписывайте общую историю и избегайте git push --force в общие ветки. Если нужно форс-пушнуть свою ветку, используйте --force-with-lease.
  5. Проверяйте изменения перед коммитом через git diff --staged.
  6. Не храните секреты в репозитории и настройте .gitignore с первого дня.
  7. Используйте SSH-ключи или токены для аутентификации в удалённых репозиториях.

Как ответить на вопрос «Знакомы ли вы с Git?» на собеседовании

Простого «да» недостаточно. Сильный ответ показывает, что вы понимаете концепции, а не только знаете несколько команд. Например: объясните, что Git — распределённая система контроля версий, опишите три области и ветки, расскажите о рабочем процессе в вашей команде (ветки задач, pull request'ы, код-ревью), объясните разницу между merge и rebase и приведите пример, как вы разрешили конфликт или восстановили потерянную работу через git reflog. Реальные примеры из собственного опыта всегда убедительнее определений.

Заключение

Git — базовый инструмент каждого разработчика. Он хранит историю проекта, позволяет безопасно экспериментировать в ветках и делает возможной командную работу. Изучите основные команды, разберитесь, как устроены коммиты, ветки и индекс, научитесь отменять ошибки и следуйте хорошим практикам для коммитов и секретов. Тогда Git перестанет пугать и станет надёжной страховкой для вашего кода.


Назад