Відстеження змін

Останнє оновлення 2024-10-01 | Редагувати цю сторінку

Приблизний час: 20 хвилин

Огляд

Питання

  • Як зберегти зміни в Git?
  • Як перевірити стан свого репозиторію?
  • Як зробити нотатки про те, які зміни було внесено і чому?

Цілі

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

Спочатку переконаймося, що ми все ще у правильному каталозі. Ви повинні знаходитися у каталозі planets.

BASH

$ cd ~/Desktop/planets

Тепер створимо файл під назвою mars.txt, який буде містити деякі нотатки про придатність Марса як бази. Ми будемо використовувати редактор nano для редагування файлу; ви можете використовувати будь-який редактор, який вам подобається. Зокрема, це не обовʼязково повинен бути core.editor, який ви раніше вказали глобально. Але пам’ятайте, що команда bash для створення або редагування нового файлу буде залежати від редактора, який ви оберете (це може бути не nano). Для довідки щодо текстових редакторів, дивіться “Which Editor?” в уроці The Unix Shell.

BASH

$ nano mars.txt

Введіть наведений нижче текст у файл mars.txt:

ВИХІД

Cold and dry, but everything is my favorite color

Давайте спочатку перевіримо, що файл був правильно створений, запустивши команду ls:

BASH

$ ls

ВИХІД

mars.txt

mars.txt містить тільки один рядок, який ми можемо побачити, запустивши:

BASH

$ cat mars.txt

ВИХІД

Cold and dry, but everything is my favorite color

Якщо ми знову перевіримо статус нашого проєкту, Git повідомляє нам, що він помітив новий файл:

BASH

$ git status

ВИХІД

On branch main

No commits yet

Untracked files:
   (use "git add <file>..." to include in what will be committed)

	mars.txt

nothing added to commit but untracked files present (use "git add" to track)

Повідомлення “untracked files” означає, що в каталозі існує файл, який Git не відстежує. Ми можемо повідомити Git, що цей файл треба відстежувати за допомогою команди git add:

BASH

$ git add mars.txt

та згодом переконатися, що все виглядає правильно:

BASH

$ git status

ВИХІД

On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

	new file:   mars.txt

Git тепер знає, що він повинен стежити за файлом mars.txt, але він ще не записав ці зміни як коміт. Щоб зробити це, нам потрібно виконати ще одну команду:

BASH

$ git commit -m "Start notes on Mars as a base"

ВИХІД

[main (root-commit) f22b25e] Start notes on Mars as a base
 1 file changed, 1 insertion(+)
 create mode 100644 mars.txt

Коли ми запускаємо git commit, Git бере все, що ми раніше запросили його зберегти за допомогою git add, та зберігає постійну копію цих змін у спеціальному каталозі .git. Ця постійна копія називається commit (або revision). У цьому прикладі коміт має скорочений ідентифікатор f22b25e. У вашого коміту може бути інший ідентифікатор.

Ми використовуємо команду -m (від “message”) щоб надати короткий, інформативний та конкретний коментар, який допоможе нам згадати пізніше про те, що ми зробили та чому. Якщо ми просто запустимо git commit без опції -m, Git запустить nano (або будь-який інший редактор, який ми вказали як core.editor), щоб ми могли написати довше повідомлення.

Гарні повідомлення комітів починаються з короткого (< 50 символів) тексту про зміни, внесені в коміт. Загалом, повідомлення має завершувати речення “If applied, this commit will” (“Якщо застосовано, цей коміт буде” <0>). Якщо ви хочете детальніше перейти до подробиць, додайте порожній рядок між першим рядком та вашими додатковими примітками. Використовуйте додаткові примітки, щоб пояснити, чому ви внесли зміни та/або яким буде їх вплив.

Якщо ми тепер запустимо git status:

BASH

$ git status

ВИХІД

On branch main
nothing to commit, working tree clean

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

BASH

$ git log

ВИХІД

commit f22b25e3233b4645dabd0d81e651fe074bd8e73b
Author: Vlad Dracula <vlad@tran.sylvan.ia>
Date:   Thu Aug 22 09:51:46 2013 -0400

    Start notes on Mars as a base

git log виводить перелік усіх комітів, які були внесені до репозиторію, у зворотному хронологічному порядку. Для кожного коміту буде надруковано повний ідентифікатор коміту (який починається з тих же символів, що і скорочений ідентифікатор, попередньо надрукований командою git commit), автор коміту, дата його створення, і повідомлення Git, яке було додано під час запису коміту.

Де зберігаються мої зміни?

Якщо ми тепер запустимо ls, ми все одно побачимо лише один файл, який називається mars.txt. Це відбувається тому, що Git зберігає інформацію про історію файлів у спеціальному каталозі .git, згаданому раніше, щоб наша файлова система не засмічувалася (і щоб ми випадково не могли змінити або видалити стару версію).

Тепер припустимо, що Dracula додає нову інформацію до файлу. (Знову ж таки, ми будемо редагувати його за допомогою nano, і потім перевіряти його зміст за допомогою cat; ви можете користуватися іншим редактором, та можете не використовувати cat.)

BASH

$ nano mars.txt
$ cat mars.txt

ВИХІД

Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman

Тепер, коли ми запускаємо git status, Git повідомляє нам, що файл, про який він вже знає, був змінений:

BASH

$ git status

ВИХІД

On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   mars.txt

no changes added to commit (use "git add" and/or "git commit -a")

Ключова фраза - це останній рядок: “no changes added to commit”. Ми змінили цей файл, але ми ще не зберегли їх (що ми робимо за допомогою git commit), та навіть не сказали Git, що ми маємо намір зберегти ці зміни у майбутньому (що ми робимо за допомогою git add). Тож зробімо це зараз. Хорошою рекомендацією є перегляд наших змін кожного разу перед їх збереженням. Це робиться за допомогою git diff. Результат показує нам відмінності між поточним станом файлу та його останньою збереженою версією:

BASH

$ git diff

ВИХІД

diff --git a/mars.txt b/mars.txt
index df0654a..315bf3a 100644
--- a/mars.txt
+++ b/mars.txt
@@ -1 +1,2 @@
 Cold and dry, but everything is my favorite color
+The two moons may be a problem for Wolfman

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

  1. Перший рядок вказує на те, що результат цієї команди у Git подібний до Unix команди diff, яка порівнює стару та нову версії файлу.
  2. Другий рядок повідомляє які саме версії файлу Git порівнює; df0654a та 315bf3a є унікальними ідентифікаторами цих версій.
  3. Третій та четвертий рядки ще раз показують назву файлу, що змінюється.
  4. Решта рядків найцікавіші, вони показують нам фактичні відмінності і рядки, у яких вони відбуваються. Зокрема, значок + в першому стовпці вказує де ми додали рядок.

Після того, як ми переглянули наші зміни, прийшов час зберегти їх:

BASH

$ git commit -m "Add concerns about effects of Mars' moons on Wolfman"

ВИХІД

On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   mars.txt

no changes added to commit (use "git add" and/or "git commit -a")

Але це не спрацює: Git не буде додавати зміни, тому що ми не використали спочатку git add. Давайте це виправимо:

BASH

$ git add mars.txt
$ git commit -m "Add concerns about effects of Mars' moons on Wolfman"

ВИХІД

[main 34961b1] Add concerns about effects of Mars' moons on Wolfman
 1 file changed, 1 insertion(+)

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

Щоб це було можливо зробити, Git має спеціальну зону стейджингу (staging area), де він відстежує речі, які були додані до поточного набору змін (changeset) проте, ще не були збережені.

Зона стейджингу (staging area)

Якщо ви будете уявляти, ніби Git робить знімки змін протягом життя проєкту, то git add вказує що буде на знімку (додаючи речі в зоні стейджингу), а git commit після того насправді робить знімок, та назавжди зберігає його (як коміт). Якщо у зоні стейджингу нічого немає, то коли ви введете git commit, Git запропонує вам використати git commit -a або git commit --all, який ніби збирає разом всіх, щоб зробити групове фото! Однак майже завжди краще явним чином додати речі до зони стейджингу, тому що без цього ви можете випадково зберегти інші зміни, про які ви забули. (Повертаючись до порівняння з груповим фото, якщо ви використали команду “-а”, до вашої фотографії може потрапити зайва людина!) Тому додавайте речі в зону стейджингу власноруч - > в іншому випадку вам може знадобитися шукати як використовувати “git undo commit” частіше, ніж вам хотілося б!

A diagram showing how "git add" registers changes in the staging area, while "git commit" moves changes from the staging area to the repository

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

BASH

$ nano mars.txt
$ cat mars.txt

ВИХІД

Cold and dry, but everything is my favorite color
The two moons may be a problem for Wolfman
But the Mummy will appreciate the lack of humidity

BASH

$ git diff

ВИХІД

diff --git a/mars.txt b/mars.txt
index 315bf3a..b36abfd 100644
--- a/mars.txt
+++ b/mars.txt
@@ -1,2 +1,3 @@
 Cold and dry, but everything is my favorite color
 The two moons may be a problem for Wolfman
+But the Mummy will appreciate the lack of humidity

Поки що все добре: ми додали один рядок в кінці файлу (що зазначає + у першій колонці). Тепер помістімо цю зміну у зону стейджингу та подивимося що після цього звітує git diff:

BASH

$ git add mars.txt
$ git diff

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

BASH

$ git diff --staged

ВИХІД

diff --git a/mars.txt b/mars.txt
index 315bf3a..b36abfd 100644
--- a/mars.txt
+++ b/mars.txt
@@ -1,2 +1,3 @@
 Cold and dry, but everything is my favorite color
 The two moons may be a problem for Wolfman
+But the Mummy will appreciate the lack of humidity

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

BASH

$ git commit -m "Discuss concerns about Mars' climate for Mummy"

ВИХІД

[main 005937f] Discuss concerns about Mars' climate for Mummy
 1 file changed, 1 insertion(+)

Перевіримо наш статус:

BASH

$ git status

ВИХІД

On branch main
nothing to commit, working tree clean

і подивимося на історію попередніх змін:

BASH

$ git log

ВИХІД

commit 005937fbe2a98fb83f0ade869025dc2636b4dad5 (HEAD -> main)
Author: Vlad Dracula <vlad@tran.sylvan.ia>
Date:   Thu Aug 22 10:14:07 2013 -0400

    Discuss concerns about Mars' climate for Mummy

commit 34961b159c27df3b475cfe4415d94a6d1fcd064d
Author: Vlad Dracula <vlad@tran.sylvan.ia>
Date:   Thu Aug 22 10:07:21 2013 -0400

    Add concerns about effects of Mars' moons on Wolfman

commit f22b25e3233b4645dabd0d81e651fe074bd8e73b
Author: Vlad Dracula <vlad@tran.sylvan.ia>
Date:   Thu Aug 22 09:51:46 2013 -0400

    Start notes on Mars as a base

Порівняння з підсвіткою змінених слів у рядках

Інколи, наприклад, у випадку текстових документів, результат diff дуже важко зрозуміти. Саме тут --color-words опція для git diff є надзвичайно зручною, бо вона виділяє кольором змінені слова.

Перегляд історії змін за сторінками

Коли розмір результату git log перевищує розмір вашого екрану, git використовує спеціальну програму “пейджер”, щоб поділити результат на сторінки розміром з ваш екран. Після виклику “пейджера”, ви помітите, що останній рядок на екрані - це :, замість звичайного запрошення командного рядка.

  • Натисніть Q, щоб вийти з пейджеру.
  • Натисніть пробіл, щоб перейти на наступну сторінку.
  • Щоб шукати some_word на всіх сторінках, натисніть / і введіть some_word. Натисніть N для навігації між результатами пошуку.

Обмеження розміру зображуваної історії змін

Щоб запобігти випадку, коли git log повністю займає ваш термінал, ви можете обмежувати кількість комітів які відображує Git, використовуючи опцію -N, де N - кількість комітів які б ви бажали бачити на екрані. Наприклад, якщо ви бажаєте побачити лише останній коміт, використовуйте команду

BASH

$ git log -1

ВИХІД

commit 005937fbe2a98fb83f0ade869025dc2636b4dad5 (HEAD -> main)
Author: Vlad Dracula <vlad@tran.sylvan.ia>
Date:   Thu Aug 22 10:14:07 2013 -0400

   Discuss concerns about Mars' climate for Mummy

Ви також можете зменшити кількість інформації, використовуючи опцію --oneline:

BASH

$ git log --oneline

ВИХІД

005937f (HEAD -> main) Discuss concerns about Mars' climate for Mummy
34961b1 Add concerns about effects of Mars' moons on Wolfman
f22b25e Start notes on Mars as a base

Ви також можете комбінувати опцію --oneline з іншими опціями. Наступна корисна комбінація використовує опцію --graph для графічного зображення історії комітів за допомогою псевдографіки, вказуючи при цьому які коміти пов’язані з поточним HEAD, поточною гілкою main, або іншими обʼєктами у репозиторії’:

BASH

$ git log --oneline --graph

ВИХІД

* 005937f (HEAD -> main) Discuss concerns about Mars' climate for Mummy
* 34961b1 Add concerns about effects of Mars' moons on Wolfman
* f22b25e Start notes on Mars as a base

Каталоги

Дві важливі речі, які ви повинні знати про каталоги в Git.

  1. Git не відстежує каталоги самостійно, тільки файли всередині них. Спробуйте власноруч:

BASH

$ mkdir spaceships
$ git status
$ git add spaceships
$ git status

Зауважте, наш новостворений порожній каталог spaceships не зʼявляється в переліку невідстежуваних файлів, навіть якщо ми конкретно додали його (виконав git add) до нашого> репозиторію Ось чому ви іноді бачите файли .gitkeep в інших порожніх каталогах. На відміну від .gitignore, ці файли не є особливими і їх єдиною метою є заповнити каталог, щоб Git додав його до репозиторію. Насправді ви можете назвати такі файли до вашої вподоби.

  1. Якщо ви створюєте каталог у вашому репозиторії Git і заповнюєте його файлами, ви можете додати всі файли в каталозі одразу:

BASH

git add <directory-with-files>

Спробуйте власноруч:

BASH

$ touch spaceships/apollo-11 spaceships/sputnik-1
$ git status
$ git add spaceships
$ git status

Перш ніж рухатися далі, ми збережемо ці зміни.

BASH

$ git commit -m "Add some initial thoughts on spaceships"

Для повторення: коли ми хочемо додати зміни до нашого репозиторію, спочатку нам потрібно додати змінені файли в зону стейджингу (git add) а потім зберегти заплановані зміни до репозиторію (git commit):

A diagram showing two documents being separately staged using git add, before being combined into one commit using git commit

Вибір повідомлення коміту

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

  1. “Changes”
  2. “Added line ‘But the Mummy will appreciate the lack of humidity’ to mars.txt”
  3. “Discuss effects of Mars’ climate on the Mummy”

Відповідь 1 є недостатньо детальною, а мета коміту неясна; відповідь 2 дублює результат команди “git diff” яка покаже зміни, зроблені у цьому коміті; відповідь 3 - оптимальна: коротка, інформативна, та імперативна.

Збереження змін у Git

Яка(які) з наведених нижче команд збережуть зміни у файлі myfile.txt до мого локального Git репозиторію?

  1. BASH

       $ git commit -m "my recent changes"
  2. BASH

       $ git init myfile.txt
       $ git commit -m "my recent changes"
  3. BASH

       $ git add myfile.txt
       $ git commit -m "my recent changes"
  4. BASH

       $ git commit -m myfile.txt "my recent changes"
  1. Створить коміт, лише якщо файли вже були у зоні стейджінгу.

  2. Намагатиметься створити новий репозиторій.

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

  4. Спробує записати коміт файлу з назвою “my recent changes” з повідомленням myfile.txt.

Коміт декількох файлів

Зона стейджингу може зберігати зміни в будь-якій кількості файлів, які ви хочете записати в один коміт.

  1. Додайте текст до mars.txt про те, що ви вирішили розглянути побудову бази на Венері
  2. Створіть новий файл venus.txt з вашими думками стосовно Венери як бази для вас та ваших друзів
  3. Додайте зміни в обох файлах до зони стейджінгу, та зробіть коміт цих змін.

Результат з файлу cat mars.txt нижче зображує тільки контент доданий під час цієї вправи. Ваш результат може виглядати іншим чином.

Спочатку ми робимо зміни у файлах mars.txt та venus.txt

BASH

$ nano mars.txt
$ cat mars.txt

ВИХІД

Maybe I should start with a base on Venus.

BASH

$ nano venus.txt
$ cat venus.txt

ВИХІД

Venus is a nice planet and I definitely should consider it as a base.

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

BASH

$ git add mars.txt venus.txt

Або за допомогою декількох команд:

BASH

$ git add mars.txt
$ git add venus.txt

Тепер файли готові до коміту. Ви можете перевірити це за допомогою git status. Якщо ви готові зробити коміт, використовуйте

BASH

$ git commit -m "Write plans to start a base on Venus"

ВИХІД

[main cc127c2]
 Write plans to start a base on Venus
 2 files changed, 2 insertions(+)
 create mode 100644 venus.txt

Вправа: репозиторій з вашою автобіографією

  • Створіть новий репозиторій Git на вашому компʼютері під назвою bio.
  • Напишіть три рядки своєї біографії у файлі під назвою me.txt, та зробіть коміт цих змін
  • Змініть один з рядків, додайте четвертий рядок
  • Покажіть відмінності між оновленим файлом та його попередньою версією.

Якщо необхідно, вийдіть з каталогу planets:

BASH

$ cd ..

Створіть новий каталог bio та перейдіть до нього:

BASH

$ mkdir bio
$ cd bio

Ініціалізуйте репозиторій Git:

BASH

$ git init

Створіть файл me.txt з вашою біографією, використовуючи nano або інший текстовий редактор. Коли будете готові, додайте його до зони стейджингу та запишіть коміт до репозиторію:

BASH

$ git add me.txt
$ git commit -m "Add biography file" 

Змініть файл як вказано (змініть один рядок, додайте четвертий рядок). Для того, щоб показати зміни між оновленим файлом та його попередньою версією, використайте git diff:

BASH

$ git diff me.txt

Ключові моменти

  • git status показує стан репозиторію.
  • Файли можуть зберігатися в робочому каталозі проєкту (де їх бачать користувачі), зоні стейджингу (де будується наступний коміт) і локальному репозиторії (де коміти зберігаються постійно).
  • git add додає файли до зони стейджингу.
  • git commit зберігає все, що міститься у зоні стейджингу, як новий коміт у локальному репозиторії.
  • Повідомлення коміту треба складати так, щоб воно акуратно описувало ваші зміни.