Интернет полон справочных материалов о принципах работы и архитектуре инструментария разработчика. Нам же интереснее «истории использования» — максимально простые и последовательные шаги, которые можно просто повторить на своём проекте. Ниже как раз такая история: как поставить на проект систему контроля версий Git. Ничего лишнего.
Зачем ещё одна инструкция про Git
Теории про Git написано много, и она по большей части прекрасная. Проблема в другом: когда систему контроля версий нужно поднять на реальном проекте сегодня, разработчику нужна не архитектура, а последовательность действий. Поэтому в нашей базе знаний мы публикуем именно инструкции — от первой команды до устоявшегося рабочего процесса.
Мы публикуем в нашей базе знаний «истории использования» — это максимально простые и последовательные инструкции.Технический директор
Схема обмена
Чтобы спокойно работать в режиме прямых коммитов командами git push origin master и git pull origin master, используем схему с двоичным репозиторием — bare repository (центральным).

Каждая часть схемы может располагаться как на разных серверах, так и на двух или вообще целиком на одном сервере. Всё зависит от путей к удалённым веткам.


PRODUCTION
Боевой код проекта. Именно здесь мы создаём .gitignore, делаем git init и отсюда впервые загружаем код в центральный репозиторий.
Bare repository
Двоичный (центральный) репозиторий без рабочей копии. Точка обмена: сюда отправляют изменения и отсюда их забирают.
DEV
Клон центрального репозитория. Здесь ведётся работа над задачами — каждая в своей ветке.
Размещение
Разные серверы, два сервера или один — схема от этого не меняется. Меняются только пути к удалённым веткам.
Создание DEV-репозитория
- Создаём .gitignore на PRODUCTION. В корне проекта создаём файл .gitignore и вписываем в него всё, что не относится к коду, который будет меняться, и по смыслу не должно попадать под версионный контроль.
- Инициализируем репозиторий. После этого выполняем git init.
- Делаем bare-версию. Идём на сервер или в каталог, где будет располагаться двоичный репозиторий, и создаём там bare-версию: git init --bare.
- Фиксируем путь к репозиторию. Смотрим, где мы оказались: pwd выдаёт, например, /var/www/sven/data/www/github.
- Ставим удалённый алиас. Возвращаемся на PRODUCTION и прописываем bare repository как origin: git remote add origin ssh://sven@o.aniart.com.ua/var/www/sven/data/www/github.
- Убеждаемся, что всё в порядке. Команда git remote -v должна показать этот же адрес дважды — для fetch и для push.
- Загружаем код. С PRODUCTION отправляем весь код в bare repository: git push origin master.
- Клонируем DEV. Идём на сервер (в каталог), где будет DEV, и клонируем из bare-репозитория всё только что загруженное: git clone ssh://sven@o.aniart.com.ua/var/www/sven/data/www/github. Это сразу настраивает алиас origin.
Файл .gitignore для примера с проекта выглядит так:
- download/
- images/
- song_1.mp3/
- video/
Кто хочет, может сделать то же самое последовательно, без клонирования: git init, далее git remote add origin ssh://sven@o.aniart.com.ua/var/www/sven/data/www/github и git pull origin master. В документации Git всё это описано очень подробно.

Полезные команды и ключи
| Команда | Что делает |
|---|---|
| git remote -v | Показывает, какие алиасы настроены — отдельными строками для fetch и для push. |
| git rm --cached -r images | Убирает из версионного контроля то, что попало туда по ошибке. Прежде всего это касается картинок и каталога download. |
| git rm --cached -r song_1.mp3 | То же самое для отдельного большого файла. |
| git pull --allow-unrelated-histories dev master | Выручает, если у репозиториев нет общего коммита-предка. |
| git checkout -b serverfix origin/serverfix | Ставит удалённую ветку на отслеживание локальной — экономит кучу времени на постоянное прописывание алиасов и веток. |
| git push origin serverfix:SVEN-5 | «Возьми мой serverfix и сделай его удалённым SVEN-5». |
Получение локальной ветки с помощью git checkout из удалённой ветки автоматически создаёт то, что называется отслеживаемой веткой. Отслеживаемые ветки — это локальные ветки, напрямую связанные с удалённой. Если, находясь на отслеживаемой ветке, вы наберёте git push, Git уже будет знать, на какой сервер и в какую ветку отправлять изменения. Точно так же выполнение git pull на одной из таких веток сначала получает все удалённые ссылки, а затем автоматически делает слияние с соответствующей удалённой веткой.
Формат git push origin serverfix:SVEN-5 можно использовать, чтобы отправить локальную ветку в удалённую ветку с другим именем: ваша локальная serverfix попадёт в ветку SVEN-5 удалённого проекта.
Порядок работы с DEV
Для каждого задания или отдельного таска работаем по одинаковому циклу.
- Делаем ветку. git checkout -b SVEN-5 — дальше вся работа идёт только в ней.
- Работаем. Пишем код, добавляем нужные файлы.
- Коммитим изменения. git add ., затем git commit -am "суть работы".
- Сливаем в master. git checkout master, далее git merge SVEN-5.
- Отправляем в центральный репозиторий. Когда получено разрешение выкладывать на PRODUCTION, выполняем git push origin master. Изменения забираем из центрального на master.
- Убираем за собой. Старые ветки можно удалять: git branch -d SVEN-5.
- git branch --merged — показывает, какие ветки уже слиты и какие можно удалять (все, кроме отмеченной звёздочкой текущей).
- git branch --no-merged — показывает, какие ветки НЕ слиты и содержат изменения.
Фиксация изменений и работа с индексом
Стандартная фиксация изменений
- Вариант №1. Добавить изменённые файлы в индекс перед коммитом: git add filename1 filename2, далее git commit.
- Вариант №2. Добавить все файлы — изменённые, новые, удалённые: git add ., далее git commit.
Если что-то попало в индекс по ошибке
Если что-то пошло не так, до фиксации (commit) из индекса всегда можно убрать случайно добавленные туда файлы.
- git reset filename1 — убрать из индекса конкретный файл.
- git rm --cached filename1 — то же самое другим способом.
- git reset HEAD — сбросить весь индекс полностью.
Как вернуть файлы и отменить изменения
Восстановить файл из одного из предыдущих коммитов
Понадобится идентификатор коммита и имя файла: git checkout id-коммита имя-файла. На практике это выглядит так: git checkout 2378d5ad6e3d5fc87df858678c226d9fc9c47c66 temp.tmp. Где взять идентификатор — смотрите git log.
Убрать из индекса файл, которого там быть не должно
- Вносим файл в .gitignore. Чтобы он больше не попадал под версионный контроль.
- Исключаем из индекса. git rm --cached filename.
- Коммитим. Без коммита изменение не зафиксируется.
Как вернуть изменённый файл назад
- git reset --soft id-commit — уничтожить в ветке коммит, но оставить индекс и дерево файлов нетронутыми.
- git reset --hard id-commit — уничтожить коммит, индекс и файлы до состояния указанного коммита.
Ветки, теги и временное хранилище
Работа с ветками
- git branch new-branch — создаст новую ветку new-branch на основе текущей.
- git checkout branch — переключение между ветками.
- git merge — слияние веток с разрешением возможных конфликтов.
Теги
- git tag stable-1 — создать «легковесный» тег, связанный с последним коммитом. Если тег уже есть, ещё один создан не будет.
- git tag -d stable-2 — удалить тег.
- git tag -l — перечислить теги.
Временно «спрятать» изменения
Часто возникает такая ситуация: пока вы работаете над частью своего проекта, всё находится в беспорядочном состоянии, а вам нужно переключить ветки, чтобы немного поработать над чем-то другим. Проблема в том, что вы не хотите делать коммит с наполовину доделанной работой только для того, чтобы позже можно было вернуться в это же состояние. Ответ на эту проблему — команда git stash.
- git stash — изменения больше не видны Git.
- git stash list — посмотреть список спрятанных работ: stash@{0}: WIP on master: 049d078 added the index file, stash@{1}: WIP on master: c264051... Revert "added file_size", stash@{2}: WIP on master: 21d80a5... added number to log.
- git stash apply — восстановить последнюю спрятанную работу.
- git stash apply stash@{2} — применить одну из более старых работ, указав её имя.
История коммитов и аналитика
Информацию об истории коммитов можно получать с разной детализацией.
| Команда | Детализация |
|---|---|
| git log | Базовая статистика по коммитам. |
| git log --stat | Подробно по каждому коммиту. |
| git log --summary | Сводка по истории. |
| git log -p | Подробно по каждому файлу. |
| git diff filename | Изменения по конкретному файлу. |
| git diff --cached | Изменения, внесённые в индекс. |
| git show | Изменения, внесённые отдельным коммитом. |
Вам понравился этот лайфхак? Напишите нам, о чём хотите узнать ещё.
