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

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

Огляд

Питання

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

Цілі

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

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

BASH

$ cd ~/Desktop/recipes

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

BASH

$ nano guacamole.md

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

ВИХІД

# Guacamole
## Ingredients
## Instructions

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

BASH

$ ls

ВИХІД

guacamole.md

guacamole.md містить три рядки, які ми можемо побачити, запустивши:

BASH

$ cat guacamole.md

ВИХІД

# Guacamole
## Ingredients
## Instructions

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

BASH

$ git status

ВИХІД

On branch main

No commits yet

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

	guacamole.md

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

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

BASH

$ git add guacamole.md

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

BASH

$ git status

ВИХІД

On branch main

No commits yet

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

	new file:   guacamole.md

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

BASH

$ git commit -m "Create a template for recipe"

ВИХІД

[main (root-commit) f22b25e] Create a template for recipe
 1 file changed, 1 insertion(+)
 create mode 100644 guacamole.md

Коли ми запускаємо 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: Alfredo Linguini <a.linguini@ratatouille.fr>
Date:   Thu Aug 22 09:51:46 2013 -0400

    Create a template for recipe

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

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

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

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

BASH

$ nano guacamole.md
$ cat guacamole.md

ВИХІД

# Guacamole
## Ingredients
* avocado
* lemon
* salt
## Instructions

Тепер, коли ми запускаємо 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 restore <file>..." to discard changes in working directory)

	modified:   guacamole.md

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/guacamole.md b/guacamole.md
index df0654a..315bf3a 100644
--- a/guacamole.md
+++ b/guacamole.md
@@ -1,3 +1,6 @@
 # Guacamole
 ## Ingredients
+* avocado
+* lemon
+* salt
 ## Instructions

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

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

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

BASH

$ git commit -m "Add basic guacamole's ingredients"
$ git status

ВИХІД

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

	modified:   guacamole.md

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

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

BASH

$ git add guacamole.md
$ git commit -m "Add basic guacamole's ingredients"

ВИХІД

[main 34961b1] Add basic guacamole's ingredient
 1 file changed, 3 insertions(+)

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

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

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

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

Додавання змін до зони стейджингу за допомогою "git add" та зберігання їх у репозиторії за допомогою "git commit"

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

BASH

$ nano guacamole.md
$ cat guacamole.md

ВИХІД

# Guacamole
## Ingredients
* avocado
* lime
* salt
## Instructions

BASH

$ git diff

ВИХІД

diff --git a/guacamole.md b/guacamole.md
index 315bf3a..b36abfd 100644
--- a/guacamole.md
+++ b/guacamole.md
@@ -1,6 +1,6 @@
 # Guacamole
 ## Ingredients
 * avocado
-* lemon
+* lime
 * salt
 ## Instructions

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

BASH

$ git add guacamole.md
$ git diff

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

BASH

$ git diff --staged

ВИХІД

diff --git a/guacamole.md b/guacamole.md
index 315bf3a..b36abfd 100644
--- a/guacamole.md
+++ b/guacamole.md
@@ -1,6 +1,6 @@
 # Guacamole
 ## Ingredients
 * avocado
-* lemon
+* lime
 * salt
 ## Instructions

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

BASH

$ git commit -m "Modify guacamole to the traditional recipe"

ВИХІД

[main 005937f] Modify guacamole to the traditional recipe
 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: Alfredo Linguini <a.linguini@ratatouille.fr>
Date:   Thu Aug 22 10:14:07 2013 -0400

    Modify guacamole to the traditional recipe

commit 34961b159c27df3b475cfe4415d94a6d1fcd064d
Author: Alfredo Linguini <a.linguini@ratatouille.fr>
Date:   Thu Aug 22 10:07:21 2013 -0400

    Add basic guacamole's ingredients

commit f22b25e3233b4645dabd0d81e651fe074bd8e73b
Author: Alfredo Linguini <a.linguini@ratatouille.fr>
Date:   Thu Aug 22 09:51:46 2013 -0400

    Create a template for recipe

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

Інколи, наприклад, у випадку текстових документів, результат 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: Alfredo Linguini <a.linguini@ratatouille.fr>
Date:   Thu Aug 22 10:14:07 2013 -0400

   Modify guacamole to the traditional recipe

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

BASH

$ git log --oneline

ВИХІД

005937f (HEAD -> main) Modify guacamole to the traditional recipe
34961b1 Add basic guacamole's ingredients
f22b25e Create a template for recipe

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

BASH

$ git log --oneline --graph

ВИХІД

* 005937f (HEAD -> main) Modify guacamole to the traditional recipe
* 34961b1 Add basic guacamole's ingredients
* f22b25e Create a template for recipe

Каталоги

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

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

BASH

$ mkdir cakes
$ git status
$ git add cakes
$ git status

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

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

BASH

$ git add <directory-with-files>

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

BASH

$ touch cakes/brownie_cakes/lemon_drizzle
$ git status
$ git add cakes
$ git status

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

BASH

$ git commit -m "Add some initial cakes"

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

{alt=‘Два документи окремо додаються до зони стейджингу за допомогою git add, а потім об’єднуються в один коміт за допомогою git commit’}

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

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

  1. “Changes”
  2. “Changed lemon for lime”
  3. “Guacamole modified to the traditional recipe”

Відповідь 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. Додайте до guacamole.md текст про приблизну ціну інгредієнтів.
  2. Створіть новий файл groceries.md зі списком товарів та їх цінами на різних ринках.
  3. Додайте зміни в обох файлах до зони стейджінгу, та зробіть коміт цих змін.

Спочатку ми оновимо файли guacamole.md та groceries.md:

BASH

$ nano guacamole.md
$ cat guacamole.md

ВИХІД

# Guacamole
## Ingredients
* avocado (1.35)
* lime (0.64)
* salt (2)

BASH

$ nano groceries.md
$ cat groceries.md

ВИХІД

# Market A
* avocado: 1.35 per unit.
* lime: 0.64 per unit
* salt: 2 per kg

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

BASH

$ git add guacamole.md groceries.md

Або кількома:

BASH

$ git add guacamole.md
$ git add groceries.md

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

BASH

$ git commit -m "Write prices for ingredients and their source"

ВИХІД

[main cc127c2]
 Write prices for ingredients and their source
 2 files changed, 7 insertions(+)
 create mode 100644 groceries.md

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

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

За потреби вийдіть з каталогу recipes:

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 зберігає все, що міститься у зоні стейджингу, як новий коміт у локальному репозиторії.
  • Повідомлення коміту треба складати так, щоб воно чітко описувало ваші зміни.