Материал

Git

1. Что такое Git и зачем он нужен?

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

Основные преимущества:

  • Хранение истории изменений
  • Возможность отката к любой версии
  • Параллельная работа над проектом
  • Резервное копирование кода

Состояния файлов

  • Untracked: Git не отслеживает файл
  • Tracked, unmodified: файл отслеживается и не отличается от текущего commit
  • Modified: Файл изменен, но изменения не добавлены в staging
  • Staged: Файл добавлен в staging area

Commit — это сохранённый snapshot проекта в истории, а не отдельное состояние path в выводе git status.

Ветвление (Branching)

Ветка — это независимая линия разработки. Ветки позволяют параллельно работать над разными задачами.

# Создание новой ветки
git branch feature-name

# Переключение на ветку
git checkout feature-name
# или
git switch feature-name

# Создание и переключение одной командой
git checkout -b feature-name

Один из вариантов модели ветвления

  • main — основная ветка
  • develop — ветка разработки
  • feature/* — ветки для новых функций
  • hotfix/* — ветки для срочных исправлений

Основные команды

git clone:

Клонирование репозитория с удаленного сервера на локальную машину. Это позволяет вам начать работу с существующим проектом.

git clone <URL репозитория>

git add:

Добавление изменений в индекс для подготовки к коммиту. Выборочное добавление файлов в индекс осуществляется с использованием этой команды.

# Добавить подходящие неигнорируемые изменения от текущего каталога вниз
git add .

# Добавить изменения по всему репозиторию, включая удаления
git add -A

# Добавить конкретный файл в индекс
git add <имя файла>

git commit:

Фиксация изменений в репозитории. Ваш код становится частью истории проекта после выполнения этой команды.

git commit -m "Ваш комментарий к коммиту"

git push:

Загрузка локальных изменений в удаленный репозиторий. Это необходимо, чтобы синхронизировать ваш локальный репозиторий с удаленным.

git push origin <название ветки>

git pull:

Получение изменений из удаленного репозитория и их интеграция в текущую ветку. После fetch Git использует merge, rebase или только fast-forward — в зависимости от флагов и конфигурации.

git pull origin <название ветки>

git fetch:

Получение изменений из удаленного репозитория без их автоматического слияния с текущей веткой.

git fetch origin

git merge:

Слияние веток в вашем репозитории. Обычно используется после завершения работы в новой функциональной ветке.

# Переключиться на целевую ветку
git checkout <целевая ветка>

# Слить изменения из другой ветки в целевую
git merge <ваша ветка>

git branch:

Отображение списка веток в вашем репозитории. Текущая активная ветка будет выделена.

# Показать все ветки
git branch

# Создать новую ветку
git branch <название ветки>

git checkout:

Переключение между ветками или восстановление файлов из определенного коммита.

# Переключиться на существующую ветку
git checkout <название ветки>

# Создать новую ветку и переключиться на нее
git checkout -b <название ветки>

git status:

Показать текущее состояние вашего рабочего каталога. Отображает измененные, добавленные и неотслеживаемые файлы.

git status

git stash:

Скрыть текущие изменения в рабочем каталоге, чтобы переключиться на другую ветку или выполнить другие операции. Позже можно вернуть эти изменения.

# Спрятать текущие изменения
git stash

# Добавить в stash также untracked-файлы
git stash -u

# Применить спрятанные изменения обратно
git stash apply

Еще команды, просто ознакомиться

git cherry-pick:

выбирает определенные коммиты по их хэшу и применяет их к текущей ветке.

git cherry-pick <хэш-коммита>

git init:

Эта команда используется для создания нового Git-репозитория. Выполняется один раз в начале проекта.

git init

git log:

Просмотр истории коммитов. Эта команда отображает список коммитов, их хэши, авторов, даты и комментарии.

git log

git remote:

Отображение списка удаленных репозиториев, связанных с вашим локальным репозиторием.

# Отобразить список удаленных репозиториев
git remote -v

git reset:

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

# Отменить последний локальный commit, оставив его изменения в индексе
git reset --soft HEAD~1

# Убрать конкретный path из индекса, сохранив файл в рабочем каталоге
git restore --staged <путь>

# Удалить последний локальный commit и tracked-изменения — операция необратима без reflog/backup
git reset --hard HEAD~1

Практические сценарии использования

Примеры сценариев работы с вашим проектом

Начало работы с новым проектом

# 1. Создаем новый проект на GitHub
# 2. Клонируем его локально
git clone <https://github.com/username/project.git>

# 3. Создаем новую ветку для работы
git checkout -b feature/registration

# 4. Работаем над кодом...

# 5. Добавляем изменения и создаем коммит
git add .
git commit -m "feat: добавлена форма регистрации"

# 6. Отправляем изменения на GitHub
git push origin feature/registration

Ежедневная работа с существующим проектом

# 1. Получаем последние изменения из main
git checkout main
git pull origin main

# 2. Создаем новую ветку для задачи
git checkout -b fix/login-bug

# 3. Работаем над задачей...

# 4. Проверяем какие файлы изменились
git status

# 5. Смотрим изменения в коде
git diff

# 6. Добавляем и коммитим изменения
git add .
git commit -m "fix: исправлена ошибка авторизации"

# 7. Получаем последние изменения из main
git checkout main
git pull origin main

# 8. Возвращаемся в свою ветку и обновляем её
git checkout fix/login-bug
git rebase main

# 9. Отправляем изменения
git push origin fix/login-bug

Работа с конфликтами

# 1. При возникновении конфликта при merge/rebase
# Git отметит конфликтные файлы

# 2. Открываем конфликтный файл
# Видим примерно такое:
<<<<<<< HEAD
const greeting = "Hello";
=======
const greeting = "Hi";
>>>>>>> feature/greeting

# 3. Выбираем нужный вариант или объединяем их
const greeting = "Hello";

# 4. Добавляем исправленный файл
git add .

# 5. Если это был rebase
git rebase --continue
# Если это был merge
git commit -m "fix: resolve merge conflicts"

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

# Отмена незакоммиченных изменений в файле (данные будут потеряны)
git restore filename.js

# Убрать файл из staging, сохранив изменения
git restore --staged filename.js

# Отмена последнего НЕОПУБЛИКОВАННОГО коммита с сохранением изменений в staging
git reset --soft HEAD~1

# Удаление последнего НЕОПУБЛИКОВАННОГО коммита и tracked-изменений
git reset --hard HEAD~1

# Для уже опубликованного commit безопаснее создать обратный commit
git revert <commit>

Code Review процесс

  1. Создаете ветку для задачи
  2. Делаете изменения и push
  3. Создаете Pull Request (PR) на GitHub
  4. Получаете комментарии от коллег
  5. Вносите правки (если нужно)
  6. После апрува — мержите в основную ветку
# Внесение правок в существующий PR
git add .
git commit -m "fix: правки по ревью"
git push origin feature/my-feature

Совместная работа над веткой

# Если над веткой работает несколько человек
git pull --rebase origin feature/shared-feature
git push origin feature/shared-feature

Забыли добавить файл в коммит

git add forgotten-file.js
git commit --amend --no-edit

--amend создаёт новый commit ID. Не переписывайте таким способом общую ветку без согласованной политики команды.

Нужно временно переключиться на другую задачу

# Сохраняем текущие изменения
git stash

# Работаем над срочной задачей
git checkout hotfix/urgent-bug

# Возвращаемся к сохраненным изменениям
git checkout feature/original-task
git stash pop

Случайно закоммитили в main

Этот рецепт подходит только для локального, ещё не опубликованного commit. Если commit уже отправлен в общую ветку, используйте git revert.

# Создаем новую ветку с текущим состоянием
git branch feature/correct-branch

# Возвращаем main в исходное состояние
git reset --hard HEAD~1

# Переключаемся на правильную ветку
git checkout feature/correct-branch

Что такое GitFlow?

Gitflow - это методология ветвления и управления версиями в Git, предложенная Vincent Driessen. Gitflow предлагает стройный и формализованный способ организации работы с ветками в репозитории Git для команд разработчиков. Основной идеей Gitflow является использование различных типов веток для отделения различных этапов разработки и релизов.

Основные компоненты Gitflow включают следующие типы веток:

  1. master/main: Основная ветка, содержащая стабильный, готовый к выпуску код. Все релизы и функциональные улучшения, завершившиеся успешно, вливаются в эту ветку.
  2. develop: Ветка, содержащая код в разработке. Это место, где сливаются все фичи и исправления, чтобы провести тестирование перед интеграцией в master.
  3. feature: Ветки, создаваемые для разработки новой функциональности или добавления нового компонента. После завершения работы над фичей она сливается обратно в develop.
  4. release: Ветки, создаваемые для подготовки к выпуску новой версии. Здесь выполняются финальные тесты, вносятся последние правки и, по завершении, вливаются в master, а также могут быть влиты обратно в develop.
  5. hotfix: Ветки, создаваемые для быстрого исправления критических ошибок в текущей версии продукта, обнаруженных после ее выпуска. После завершения работы hotfix сливается как в master, так и в develop. Пример для реализации фичи:
main(tag: 0.1.0)
=> feature/mw-1234
=> dev/mw-1234/fname
=> feature/mw-1234
=> dev
=> release/0.1.1
=> master(tag: 0.1.1)

Пример хотфикса:

main(tag: 0.1.1)
=> hotfix/error-123
=> main (tag: 0.1.2)


SemVer: MAJOR.MINOR.PATCH
MAJOR — несовместимые изменения публичного API
MINOR — новая обратно совместимая функциональность
PATCH — обратно совместимые исправления ошибок

1.4.5 -> 1.4.6  # patch
1.4.5 -> 1.5.0  # minor
1.4.5 -> 2.0.0  # major

Feature development

Иллюстрация к материалу «Git»

Release development

Иллюстрация к материалу «Git»

Что могут спросить (теория)

git fetch vs git pull :

Команда git pull сначала выполняет fetch, а затем интегрирует выбранную remote branch. Способ интеграции зависит от флагов и конфигурации: merge, rebase или только fast-forward. Вот их основные отличия:

  1. git fetch:
  • Действие: Извлекает (получает) изменения из удаленного репозитория в ваш локальный репозиторий, но не выполняет автоматического слияния с текущей веткой.
  • Влияние на рабочий каталог: Не влияет на ваш рабочий каталог или индекс - ваши текущие изменения останутся нетронутыми.
  • Применение: Часто используется, когда вы хотите увидеть, какие изменения были внесены в удаленном репозитории, перед тем как решить, сливать их или нет.
git fetch origin
  1. git pull:
  • Действие: Извлекает изменения и интегрирует их в текущую ветку согласно --ff-only, --rebase, --no-rebase или настройкам Git.
  • Влияние на рабочий каталог: Может внести изменения в ваш рабочий каталог и индекс в случае автоматического слияния.
  • Применение: Используется, когда вы хотите получить изменения из удаленного репозитория и автоматически объединить их с вашей текущей веткой.
git pull origin <название ветки>

Коротко: git fetch только обновляет remote-tracking refs, а git pull после этого ещё интегрирует выбранную ветку.

Как добавить изменения в индекс перед коммитом?

git add . // Или конкретный файл вместо “.”

Как создать новую ветку в Git?

git checkout -b branch_name

Как выполнить коммит в Git?

git commit -m 'message'

git merge vs git rebase

  • git merge: Объединяет истории. При fast-forward Git только передвигает ref; отдельный merge commit появляется при non-fast-forward merge или с --no-ff.
  • git rebase: Переносит коммиты из одной ветки в другую, создавая новые коммиты. История коммитов становится линейной и более чистой, но может вызвать конфликты. Когда использовать:
  • Используйте git merge, когда важна отдельная история изменений веток.
  • Используйте git rebase, чтобы сделать историю коммитов более линейной и читаемой.

Официальные источники

Вопросы на собеседовании: как построить честный ответ

Используйте эти пункты как план ответа и адаптируйте их только под реальный опыт. Командный Git-flow не универсален: важно точно назвать правила конкретного проекта и свою роль в них.

Как у вас была устроена разработка с точки зрения GIT?

Опишите один реальный путь изменения от задачи до production:

  1. От какой ветки создавали рабочую ветку и как её называли.
  2. Как часто делали commits и отправляли ветку в remote.
  3. Куда открывали pull/merge request, кто проводил review и какие проверки запускал CI.
  4. Использовали merge, squash или rebase и почему.
  5. Кто выполнял merge, как создавались tags/releases и как исправляли проблемы после выпуска.

Если в проекте использовались только main и короткоживущие feature-ветки, так и скажите. Не добавляйте develop, release-ветки или Gitflow, если их не было.

Как лично ты пользовался гитом?

Перечислите операции, которые выполняли самостоятельно: создание и переключение веток, просмотр diff/status/log, выборочное добавление файлов, commit, pull/fetch, разрешение конфликтов, push и обновление pull request. Нормально честно сказать, что основную работу делали через PyCharm, а в терминале использовали базовые команды. Если не применяли rebase, cherry-pick, bisect или восстановление через reflog, не включайте их в свой опыт — можно отдельно сказать, что знакомы с назначением теоретически.