Чи знайомі ви з системою Git? Практичний посібник із системи контролю версій

Чи знайомі ви з системою 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, треба розуміти, де перебувають ваші зміни:
- Робоча директорія (working directory) — файли, які ви редагуєте просто зараз.
- Індекс (staging area) — зміни, які ви обрали для наступного коміту за допомогою
git add. - Репозиторій — збережена історія комітів у папці
.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."
Найкращі практики
- Комітьте часто, пуште регулярно. Невеликі коміти простіше рев'ювити, відкочувати та розуміти.
- Працюйте в гілках і зливайте їх через pull request'и з код-рев'ю.
- Робіть pull перед початком роботи і тримайте свою гілку актуальною, щоб уникнути великих конфліктів.
- Не переписуйте спільну історію й уникайте
git push --forceу спільні гілки. Якщо треба форс-пушнути свою гілку, використовуйте--force-with-lease. - Перевіряйте зміни перед комітом через
git diff --staged. - Не зберігайте секрети в репозиторії й налаштуйте
.gitignoreз першого дня. - Використовуйте SSH-ключі або токени для автентифікації у віддалених репозиторіях.
Як відповісти на запитання «Чи знайомі ви з Git?» на співбесіді
Простого «так» недостатньо. Сильна відповідь показує, що ви розумієте концепції, а не лише знаєте кілька команд. Наприклад: поясніть, що Git — розподілена система контролю версій, опишіть три області та гілки, розкажіть про робочий процес у вашій команді (гілки задач, pull request'и, код-рев'ю), поясніть різницю між merge і rebase та наведіть приклад, як ви розв'язали конфлікт або відновили втрачену роботу через git reflog. Реальні приклади з власного досвіду завжди переконливіші за визначення.
Висновок
Git — базовий інструмент кожного розробника. Він зберігає історію проєкту, дозволяє безпечно експериментувати в гілках і робить можливою командну роботу. Вивчіть основні команди, розберіться, як влаштовані коміти, гілки та індекс, навчіться скасовувати помилки й дотримуйтеся добрих практик для комітів і секретів. Тоді Git перестане лякати й стане надійною страховкою для вашого коду.
Назад



