1. Детальний гайд Git для новачків

Сьогодні поговоримо про систему контролю версій — Git (читається як ГІТ).

Без знання та розуміння цього інструмента неможливо бути програмістом. Само собою, для постійної роботи не потрібно пам’ятати всі команди та можливості. Потрібно знати набір команд, які допоможуть розуміти все, що відбувається.

Основи Git

Git — це розподілена система контролю версій нашого коду. Для чого вона нам? Для команди потрібна якась система керування роботою. Вона потрібна, щоб відстежувати зміни, які відбуваються з часом.

Тобто крок за кроком ми бачимо, які файли змінилися і як. Особливо це важливо, коли аналізуєш, що було зроблено в межах одного завдання: це дає можливість повертатися назад.

Уявімо ситуацію: був працюючий код, все в ньому було добре, але ми вирішили щось поліпшити чи підправити. Все нічого, але таке поліпшення зламало половину функціоналу, унеможливило роботу. І що далі? Без Гіта треба було б годинами сидіти і згадувати, як усе було спочатку. А так ми просто відкочуємось на коміт назад — і все.

Чи що робити, якщо є два розробники, які роблять одночасно свої зміни у коді? Без Гіта це виглядає так: вони скопіювали код із оригіналу, зробили що потрібно. Настає момент, і обидва хочуть додати свої зміни до головної папки. І що робити в цій ситуації?..

Таких проблем не буде взагалі, якщо користуватися Гітом.

Установка Git

Встановимо гіт на комп’ютер. Для різних OS цей процес трохи відрізняється.

Встановлення для Windows

Як завжди, потрібно завантажити exe файл і запустити його. Тут все просто: тиснемо на перше посилання гугла, встановлюємо і все. Для роботи будемо використовувати bash консоль, яку вони надають.

Щоб працювати у Windows, потрібно запустити Git Bash. Ось як він виглядає в меню пуск:

І це вже консоль, у якій можна працювати.

Щоб не переходити щоразу в папку з проєктом, щоб там відкрити гіт, можна в папці правою кнопкою миші відкрити консоль із потрібним нам шляхом:

Встановлення для Linux

Зазвичай git вже встановлений і є в дистрибутивах лінуксу, тому що це інструмент, який вперше був написаний для розробки ядра лінуксу. Але бувають ситуації, коли його нема. Щоб перевірити це, треба відкрити термінал і прописати: git --version. Якщо буде зрозуміла відповідь, нічого встановлювати не потрібно.

Відкриваємо термінал та встановлюємо. Для Ubuntu треба написати: sudo apt-get install git. І все: тепер у будь-якому терміналі можна користуватися гітом.

Встановлення на macOS

Тут також спочатку потрібно перевірити, чи є вже гіт (дивися вище, як на лінуксі).

Якщо все ж ні, найпростіший шлях — це a href="https://sourceforge.net/projects/git-osx-installer/files/" target="_blank". Якщо встановлений XCode, то гіт вже точно буде автоматично встановлений.

Налаштування Git

У гіта є налаштування користувача, від якого буде йти робота. Це розумна і необхідна річ, оскільки коли створюється коміт, гіт бере саме цю інформацію для поля 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).

І так далі.

Стани в Git

У Гіта є кілька станів, які потрібно зрозуміти та запам’ятати:

  • невідстежуваний (untracked);
  • змінений (modified);
  • підготовлений (staged);
  • закомічений (committed).

Як це розуміти?

Це стани, в яких перебувають файли із нашого коду. Тобто їхній життєвий шлях зазвичай виглядає так:

  • Файл, який створений і не доданий в репозиторій, буде в стані untracked.
  • Робимо зміни у файлах, які вже додані в гіт репозиторій — перебувають у стані modified.
  • З тих файлів, які ми змінили, обираємо тільки ті (або всі), які потрібні нам (наприклад, скомпільовані класи нам не потрібні), і ці класи зі змінами потрапляють у стан staged.
  • Із заготовлених файлів зі стану staged створюється коміт і перетворюється вже на гіт репозиторій. Після цього staged стан — порожній. А ось modified ще може щось містити.

Виглядає це так:

Що таке коміт

Коміт — це основний об’єкт в керуванні контролю версій. Він містить усі зміни під час цього коміту. Коміти пов’язані між собою як однозв’язний список.

А саме: є перший коміт. Коли створюється другий коміт, то він (другий) знає, що йде після першого. І в такий спосіб можна відстежити інформацію.

Також коміт має ще свою інформацію, так звані метадані:

  • унікальний ідентифікатор коміту, за яким можна його знайти;
  • ім’я автора коміту, який створив його;
  • дата створення коміту;
  • коментар, який визначає, що було зроблено під час цього коміту.

Ось як це виглядає:

Що таке гілка

Гілка — це покажчик певного коміту. Оскільки коміт знає, який коміт був до нього, коли гілка вказує на певний коміт, до неї належать і всі ті попередні.

З огляду на це можна сказати, що гілок, що вказують на той самий коміт, може бути скільки завгодно багато.

Робота відбувається у гілках, тому коли створюється новий коміт, гілка переносить свій покажчик на новіший коміт.

Початок роботи з Git

Можна працювати і лише з локальним репозиторієм, і з віддаленим.

Для відпрацювання необхідних команд можна скористатися лише локальним репозиторієм. Він зберігає всю інформацію лише локально у проєкті в папці .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

Зрозуміло, що ми хочемо зберігати лише вихідний код і нічого іншого в репозиторії. А що може бути ще? Як мінімум, скомпільовані класи та/або файли, які створюють середовища розробки.

У цьому прикладі гіт ігнор виглядатиме так:

*.class
target/
*.iml
.idea/

Дивимося тепер:

  • перший рядок — це ігнорування всіх файлів із розширенням .class;
  • другий рядок — це ігнорування папки target та всього, що вона містить;
  • третій рядок — це ігнорування всіх файлів із розширенням .iml;
  • четвертий рядок — це ігнорування папки .idea.

Спробуємо на прикладі. Щоб подивитися, як це працює, додамо скомпільований клас GitTest.class у проєкт і подивимося статус проєкту:

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 — перевіряємо, чи точно на мастері.

Ось тут видно, що ми перейшли на master гілку, тут вже працює гіт ігнор, і скомпільований клас уже не світиться як untracked.

Тепер створюємо нову гілку на основі master гілки:

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:

І тут ми можемо бачити, що гіт не зміг самостійно вирішити, як змерджити цей код, і каже, що треба спочатку розрезолвити конфлікт, а вже потім зробити коміт.

Ок, відкриваємо у текстовому редакторі файл, у якому конфлікт, і бачимо:

Щоб зрозуміти, що тут зробив гіт, треба згадати, що ми де писали, і порівняти:

  1. Між “<<<<<<< HEAD” та “=======” знаходяться зміни мастер, які були в цьому рядку в мастер гілці.
  2. Між “=======” та “>>>>>>> feature/add-header” знаходяться зміни, які були в feature/add-header гілці.

У такий спосіб гіт показує, що в цьому місці він не зміг зрозуміти, як злити в одне ціле цей файл, розділив цю ділянку на дві частини з різних гілок і запропонував вирішити нам самим.

Добре, вирішую прибрати усе і залишити лише слово header:

Подивимося на статус змін, опис буде дещо іншим. Буде не modified стан, а Unmerged. Тому сміливо можна було додати п’ятий стан… Але я думаю, що це зайве, подивимося:

git status

Переконалися, що це інший випадок, незвичайний. Продовжуємо:

git add *.txt

В описі можна помітити, що пропонують написати лише git commit. Слухаємо та пишемо:

git commit

І все: таким чином ми зробили це — розрезолвили конфлікт у консолі.

Звісно, в середовищах розробки можна це зробити трохи простіше, наприклад, у Intellij IDEA все налаштовано так добре, що можна виконувати всі необхідні дії у ній. Але середовище розробки робить багато чого “під капотом”, і ми часто не розуміємо, що саме там сталося. А коли немає розуміння, тоді можуть виникнути й проблеми.

Робота з віддаленими репозиторіями

Останній крок — розібратися ще з кількома командами, які потрібні для роботи з віддаленим репозиторієм.

Як я вже казав, віддалений репозиторій — це місце, де зберігається репозиторій і звідки можна його клонувати.

Які бувають видалені репозиторії? Прикладів безліч:

  • GitHub — це величезне сховище для репозиторіїв та спільної розробки.
  • GitLab — веб-інструмент життєвого циклу DevOps з відкритим кодом, що представляє систему управління репозиторіями коду для Git з особистим вікв, системою відслідковування помилок, CI/CD пайплайн та іншими функциями.
  • 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

Ось і все!

Корисні посилання

2. Як працювати з Git в IntelliJ IDEA

У цій частині ти дізнаєшся, як працювати з Git в Intellij IDEA.

Необхідні дії для підготовки:

  1. Прочитати, повторити та зрозуміти попередню частину. Це допоможе бути впевненим, що все вже налаштоване та готове до роботи.
  2. Встановити Intellij IDEA. З цим все має бути гаразд :)
  3. Виділити годину для повного засвоєння.

Для роботи візьмемо демопроєкт, який використовувався у лекції про Git.

Клонуємо проєкт локально

Тут є два варіанти.

  1. Якщо вже є гітхаб акаунт і хочеться щось потім запушити, краще зробити форк проєкту до себе і клонувати свою копію. Як зробити форк — можеш почитати в цій статті, у главі приклад the forking workflow.
  2. Клонувати з репозиторію і зробити все локально без можливості все це запушити на сервер.

Щоб клонувати проєкт із гітхабу, потрібно скопіювати посилання на проєкт і передати його в IntelliJ IDEA:

  1. Копіюємо адресу проєкту:

  2. Відкриваємо Intellij IDEA та обираємо Get from Version Control:

  3. Копіюємо, вставляємо адресу на проєкт:

  4. Вам запропонують створити Intellij IDEA проєкт. Приймаємо пропозицію:

  5. Оскільки немає системи збирання, обираємо Create project from existing sources:

  6. Далі буде така картина:

З клонуванням розібралися, тепер вже можна й озирнутися на всі боки.

Перший погляд на Intellij IDEA як на гіт UI

Придивись ще раз уважно до клонованого проєкту: там можна отримати багато інформації про систему контролю версій.

Перше — це Version Control панель у нижньому лівому куті. У ній можна знайти всі локальні зміни та отримати список комітів (аналог git log).

Перейдемо в лекцію Log. Є певна візуальна складова, яка допомагає зрозуміти, як саме відбувався процес розробки. Наприклад, видно, що створювалася нова гілка з комітом added header to txt, який потім влився в мастер-гілку. Якщо натиснути на коміт, у правому куті можна побачити всю інформацію про коміт: всі зміни та його метадані.

Більше того, можна побачити, які були зроблені зміни. Тим паче, що там же було розрезолвлено конфлікт. Це IDEA теж чудово показує.

Якщо натиснути двічі на файл, який був змінений за цей коміт, побачимо, як резолвили кофлікт:

Помітно, що праворуч і ліворуч були два варіанти одного файлу, який потрібно було змерджити в один. А посередині — результат, який був отриманий.

Коли в проєкті безліч гілок, комітів і користувачів, які працюють у проєкті, необхідно пошукати окремо за гілкою (branch), користувачем (user) та датою (date):

Також перед початком роботи слід пояснити, як зрозуміти, в якій гілці ми перебуваємо.

У правому нижньому куті є кнопка Git: master, де після Git: показано, на якій гілці перебуває зараз проєкт. Якщо натиснути на кнопку, можна зробити безліч корисних речей: перейти на іншу гілку, створити нову, перейменувати існуючу тощо.

Робота з репозиторієм

Корисні гарячі клавіші

Щоб далі працювати, потрібно запам’ятати кілька дуже корисних гарячих клавіш:

  1. ctrl + t — отримати останні зміни з віддаленого репозиторію (git pull).
  2. ctrl + k — зробити коміт/подивитися всі зміни, які є на даний момент. Сюди входять і untracked, і modified файли (git commit).
  3. ctrl + shift + k — це команда створення пуша змін на віддалений репозиторій. Всі коміти, які були створені локально і ще не перебувають на віддаленому, будуть запропоновані для пуша (git push).
  4. alt + ctrl + z — відкотити у конкретному файлі зміни до стану останнього створеного коміту в локальному репозиторії. Якщо у верхньому лівому куті виділити весь проєкт, то можна буде відкотити зміни всіх файлів.

Що ми хочемо?

Нам для роботи треба освоїти базовий сценарій, який використовується скрізь.

Постає завдання реалізувати нову функціональність в окремій гілці та запушити її на віддалений репозиторій (далі потрібно створити ще пул-реквест на головну гілку, але це виходить за межі нашої лекції).

Що потрібно для цього зробити?

  1. Отримати всі зміни на цей момент в основний гілці (master, наприклад).

  2. На базі цієї основної створити окрему для своєї роботи.

  3. Реалізувати нову функціональність.

  4. Перейти на основну гілку та перевірити, чи не було нових змін за час, поки працювали. Якщо не було, то все добре, а якщо було, то робимо таке: переходимо на працюючу гілку та робимо ребейз змін з основної гілки в нашу. Якщо все пройшло успішно, то чудово. Але цілком можуть бути і конфлікти. І їх якраз можна буде заздалегідь вирішити, не гаючи часу на віддаленому репозиторії.

    Здавалося б, навіщо це робити? Це правило доброго тону, яке запобігає виникненню конфліктів вже після пуша своєї гілки на локальний репозиторій (є, звісно, ймовірність, що все одно вони будуть, але вона стає значно меншою)..

  5. Запушити свої зміни на віддалений репозиторій.

Як отримати зміни з віддаленого сервера

Ми додали опис у README у вигляді нового коміту і хочемо ці зміни отримати. Пропонується вибір між мерджем та ребейзом у разі, якщо були зроблені зміни і в локальному репозиторії, і у віддаленому. Обираємо мерж.

Вводимо ctrl + t:

В результаті видно, як змінився README, тобто зміни з віддаленого репозиторію підтяглися, і в правому нижньому куті можна переглянути всі деталі тих змін, які прийшли із сервера.

Створити нову гілку на основі master

Тут все просто.

Переходимо в правий нижній кут і натискаємо на Git: master, обираємо + New Branch.

Залишаємо галочку Checkout branch і пишемо ім’я нової гілки. У нашому випадку це буде readme-improver.

Після цього Git: master зміниться на Git: readme-improver.

Імітуємо паралельну роботу

Щоб конфлікти виникли, їх хтось має створити.

Відредагуємо через браузер README у вигляді нового коміту і таким чином зімітуємо паралельну роботу. Мовляв, хтось під час роботи зробив зміни у тому самому файлі, що й ми, що призведе до конфлікту. Видалимо слово «повністю» з 10 рядка.

Реалізувати свою функціональність

Завдання полягає в тому, щоб змінити README та додати опис до нової статті, тобто те, що робота в гіті йде через Intellij IDEA. Додаємо це:

Зміни виконані, тепер можна створити коміт. Натискаємо гарячу клавішу ctrl + k, отримаємо:

Перш ніж створити коміт, потрібно уважно подивитися на те, що пропонується в цьому вікні.

В секції Commit Message пишемо текст коміту, і, щоб він створився, потрібно натиснути кнопку Commit.

Пишемо, що README змінився, та створюємо коміт. В результаті в лівому нижньому куті спливає оповіщення, в якому буде ім’я коміту:

Перевірити, чи не змінилася основна гілка

Виконали завдання, все працює, тести написали, все гаразд. Але перш ніж пушити на сервер, потрібно перевірити, чи не було змін в основній гілці за цей час. Як це могло статися? Дуже просто: комусь дали завдання після вас, і цей хтось виконав його швидше за вас.

Тому переходимо на master гілку. Для цього треба в правому нижньому куті зробити те, що показано нижче на рисунку:

У master гілці натискаємо ctrl + t, щоб отримати її останні зміни з віддаленого сервера. Якщо подивитися, які були зміни, легко можна помітити, що сталося:

Як бачимо, було видалено слово «повністю». Можливо, це був хтось із маркетингу, і він вирішив, що так не можна писати, і дав розробникам завдання оновити це.

Тепер у нас локально остання версія master гілки. Переходимо назад на readme-improver.

Тепер треба заребейзити зміни з мастер гілки в нашу. Робимо:

Якщо ви все правильно виконували зі мною, в результаті має з’явитися конфлікт у README файлі:

Тут також багато інформації, яку варто було б зрозуміти й засвоїти. Тут показано список (у нашому випадку з одного елемента) файлів, у яких конфлікти. Ми можемо обрати три опції:

  1. accept yours — прийняти тільки зміни з readme-improver.
  2. accept theirs — прийняти тільки зміни з master.
  3. merge — самому обрати, що потрібно залишити, а що — прибрати.

Незрозуміло, що там змінилося, і якщо вже зміни є в мастері, отже, вони потрібні там, і просто прийняти наші зміни не можна, тому обираємо merge:

Тут видно, що є три частини:

  1. Це зміни з readme-improver.
  2. Результат. Поки що там так, як було до змін.
  3. Зміни з master гілки.

Нам потрібно таким чином зібрати результат, щоби він усіх задовольнив. Тому вивчили, що зробили ДО нас, зрозуміли, що просто прибрали слово «повністю». Ну, окей, без проблем. Отже, і ми його приберемо в результаті і додамо наші зміни. Як тільки виправимо результат, можна натиснути Apply.

Після цього з’явиться оповіщення, що ребейз пройшов успішно:

Ось так ми зарезолвили свій перший конфлікт через Intellij IDEA.

Запушити зміни на віддалений сервер

Наступний крок — запушити зміни на віддалений сервер і створювати пул-реквест. Для цього просто натискаємо ctrl + shift + k, після чого отримаємо:

Ліворуч буде список комітів, які не запушені на віддалений репозиторій, а праворуч будуть усі файли, які змінені. І все: натискаємо Push, і буде вам щастя :)

У разі успішного пуша буде ось таке повідомлення в нижньому правому куті:

Бонус: створення пул-реквесту

Переходимо на гітхаб репозиторій і бачимо, що гітхаб вже знає, що нам запропонувати:

Натискаємо на Compare & pull request, після чого натискаємо Create pull request. Завдяки тому, що ми заздалегідь вирішили конфлікти, тепер під час створення пул-реквесту його одразу можна мерджити:

Ось і все!