Інтернет сповнений довідкових матеріалів про принципи роботи та архітектуру інструментарію розробника. Нам же цікавіші «історії використання» — максимально прості й послідовні кроки, які можна просто повторити на своєму проєкті. Нижче саме така історія: як поставити на проєкт систему контролю версій 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 | Зміни, внесені окремим комітом. |
Вам сподобався цей лайфхак? Напишіть нам, про що хочете дізнатися ще.
