← До списку уроків
8 клас · Урок 2 з 16

GitHub і контроль версій

виконано0%
Ситуація

Сторінка стала гіршою, а повернути як було нема куди

Знайома ситуація — і чим її прибирають.

На першому уроці ти зробив сторінку в ~/www і відкрив її в інтернеті. Сьогодні щось у ній поправив, зберіг — і стало гірше, ніж було. Як воно виглядало годину тому, ти вже не памʼятаєш, а повернути нема звідки.

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

Потрібно інше: щоб кожен варіант роботи лишався окремою точкою, до якої можна повернутися. Це називають контролем версій, а інструмент для нього — git. Він уже стоїть на сервері, окремо ставити нічого не треба.

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

Ідея

Коміт — це збережений знімок теки

Звідки беруться варіанти, до яких вертаються.

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

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

Кожен коміт отримує короткий код і твоє повідомлення одним рядком: що саме змінив. Усі коміти по черзі — це історія, звичайний список знімків. Щоб повернутися до вчорашнього варіанта, нічого памʼятати не треба: він лежить окремим комітом, і git його дістане.

Питання

Ти зробив коміт, а потім ще раз змінив той самий файл. Що тепер зберігає той коміт?

Де

Історію тримаємо в теці проєкту, а не в публічній www

Чому місце для .git — не там, де сторінка.

git зберігає всю історію в прихованій теці .git поряд із файлами, за якими стежить. Її імʼя починається з крапки, тож у звичайному списку файлів її не видно — але «не видно» не означає «недоступно».

Тека ~/www віддається nginx усьому інтернету. Якби .git лежала в ній, хтось міг би поштучно завантажити її вміст і зібрати всю історію твоїх правок — навіть ті варіанти, що ти давно прибрав.

Тому правило просте: історія не живе там, куди має доступ інтернет. Репозиторій робимо в теці проєкту ~/data/hardware-passport — тека data назовні закрита, і історія з неї нікуди не витече.

Що де лежить ~/www лишається тільки для готової, опублікованої сторінки. Робочі файли проєкту («паспорт твого компʼютера») і їх історія живуть у ~/data/hardware-passport.
Питання

Твоя сторінка лежить у ~/www, її віддає nginx усьому інтернету. Де запустити git init для історії проєкту?

План

Що ти зараз збудуєш: репозиторій, два коміти, друга копія

Три результати, до яких веде практика.

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

Репозиторій із першим комітом. Тека проєкту під наглядом git, у ній перший знімок.

Друга зміна і другий коміт. Історія, у якій уже є куди повертатися.

Друга копія. Незалежне сховище з тими самими комітами — на випадок, якщо перше пропаде.

Спочатку розберемо, що показують git status, git log і git diff, а тоді виконаємо ці три результати крок за кроком.

Підпис автора

git один раз запамʼятовує, хто автор комітів

Без цього перший коміт не збережеться.

Кожен коміт підписується імʼям автора — так в історії видно, хто зробив який знімок. Поки git не знає, хто ти, команда commit зупиниться з помилкою і нічого не збереже.

Тому один раз на акаунті задають user.name і user.email через git config --global. Це просто підпис у налаштуваннях git, а не окремий логін чи пароль; пошта може бути будь-якою. У практиці ми складемо і імʼя, і пошту з твого логіна автоматично — вводити руками нічого.

Обережно Якщо робитимеш копію на GitHub, це імʼя стане видимим у комітах на сайті. Не хочеш світити логін — постав замість нього псевдонім.
Що бачить git

git status: файл видно, але він ще не збережений

Різниця між «git бачить файл» і «git його зберіг».

Головна команда для орієнтування — git status. Вона нічого не змінює, її можна запускати скільки завгодно, і вона щоразу каже, у якому стані тека. Ось що вона показує одразу після того, як ти створив README.md, але ще не зберіг його:

приклад виводу
$ git status On branch main No commits yet Untracked files: (use "git add <file>..." to include in what will be committed) README.md nothing added to commit but untracked files present

Рядок On branch main каже, в якій гілці — окремій лінії історії комітів — ти зараз працюєш; поки вона одна, і зветься main. Розділ Untracked files означає: git помітив README.md, але поки не стежить за ним. У знімок такий файл сам не потрапить — його треба спершу додати командою git add, а тоді зберегти в коміт. Доти файл лишається поза історією.

Питання

Ти створив README.md, а git status показує його в розділі Untracked files. Він уже в історії?

Історія

git log показує список знімків

Історія — це рядки, по одному на коміт.

Коли знімки вже зроблені, git log --oneline друкує історію: по рядку на кожен коміт, згори новіший. У рядку — короткий код і те повідомлення, яке ти написав.

приклад виводу
$ git log --oneline fd5f42c Додав опис проєкту 8d70e40 Перший коміт: додав README

Саме сюди ти зазирнеш, коли захочеш знайти точку, до якої повернутися: за повідомленням згадаєш, що в якому знімку. Коди в тебе будуть інші — вони обчислюються з вмісту, тож у кожного свої.

Питання

Після першого коміту git log --oneline показав один рядок: короткий код і твій підпис. Що це за рядок?

Порівняння

git diff показує, що змінилось між знімками

Не просто список комітів, а самі рядки правок.

Часто треба зрозуміти не те, які коміти є, а що саме змінилося між двома з них. Для цього — git diff. У виводі рядки з + — додані, з - — прибрані. HEAD означає останній коміт, HEAD~1 — попередній:

приклад
$ git diff HEAD~1 HEAD

Так само можна порівняти будь-які два коміти, підставивши їхні коди. Верхні технічні рядки виводу й коди після слова index у кожного свої — на них не зважай, дивись на + і -.

Питання

В історії два коміти. Ти хочеш побачити, які саме рядки змінилися між ними. Що зробиш?

Навіщо копія

Одна копія історії — це ризик

Що станеться, якщо зникне сервер.

Уся твоя історія зараз лежить в одному місці — на сервері, у теці .git. Досить одного збою: зникне акаунт, хтось зітре теку, впаде диск — і робота зникне разом з історією.

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

Звʼязок

git remote називає копію, git push її наповнює

Дати копії імʼя й відправити в неї коміти.

Спершу для копії роблять окреме сховище командою git init --bare — це сховище без робочих файлів, лише історія; туди не заходять редагувати. Далі git треба сказати, де ця копія: адресі дають коротке імʼя, за звичаєм origin — головна копія проєкту. Після цього git push відправляє в неї всі наявні коміти.

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

приклад — заміни юзернейм
$ git remote add origin https://github.com/юзернейм/hardware-passport.git

Push відправляє тільки закомічене; незбережені зміни лишаються в тебе. Прапорець -u звʼязує твою гілку main з копією, тож наступного разу вистачить самого git push.

Ніяких запитів до api.github.com І для GitHub, і для локального сховища відправка та перевірка йдуть через сам git, а не через API сайта — це спосіб, яким сайт відповідає на автоматичні запити, і він же обмежує, скільки таких запитів можна зробити за годину з однієї адреси. Сорок із лишком учнів за однією шкільною адресою вичерпали б цей ліміт за хвилини.
Перевірка копії

git ls-remote показує, що лежить у копії

Один рядок доводить, що копія на місці.

Щоб переконатися, що коміти справді доїхали, не потрібні ні браузер, ні API сайта — досить спитати саму копію, що в ній лежить. Команда git ls-remote origin HEAD виведе довгий код і слово HEAD:

приклад виводу
$ git ls-remote origin HEAD fd5f42c403e8d4713f096ad9b96e67286fdcf028 HEAD

Код має збігатися з кодом верхнього коміту в git log — тоді копія повна. Порожня відповідь означає, що сховище зробили без -b main, і його HEAD показує на гілку, якої там немає. Код у тебе буде свій.

Питання

Усі твої коміти лежать тільки на сервері. Що дає git push -u origin main?

Практика

Збери репозиторій, два коміти й другу копію

Виконуй по одному кроку зверху вниз. Кожен спирається на попередній.

Докладно про кожен крок

Завдання A — збудуй репозиторій і зроби перший коміт (кроки 1–8). Заходиш у теку проєкту всередині ~/data (не в www), один раз називаєш автора комітів — $(whoami) сам підставить твій логін, руками нічого не вводь. Далі git init -b main починає історію, echo з однією стрілкою > створює README.md, а пара git add + git commit робить перший знімок. Без кроків 3–4 commit зупиниться з помилкою.

Завдання B — зроби другу зміну і другий коміт (кроки 9–11). echo з двома стрілками >> дописує рядок опису в кінець README.md, не затираючи його. Тоді знову git add і git commit — порядок незмінний: спершу add, потім commit, інакше зміна не потрапить у знімок. Після цього в історії два коміти (перевіриш git log --oneline, а різницю — git diff).

Завдання C — зроби другу копію і залий у неї коміти (кроки 12–14). git init --bare -b main робить окреме сховище в ~/backup; -b main обовʼязкове, без нього перевірка покаже порожньо. git remote add origin називає копію, git push -u origin main наповнює її. Маєш акаунт GitHub — постав адресу свого репозиторію замість шляху ~/backup.

Крок 15 — здай відповіді. Це не команда термінала, а ручний крок: натисни «Експортувати відповіді» вгорі сторінки, а тоді залий отриманий lesson-02.json у FileZilla в теку upload/answers. Детальніше — у наступній вкладці «Здача і підсумок».

Перевірка

Що має зійтися, щоб роботу прийняли

Пункти нижче перевіряються автоматично. Червоний — виправ і запусти ще раз.

Здача

Здай свої відповіді через FileZilla

Останній крок роботи — фінальний результат, який оцінюють.

Коли git-частину зроблено й на питання відповів, натисни кнопку «Експортувати відповіді» вгорі сторінки. Браузер завантажить у теку Downloads файл lesson-02.json. Його імʼя й твій клас сторінка підставить сама — перейменовувати нічого не треба.

Тепер відкрий FileZilla (хост sftp://91.219.61.4, порт 22, твій логін) і перетягни lesson-02.json у теку upload/answers. Цю теку зробили ще на першому уроці — тут її не створюємо, лише заливаємо файл усередину.

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

Без цього кроку роботу не приймуть Поки lesson-02.json не лежить у upload/answers, у сервера немає твоїх відповідей — критерій «файл відповідей залито» лишиться червоним.
Тест

Чотири ситуації наостанок

Обери, що зробити або що це означає.

Питання 1

git status показує modified: README.md. Що це означає?

Питання 2

Ти хочеш зробити другий коміт після правки. Який порядок команд правильний?

Питання 3

Навіщо git init для історії робимо в ~/data/hardware-passport, а не в ~/www?

Питання 4

Ти зробив git push, а git ls-remote origin HEAD не показав нічого. Найімовірніша причина?

Оцінка

Шкала виконання

Це те, що бачить учитель, коли виставляє оцінку.

СкладникВагаРезультат
Виконано
0%
Рекомендований бал — за 12-бальною

Типові помилки цього уроку