Знайома ситуація — і чим її прибирають.
На першому уроці ти зробив сторінку в ~/www і відкрив її в інтернеті. Сьогодні щось у ній поправив, зберіг — і стало гірше, ніж було. Як воно виглядало годину тому, ти вже не памʼятаєш, а повернути нема звідки.
Так влаштоване звичайне збереження: коли ти зберігаєш файл, компʼютер лишає тільки останній варіант і затирає попередній. Учорашнього тексту на диску вже немає. Один необережний рух — і години роботи зникли безслідно.
Потрібно інше: щоб кожен варіант роботи лишався окремою точкою, до якої можна повернутися. Це називають контролем версій, а інструмент для нього — git. Він уже стоїть на сервері, окремо ставити нічого не треба.
Це не шкільна вигадка: git — інструмент, яким щодня користується практично кожна команда розробників у світі, від соло-проєктів до великих компаній. Уміння повернутися до робочої версії й показати історію змін — базова навичка будь-кого, хто пише код чи веде проєкт.
Звідки беруться варіанти, до яких вертаються.
git працює просто: ти кажеш йому запамʼятати, як тека виглядає прямо зараз, і він робить знімок — коміт. У знімок потрапляє стан усіх файлів теки на ту мить, а не один рядок чи один файл.
Пізніші правки цей знімок уже не міняють: він назавжди лишається таким, якою тека була, коли ти його зробив. Хочеш зберегти новий стан — робиш новий коміт.
Кожен коміт отримує короткий код і твоє повідомлення одним рядком: що саме змінив. Усі коміти по черзі — це історія, звичайний список знімків. Щоб повернутися до вчорашнього варіанта, нічого памʼятати не треба: він лежить окремим комітом, і git його дістане.
Ти зробив коміт, а потім ще раз змінив той самий файл. Що тепер зберігає той коміт?
Чому місце для .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 не знає, хто ти, команда commit зупиниться з помилкою і нічого не збереже.
Тому один раз на акаунті задають user.name і user.email через git config --global. Це просто підпис у налаштуваннях git, а не окремий логін чи пароль; пошта може бути будь-якою. У практиці ми складемо і імʼя, і пошту з твого логіна автоматично — вводити руками нічого.
Різниця між «git бачить файл» і «git його зберіг».
Головна команда для орієнтування — git status. Вона нічого не змінює, її можна запускати скільки завгодно, і вона щоразу каже, у якому стані тека. Ось що вона показує одразу після того, як ти створив README.md, але ще не зберіг його:
Рядок On branch main каже, в якій гілці — окремій лінії історії комітів — ти зараз працюєш; поки вона одна, і зветься main. Розділ Untracked files означає: git помітив README.md, але поки не стежить за ним. У знімок такий файл сам не потрапить — його треба спершу додати командою git add, а тоді зберегти в коміт. Доти файл лишається поза історією.
Ти створив README.md, а git status показує його в розділі Untracked files. Він уже в історії?
Історія — це рядки, по одному на коміт.
Коли знімки вже зроблені, git log --oneline друкує історію: по рядку на кожен коміт, згори новіший. У рядку — короткий код і те повідомлення, яке ти написав.
Саме сюди ти зазирнеш, коли захочеш знайти точку, до якої повернутися: за повідомленням згадаєш, що в якому знімку. Коди в тебе будуть інші — вони обчислюються з вмісту, тож у кожного свої.
Після першого коміту git log --oneline показав один рядок: короткий код і твій підпис. Що це за рядок?
Не просто список комітів, а самі рядки правок.
Часто треба зрозуміти не те, які коміти є, а що саме змінилося між двома з них. Для цього — git diff. У виводі рядки з + — додані, з - — прибрані. HEAD означає останній коміт, HEAD~1 — попередній:
Так само можна порівняти будь-які два коміти, підставивши їхні коди. Верхні технічні рядки виводу й коди після слова index у кожного свої — на них не зважай, дивись на + і -.
В історії два коміти. Ти хочеш побачити, які саме рядки змінилися між ними. Що зробиш?
Що станеться, якщо зникне сервер.
Уся твоя історія зараз лежить в одному місці — на сервері, у теці .git. Досить одного збою: зникне акаунт, хтось зітре теку, впаде диск — і робота зникне разом з історією.
Тому роблять другу копію в іншому місці. Копія має бути незалежною: якщо оригінал пропаде, з копії все відновлюється. Спосіб, що працює скрізь без винятку, — окреме сховище на самому сервері, поряд, але окремо від робочої теки.
Дати копії імʼя й відправити в неї коміти.
Спершу для копії роблять окреме сховище командою git init --bare — це сховище без робочих файлів, лише історія; туди не заходять редагувати. Далі git треба сказати, де ця копія: адресі дають коротке імʼя, за звичаєм origin — головна копія проєкту. Після цього git push відправляє в неї всі наявні коміти.
Якщо тобі є 13 років і маєш акаунт GitHub, замість шляху на сервері можна поставити адресу порожнього репозиторію з сайта — решта кроків однакова:
Push відправляє тільки закомічене; незбережені зміни лишаються в тебе. Прапорець -u звʼязує твою гілку main з копією, тож наступного разу вистачить самого git push.
git, а не через API сайта — це спосіб, яким сайт відповідає на автоматичні запити, і він же обмежує, скільки таких запитів можна зробити за годину з однієї адреси. Сорок із лишком учнів за однією шкільною адресою вичерпали б цей ліміт за хвилини.Один рядок доводить, що копія на місці.
Щоб переконатися, що коміти справді доїхали, не потрібні ні браузер, ні API сайта — досить спитати саму копію, що в ній лежить. Команда git ls-remote origin HEAD виведе довгий код і слово 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. Детальніше — у наступній вкладці «Здача і підсумок».
Пункти нижче перевіряються автоматично. Червоний — виправ і запусти ще раз.
Останній крок роботи — фінальний результат, який оцінюють.
Коли git-частину зроблено й на питання відповів, натисни кнопку «Експортувати відповіді» вгорі сторінки. Браузер завантажить у теку Downloads файл lesson-02.json. Його імʼя й твій клас сторінка підставить сама — перейменовувати нічого не треба.
Тепер відкрий FileZilla (хост sftp://91.219.61.4, порт 22, твій логін) і перетягни lesson-02.json у теку upload/answers. Цю теку зробили ще на першому уроці — тут її не створюємо, лише заливаємо файл усередину.
У файлі — твої обрані відповіді, позначені кроки й попередній бал. Раз на годину сервер сам автоматично перераховує теоретичні відповіді за власним ключем — твоєму файлу на слово не вірить — і зводить результат разом з автобалом у панель учителя. Тож бал, який ти бачиш одразу, — попередній; остаточний зʼявиться після перевірки на сервері.
lesson-02.json не лежить у upload/answers, у сервера немає твоїх відповідей — критерій «файл відповідей залито» лишиться червоним.Обери, що зробити або що це означає.
git status показує modified: README.md. Що це означає?
Ти хочеш зробити другий коміт після правки. Який порядок команд правильний?
Навіщо git init для історії робимо в ~/data/hardware-passport, а не в ~/www?
Ти зробив git push, а git ls-remote origin HEAD не показав нічого. Найімовірніша причина?
Це те, що бачить учитель, коли виставляє оцінку.
| Складник | Вага | Результат |
|---|
Index.HTML — сервер такої сторінки не знаходить;www\index.html;cd www набрано не зі своєї домашньої теки замість
cd ~/www;~/upload — його не перенесли
в ~/www;<meta charset="UTF-8">,
і замість українських літер видно набір символів;~/www.