Замість вступу
Привіт тобі, майбутній Senior Software Engineer. Сьогодні поговоримо про систему контролю версій, а саме про Git (читається як ГІТ, а не ДЖІТ, як могло б здатися з граматики англійської мови). Так-так, я знаю, що є ще й Mercurial, SVN… Але будемо відвертими: їхній час уже минув, і витрачати ваш дорогоцінний час на них не збираюся. Щоб ви розуміли важливість знання гіта в наш час, скажу так: без знання/розуміння цього робити вам у програмуванні нічого. Але краса в тому, що для постійної роботи не потрібно пам'ятати всі команди та можливості. Потрібно знати набір команд, які допоможуть розуміти, що відбувається.Основи Git
Git це розподілена система контролю версій нашого коду. Для чого вона нам? Для розподілених команд потрібна система управління роботи. Потрібно, щоб відстежувати зміни, які відбуваються з часом. Тобто, крок за кроком ми бачимо, які файли змінабося і як. Особливо це важливо, коли аналізуєш, що було зроблено в рамках одного завдання: це дає можливість повертатись назад. Уявімо ситуацію: був працюючий код, все в ньому було добре, але ми вирішабо щось покращити, там підправити, там підправити. Все нічого, але таке покращення поламало половину функціоналу, унеможливило роботу. І що далі? Без Гіта треба було б годинами сидіти і згадувати, як усе було спочатку. А так ми просто відкочуємось на коміт назад — і все. Або що робити, якщо є два розробники, які роблять одночасно свої зміни у коді? Без Гіта це виглядає так: вони скопіювали код із оригіналу, зробабо що потрібно. Настає момент, і обидва хочуть додати свої зміни до головної папки. І що робити в цій ситуації?.. Я навіть не беруся оцінити час, щоб зробити цю роботу. Таких проблем зовсім не буде, якщо користуватися Гітом.Установка Git
Встановимо гіт на комп'ютер. Я розумію, що всі різні OS, тому постараюся описати для кількох випадків.Установка для Windows
Як завжди, потрібно завантажити exe файл і запустити його. Тут все просто: тиснемо на перше посилання гугла , встановлюємо і все. Для роботи будемо використовувати bash консоль, яку вони надають. Щоб працювати у віндоусі, потрібно запустити Git Bash. Ось як він виглядає в меню запуску: І це вже консоль, в якій можна працювати. Щоб не переходити щоразу в папку з проектом, щоб там відкрити гіт, можна в папці правою кнопкою миші відкрити консоль із потрібним нам шляхом:Установка для Linux
Зазвичай git вже встановлений і є в дистрибутивах лінуксу, тому що це інструмент, спочатку написаний для розробки лінуксу ядра. Але бувають ситуації, коли його нема. Щоб перевірити це, необхідно відкрити термінал і прописати: git --version. Якщо буде зрозуміла відповідь, нічого встановлювати не потрібно. Відкриваємо термінал та встановлюємо. Я працюю на Ubuntu, тому можу сказати, що писати для неї: sudo apt-get install git. І все: тепер у будь-якому терміналі можна користуватися гітом.Встановлення на macOS
Тут також спочатку потрібно перевірити, чи є вже гіт (дивися вище, як на лінуксі). Якщо все ж таки ні, найпростіший шлях — це завантажити звідси останню версію. Якщо встановлений XCode, то гіт вже точно буде автоматично встановлений.Налаштування гіта
Гіта має налаштування користувача, від якого йтиме робота. Це розумна і необхідна річ, оскільки коли створюється комміт, гіт бере саме цю інформацію для поля Author. Щоб налаштувати ім'я користувача та пароль для всіх проектів, потрібно прописати такі команди:
git config --global user.name ”Ivan Ivanov”
git config --global user.email ivan.ivanov@gmail.com
Якщо є необхідність для конкретного проекту поміняти автора (для особистого проекту, наприклад), можна прибрати --global, і так вийде:
git config user.name ”Ivan Ivanov”
git config user.email ivan.ivanov@gmail.com
Трохи теорії…
Щоб бути в темі, бажано додати до свого звернення кілька нових слів і дій… А то говорити нема про що. Звичайно це якийсь жаргон і калька з англійської, тому я додаватиму значення англійською. Які слова та дії?- гіт репозиторій (git repository);
- коміт (commit);
- гілка (branch);
- смерджити (merge);
- конфлікти (conflicts);
- спулити (pull);
- запушити (push);
- як ігнорувати якісь файли (.gitignore)
Стану в Гіт
У Гіта є кілька станів, які потрібно зрозуміти та запам'ятати:- невідслідковується (untracked);
- змінене (modified);
- підготовлений (staged);
- закомічене (committed).
Як це розуміти?
Це стани, в яких знаходяться файли нашого коду. Тобто їхній життєвий шлях зазвичай виглядає так:- Файл, який створений і не доданий до репозиторію, буде в змозі untracked.
- Робимо зміни у файлух, які вже додані в гіт репозиторій – перебувають у стані modified.
- З тих файлів, які ми змінабо, вибираємо тільки ті (або всі), які нам потрібні (наприклад, скомпільовані класи нам не потрібні), і ці класи зі змінами потрапляють у стан staged.
- З заготовлених файлів зі стану staged створюється коміт і перетворюється на гіт репозиторій. Після цього staged стан – порожній. А ось modified ще може щось утримувати.
Що таке коміт
Коміт - це основний об'єкт в управлінні контролю версій. Він містить усі зміни під час цього комміту. Комміти пов'язані між собою як однозв'язковий список. А саме: Є перший коміт. Коли створюється другий коміт, він (другий) знає, що йде після першого. І в такий спосіб можна відстежити інформацію. Також комміт має ще свою інформацію, так звані метадані:- унікальний ідентифікатор комміту, яким можна його знайти;
- ім'я автора комміту, який створив його;
- дата створення комміту;
- коментар, який визначає, що було зроблено під час цього комміту.
Що таке гілка
Гілка – це покажчик якогось комміту. Так як коміт знає, який коміт був до нього, коли гілка вказує на якийсь коміт, до неї належать і всі попередні. Виходячи з цього можна сказати, що гілок, що вказують на той самий коміт, може бути скільки завгодно багато. Робота відбувається у гілках, тому коли створюється новий коміт, гілка переносить свій покажчик більш новий комміт.Початок роботи з Гітом
Можна працювати і лише з локальним репозиторієм, і з віддаленим. Для відпрацювання необхідних команд можна скористатися лише локальним репозиторієм. Він зберігає всю інформацію лише локально у проекті в папці .git. Якщо говорити про віддалений, то вся інформація зберігається десь на віддаленому сервері: локально зберігається лише копія проекту, зміни якої можна запустити (git push) у віддалений репозиторій. Тут і далі обговорюватимемо роботу з гітом у консолі. Звичайно, можна користуватися якимись графічними рішеннями (наприклад, Intellij IDEA), але спершу потрібно розібратися, які команди відбуваються і що вони означають.Робота з гітом у локальному репозиторії
Далі я пропоную вам зробити всі ті кроки, які зробив я, коли читатимете статтю. Це покращить ваше розуміння та засвоєння матеріалу. Так що приємного апетиту:) Щоб створити локальний репозиторій, потрібно написати:
git init
Після цього буде створено папку .git у тому місці, де знаходиться консоль. .git - це папка, яка зберігає всю інформацію про гіт репозиторії. Її видаляти не потрібно ;) Далі, додаються файли в цей проект, і їхній стан стає Untracked. Щоб подивитися, який статус роботи на даний момент пишемо:
git status
Ми знаходимося в master гілці, і поки ми не перейдемо в іншу, то все й залишиться. Таким чином видно, які файли змінені, але ще не додані до стану staged. Щоб додати їх до стану staged, потрібно написати git add. Тут може бути кілька варіантів, наприклад:
- git add -A - додати всі файли зі стану в staged;
- git add. — додати всі файли з цієї папки та всі внутрішні. По суті те саме, що й попереднє;
- git add <ім'я файлу> — додає лише конкретний файл. Тут можна скористатися регулярними виразами, щоб додавати за якимось шаблоном. Наприклад, git add *.java: це означає, що потрібно додати лише файли з розширенням java.
git add *.txt
Щоб перевірити статус, використовуємо вже відому нам команду:
git status
Звідси видно, що регулярне вираз відпрацювало вірно, і тепер test_resource.txt знаходиться в стані staged. І, нарешті, останній етап (при локальному репозиторії, з віддаленим буде ще один);
git commit -m “all txt files were added to the project”
Далі є чудова команда, щоб подивитися на історію коммітів у гілці. Скористаємося нею:
git log
Тут уже видно, що з'явився наш перший коміт із текстом, який ми передали. Дуже важливо зрозуміти, що текст, який ми передаємо, має максимально точно визначати те, що було зроблено за цей коміт. Це в майбутньому допомагатиме багато разів. Допитливий читач, який ще не заснув, може сказати: а що сталося із файлом GitTest.java? Зараз дізнаємося, використовуємо для цього:
git status
Як бачимо, він так і залишився в змозі untracked і чекає свого часу. А може, ми зовсім не хочемо його додавати в проект? Буває й таке. Далі, щоб стало цікавіше, спробуємо змінити текстовий файл test_resource.txt. Додамо туди якийсь текст і перевіримо стан:
git status
Тут добре видно різницю між двома станами — untracked і modified. GitTest.java знаходиться в стані untracked, а test_resource.txt знаходиться в modified. Тепер, коли вже є файли в стані modified, ми можемо подивитися на зміни, які були зроблені над ними. Зробити це можна за допомогою команди:
git diff
Тобто тут добре видно, що я додав до нашого текстового файлу hello world! Додаємо зміни в текстовому файлі та комітімо:
git add test_resource.txt
git commit -m “added hello word! to test_resource.txt”
Щоб подивитися на всі комміти, пишемо:
git log
Як бачимо, вже є два коміти. Так само додаємо і GitTest.java. Тепер без коментарів, просто команди:
git add GitTest.java
git commit -m “added GitTest.java”
git status
Робота з .gitignore
Ясно, що ми хочемо зберігати лише вихідний код і нічого іншого у репозиторії. А що ще може бути? Як мінімум, скомпіловані класи та/або файли, які створюють середовища розробки. Щоб гіт їх ігнорував, є спеціальний файл, який потрібно створити. Робимо це: створюємо файл у корені проекту під назвою .gitignore, і в цьому файлі кожен рядок буде шаблоном для ігнорування. У цьому прикладі гіт ігнор виглядатиме так:
```
*.class
target/
*.iml
.idea/
```
Дивимося тепер:
- перший рядок – це ігнорування всіх файлів з розширенням .class;
- другий рядок – це ігнорування папки target та всього, що вона містить;
- третій рядок – це ігнорування всіх файлів з розширенням .iml;
- четвертий рядок – це ігнорування папки .idea.
git status
Ясно, що ми не хочемо випадково (якщо використовувати git add -A) додати скомпільований клас в проект. Для цього створюємо .gitignore файл і додаємо все, що описувалося раніше: Тепер додамо новим комітом гіт ігнор у проект:
git add .gitignore
git commit -m “added .gitignore file”
І тепер момент істини: у нас є в untracked стані скомпільований клас GitTest.class, який ми не хотіли додавати в гіт репозиторій. Ось тут і повинен заробити гіт ігнор:
git status
Все чисто) Гіт ігнору +1)
Робота з гілками та іже з ним
Зрозуміло, працювати в одній гілці незручно одному і неможливо, коли в команді більше однієї людини. І тому існує розгалуження. Як я вже казав, гілка – це просто рухливий покажчик на комміти. У цій частині розглянемо роботу в різних гілках: як смердити зміни однієї гілки в іншу, які можуть виникнути конфлікти та багато іншого. Щоб подивитися список усіх гілок у репозиторії та зрозуміти, на якій перебуваєш, потрібно написати:
git branch -a
Видно, що у нас тільки одна гілка master, і зірочка перед нею каже, що ми на ній. До речі, щоб дізнатися, на якій гілці ми знаходимося, можна скористатися і перевіркою статусу (git status). Далі є кілька варіантів створення гілок (може їх і більше, я використовую ці):
- створити нову гілку на основі тієї, на якій перебуваємо (99% випадків);
- створити гілку з урахуванням конкретного комміту (1%).
Створюємо гілку на основі конкретного комміту
Спиратимемося на унікальний ідентифікатор коміту. Щоб знайти його, напишемо:
git log
Я виділив коміт із коментарем “added hello world…”. У нього унікальний ідентифікатор - "6c44e53d06228f888f2f454d3cb8c1c976dd73f8". Я хочу створити гілку development з цього комміту. Для цього напишу:
git checkout -b development 6c44e53d06228f888f2f454d3cb8c1c976dd73f8
Створюється гілка, в якій будуть лише перші два коміти з гілки master. Щоб перевірити це, ми спершу переконаємося, що перейшли в іншу гілку і подивимося на кількість комітів:
git status
git log
І справді: вийшло, що у нас два коміти. До речі, цікавий момент: у цій гілці ще немає файлу .gitignore, тому наш скомпільований файл (GitTest.class) тепер підсвічується в untracked стані. Тепер можемо ще раз провести ревізію наших гілок, написавши:
git branch -a
Видно, що є дві гілки – master та development – і зараз стоїмо на development.
Створюємо гілку на основі поточної
Другий спосіб створення гілки – створення на основі іншої. Я хочу створити гілку на основі master гілки, тому потрібно спершу перейти на неї, а вже наступним кроком створити нову. Дивимося:- git checkout master – переходимо на гілку master;
- git status - перевіряємо, чи точно на майстрі.
git checkout -b feature/update-txt-files
Якщо є сумніви, що ця гілка буде не такою самою, як і master, можна це легко перевірити, написавши git log і подивитися на всі комміти. Там їх має бути чотири.
Резолвім конфлікти
Перш ніж розібратися з тим, що таке конфлікт, слід поговорити про злиття (смерджування) однієї гілки в іншу. Ось таким малюнком можна показати процес, коли одну гілку мерджають в іншу: Тобто є головна гілка. Від неї в якийсь момент створюють другорядну, в якій відбуваються зміни. Як тільки робота зроблена, потрібно злити одну гілку в іншу. Я не описуватиму різні особливості: я хочу донести в рамках цієї статті лише розуміння, а вже деталі дізнаєтеся самі, якщо буде потрібно. Так ось, на нашому прикладі ми створабо гілку feature/update-txt-files. Як написано в імені гілки – оновимо текст. Тепер потрібно створити під цю справу новий коміт:
git add *.txt
git commit -m “updated txt files”
git log
Тепер, якщо ми хочемо смердити feature/update-txt-files гілку в master, потрібно перейти в master і написати git merge feature/update-txt-files:
git checkout master
git merge feature/update-txt-files
git log
Як результат – тепер і в майстер гілці є комміт, який був доданий у feature/update-txt-files. Ця функціональність додана, тому можна видалити фіче (feature) гілку. Для цього напишемо:
git branch -D feature/update-txt-files
Поки що зрозуміло, так? Ускладнюємо ситуацію: тепер припустимо, що знову потрібно змінити файл txt. Але тепер ще й у майстрі цей файл буде змінено також. Тобто він паралельно змінюватиметься, і гіт не зможе зрозуміти що потрібно робити в ситуації, коли ми захочемо смердити в master гілку новий код. Поїхали! Створюємо нову гілку на основі master, робимо зміни до text_resource.txt і створюємо коміт під цю справу:
git checkout -b feature/add-header
... делаем изменения в файле
git add *.txt
git commit -m “added header to txt”
Переходимо на master гілку і також оновлюємо цей текстовий файл у тому ж рядку, що і фіче гілка:
git checkout master
… обновабо test_resource.txt
git add test_resource.txt
git commit -m “added master header to txt”
І тепер найцікавіший момент: потрібно смердити зміни з feature/add-header гілки в master. Ми знаходимося в майстер гілці, тому потрібно тільки написати:
git merge feature/add-header
Але ми отримаємо результат із конфліктом у файлі test_resource.txt: І тут ми можемо бачити, що гіт не зміг самостійно вирішити, як смерджити цей код і каже, що потрібно спочатку розрізнити конфлікт, а вже потім зробити коміт. Ок, відкриваємо в текстовому редакторі файл, у якому конфлікт, і бачимо: Щоб зрозуміти, що тут зробив гіт, потрібно згадати, що ми писали, і порівняти:
- між “<<<<<<< HEAD” та “=======” знаходяться зміни майстер, які були в цьому рядку в майстер гілці.
- між “=======” та “>>>>>>> feature/add-header” знаходяться зміни, які були у feature/add-header гілці.
git status
Переконалися, що то інший випадок, незвичайний. Продовжуємо:
git add *.txt
В описі можна помітити, що пропонують написати лише git commit. Слухаємо та пишемо:
git commit
І все: у такий спосіб ми зробабо це — розрізнабо конфлікт у консолі. Звичайно, в середовищах розробки можна це зробити трохи простіше, наприклад, Intellij IDEA все налаштовано так добре, що можна виконувати всі необхідні дії в ній. Але середовище розробки робить багато чого під капотом, і ми часто не розуміємо, що саме там сталося. А коли немає розуміння, то можуть виникнути й проблеми.
Робота з віддаленими репозиторіями
Останній крок – розібратися ще з кількома командами, які потрібні для роботи з віддаленим репозиторієм. Як я вже казав, віддалений репозиторій — це місце, де зберігається репозиторій і звідки можна його клонувати. Які бувають видалені репозиторії? Прикладів темрява:-
GitHub - це найбільше сховище для репозиторіїв та спільної розробки. Я вже описував його у попередніх статтях.
Підписуйтесь на мій аккаунт . Я часто виставляю там свої напрацювання у тих сферах, які вивчаю під час роботи. -
GitLab — веб-інструмент життєвого циклу DevOps з відкритим вихідним кодом , що представляє систему управління репозиторіями коду для Git з власної вікі, системою відстеження помилок , CI/CD пайплайн та іншими функціями.
Після новини про те, що Microsoft купила GitHub, деякі розробники продублювали свої напрацювання у GitLab. -
BitBucket — веб-сервіс для хостингу проектів та їхньої спільної розробки, заснований на системі контролю версій Mercurial та Git. У свій час мав велику перевагу перед GitHub у тому, що у нього були безкоштовні приватні репозиторії. Минулого року GitHub також відкрив цю можливість всім безкоштовно.
-
І так далі…
git clone https://github.com/romankh3/git-demo
Наразі локально є повна копія проекту. Щоб бути впевненим, що локально знаходиться остання копія проекту, потрібно, як кажуть, спулити дані, написавши:
git pull
У нашому випадку зараз нічого не змінилося віддалено, тому й відповідь Already up to date. Але якщо я внесу якісь зміни у віддаленому репозиторії, локальний оновиться після того, як ми їх спулимо. І, нарешті, остання команда запустити дані на віддалений репозиторій. Коли ми локально щось зробабо і хочемо передати це на віддалений репозиторій, потрібно спочатку створити новий коміт локально. Для цього додамо в наш текстовий файл ще щось: Тепер вже звичайна для нас річ - створюємо коміт під цю справу:
git add test_resource.txt
git commit -m “prepated txt for pushing”
І тепер команда, щоб відправити це на віддалений репозиторій:
git push
Ось і все, що я хотів розповісти. Дякую за увагу. Підписуйтесь на мій обліковий запис на GitHub , в якому я викладаю різні прикольні проекти-приклади з того, що я вивчаю та використовую на роботі.
Корисні посилання
- Офіційна дока на гіт, є російською . Рекомендую як довідковий посібник.
- Git
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ