Основи Git

Отримання Git-репозиторію

Зазвичай ви отримуєте Git-репозиторій одним з двох способів:

  1. Ви можете взяти локальний каталог, який наразі не перебуває під контролем версій, і перетворити його на Git-репозиторій.

  2. Ви можете клонувати існуюче сховище Git’а з іншого місця.

У будь-якому випадку, ви отримаєте Git-репозиторій на вашій локальній машині, готовий до роботи.

Ініціалізація репо в існуючому каталозі

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

Зміна каталогу в bash (Linux)
cd /home/user/project
Зміна каталогу в bash (MacOS)
cd /Users/user/project
Зміна каталогу в PowerShell (Windows)
cd C:\Users\user\project

У каталозі проекту ініціалізуйте новий Git-репозиторій.

git init

Це створить новий підкаталог з ім’ям .git, який міститиме всі необхідні файли сховища - скелет сховища Git.

Клонування існуючого репо

Якщо ви хочете отримати копію існуючого сховища Git’а - наприклад, проекту, до якого ви хочете долучитися, - вам потрібна команда git clone.

git clone https://github.com/edu-python-course/edu-python-course.github.io

Він створює каталог з назвою edu-python-course.github.io, ініціалізує каталог .git всередині нього, витягує всі дані для цього сховища і перевіряє робочу копію останньої версії.

git clone https://github.com/edu-python-course/edu-python-course.github.io python-course

Ця команда робить те саме, що й попередня, але цільовий каталог називається python-course.

Git має декілька різних протоколів передачі даних, які ви можете використовувати. У попередньому прикладі використовується протокол https://, але ви також можете побачити git:// або user@server:path/to/repo.git, який використовує протокол передачі SSH.

Внесення змін до репозиторію

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

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

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

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

sequenceDiagram participant Untracked participant Unmodified participant Modified participant Staged Untracked ->> Staged: Add the file Unmodified ->> Modified: Edit the file Modified ->> Staged: Stage the file Unmodified ->> Untracked: Remove the file Staged ->> Unmodified: Commit

The lifecycle of the status of repo’s files

Перевірка стану файлу(ів)

Основним інструментом для визначення стану файлів є команда git status.

$ # check status
$ git status
On branch devel

No commits yet

nothing to commit (create/copy files and use "git add" to track)

$ # add file to the repository
$ echo "# Project Title" > README.md
$ # check status once again
$ git status
On branch devel

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 (use "git add" to track)

Щойно доданий файл README.md не відстежується, оскільки він знаходиться у розділі «Файли, що не відстежуються» у виведенні статусу.

Відстеження нових файлів

Для того, щоб почати відстеження нового файлу, скористайтеся командою git add.

$ git add README.md
$ git status
On branch devel

No commits yet

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

Відтепер файл README.md додано до області сцени і він готовий до фіксації (знаходиться під заголовком «Зміни, що підлягають фіксації»).

Підказка

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

git add *     # stage all changes
git add .     # stage all changes in current directory
git add docs  # stage all changes in "docs" directory

Зберігання змінених файлів

Якщо файл, що перебуває на етапі (або вже зафіксований), було змінено, його буде переміщено у рубрику «Змінено». Ці зміни не будуть зафіксовані, якщо вони не були поетапними.

$ git status
On branch devel

No commits yet

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

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:   README.md
  • Зміни можна додати до області сцени, повторивши команду git add.

  • Зміни можна відкинути командою git restore <file>. Ця дія відновить файл до його попередньої версії.

Фіксація змін

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

Найпростіший спосіб фіксації - ввести git commit:

git commit

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

Примітка

Це задається змінною оточення EDITOR вашої оболонки - зазвичай vim або emacs, хоча ви можете налаштувати її як завгодно за допомогою git config --global core.editor

Крім того, ви можете ввести повідомлення про фіксацію у рядку з командою commit, вказавши його після прапорця -m, як показано нижче:

git commit -m "Add GitHub workflow to test Sphinx builds for PRs to devel"

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

$ git status
On branch devel

No commits yet

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

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:   README.md

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

$ git commit -a -m "Commit tracked files"
[devel (root-commit) 7acb7a1] Commit tracked files
 1 file changed, 3 insertions(+)
 create mode 100644 README.md

$ git status
On branch devel
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        example.json

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

Ігнорування файлів

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

# virtual environment
/.venv/
/.env/
/venv/
/env/

# node packages
/node_modules/

# ide configs
/.vscode/
/.idea/

# emacs cache and backup files
\#*
*~

# temporary files storage
/temp/
/tmp/

# documentation builds
_builds/
_build/
builds/
build/

# translation object files
*.pot
*.mo

Ці рядки означають:

  • Вміст каталогів з іменами «.venv», «.env», «venv» або «env» буде повністю проігноровано.

  • Вміст каталогу «node_modules» буде повністю проігноровано.

  • Будь-які файли в каталогах з іменами «.vscode» або «.idea» будуть повністю проігноровані.

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

  • Будь-який файл, ім’я якого закінчується на тильду (~), буде проігноровано.

  • Вміст каталогів з іменами «temp» або «tmp» буде повністю проігноровано.

  • Вміст каталогів з іменами «_builds», «_build», «builds» або «build» буде повністю проігноровано.

  • Будь-який файл з іменем, що закінчується на «.pot», буде проігноровано.

  • Будь-який файл з іменем, що закінчується на «.mo», буде проігноровано.

Створення файлу .gitignore для вашого нового сховища перед початком роботи, як правило, є гарною ідеєю, щоб випадково не зафіксувати файли, які вам насправді не потрібні у вашому Git-репозиторії.

Правила для шаблонів, які ви можете помістити у .gitignore файл, такі:

  • Порожні рядки або рядки, що починаються з #, ігноруються.

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

  • Щоб уникнути рекурсивного включення, ви можете починати шаблони з прямої похилої риски (/).

  • Ви можете закінчувати шаблони прямою похилою рискою (/), щоб вказати каталог.

  • Ви можете заперечити шаблон, почавши його зі знаку оклику (!).

Глобальні шаблони подібні до спрощених регулярних виразів, які використовують оболонки. Зірочка (*) відповідає нулю або більше символів; [ab] відповідає будь-якому символу всередині дужок (у цьому випадку a або b); знак питання (?) відповідає одному символу; а дужки, що містять символи, розділені дефісом ([0-9]), відповідають будь-якому символу між ними (у цьому випадку від 0 до 9). Ви також можете використовувати дві зірочки для вкладених каталогів; a/**/z буде відповідати a/z, a/b/z, a/b/c/z і так далі.

Перегляд історії коммітів

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

$ git log
co  mmit 8b755eb400a1db7f88ca2058094321dcefea7f9c (HEAD -> feature/vcs, origin/feature/vcs)
Author: Serhii Horodilov <sgorodil@gmail.com>
Date:   Wed Aug 16 15:26:39 2023 +0300

    Update gitflow diagram

commit 1e131a0c9faee2a22ea2bae8f31f8c7ee04fefc5
Author: Serhii Horodilov <sgorodil@gmail.com>
Date:   Wed Aug 16 14:46:39 2023 +0300

    fixup! Add translations to VSC documents

commit 895dc24343fbbe25c3c94b25091ac64ac8aea53d
Author: Serhii Horodilov <sgorodil@gmail.com>
Date:   Wed Aug 16 14:42:10 2023 +0300

    Add translations to VSC documents

За замовчуванням, без аргументів, git log виводить список коммітів, зроблених у цьому сховищі, у зворотному хронологічному порядку; тобто, найновіші комміти показуються першими. Як ви можете бачити, ця команда показує кожне внесення з його контрольною сумою SHA-1, ім’ям та електронною адресою автора, датою створення та повідомленням про внесення.

Однією з найбільш корисних опцій є -p або --patch, яка показує відмінності (виведення patch), внесені у кожну фіксацію. Ви також можете обмежити кількість відображуваних записів, наприклад, за допомогою -<number>, щоб показати лише потрібну кількість останніх записів.

$ git log -p -1
commit 8b755eb400a1db7f88ca2058094321dcefea7f9c (HEAD -> feature/vcs, origin/feature/vcs)
Author: Serhii Horodilov <sgorodil@gmail.com>
Date:   Wed Aug 16 15:26:39 2023 +0300

    Update gitflow diagram

diff --git a/assets/mermaid/git/gitflow.mmd b/assets/mermaid/git/gitflow.mmd
index 6287bbb..4e4eab7 100644
--- a/assets/mermaid/git/gitflow.mmd
+++ b/assets/mermaid/git/gitflow.mmd
@@ -19,8 +19,6 @@ gitGraph
     commit
     branch feature/C
     commit
-    commit
-    commit

 %% working with hotfix branch
     checkout hotfix
@@ -35,7 +33,6 @@ gitGraph
 %% working with feature-b branch
     checkout feature/A
     commit
-    commit
     checkout develop
     merge feature/A
 %% work with feature-a branch

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

Якщо ви хочете побачити скорочену статистику для кожного коміту, ви можете скористатися опцією --stat:

$ git log -1 --stat
commit 8b755eb400a1db7f88ca2058094321dcefea7f9c (HEAD -> feature/vcs, origin/feature/vcs)
Author: Serhii Horodilov <sgorodil@gmail.com>
Date:   Wed Aug 16 15:26:39 2023 +0300

    Update gitflow diagram

 assets/mermaid/git/gitflow.mmd | 3 ---
 1 file changed, 3 deletions(-)

commit 1e131a0c9faee2a22ea2bae8f31f8c7ee04fefc5
Author: Serhii Horodilov <sgorodil@gmail.com>
Date:   Wed Aug 16 14:46:39 2023 +0300

    fixup! Add translations to VSC documents

 src/_locales/uk/LC_MESSAGES/vcs.po | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Ще одним дійсно корисним параметром є --pretty. Цей параметр змінює формат виведення журналу на формат, відмінний від стандартного. Ви можете скористатися кількома готовими значеннями цього параметра. Значення oneline для цього параметра виводить кожну фіксацію в одному рядку, що є корисним, якщо ви переглядаєте багато фіксацій. Крім того, значення short, full і fuller показують виведення у приблизно однаковому форматі, але з меншою або більшою кількістю інформації.

$ git log --pretty=oneline
8b755eb400a1db7f88ca2058094321dcefea7f9c (HEAD -> feature/vcs, origin/feature/vcs) Update gitflow diagram
1e131a0c9faee2a22ea2bae8f31f8c7ee04fefc5 fixup! Add translations to VSC documents
895dc24343fbbe25c3c94b25091ac64ac8aea53d Add translations to VSC documents
30cb1a2db3d62210010b05df634e1ec87e5ef748 Fix apostrophe for VCS files
79427a88defef82bc92482cfaf7da5fba3260f5e Add commit document (draft)
0786a699e6901a6c968090422b3cec789402ad21 Update branches document
74710531809a9cbbdec1979ef8ae775a034c2027 Fixed GitFlow branches list
$ git log -10 --pretty=format:"%h - %an - %ad"
8b755eb - Serhii Horodilov - Wed Aug 16 15:26:39 2023 +0300
1e131a0 - Serhii Horodilov - Wed Aug 16 14:46:39 2023 +0300
895dc24 - Serhii Horodilov - Wed Aug 16 14:42:10 2023 +0300
30cb1a2 - Serhii Horodilov - Wed Aug 16 14:41:49 2023 +0300
79427a8 - Serhii Horodilov - Mon Jul 31 14:31:08 2023 +0300
0786a69 - Serhii Horodilov - Mon Jul 31 14:30:54 2023 +0300
7471053 - Serhii Horodilov - Fri Jul 28 15:13:15 2023 +0300
be60eb3 - Serhii Horodilov - Fri Jul 28 14:54:09 2023 +0300
24972b1 - Serhii Horodilov - Fri Jul 28 14:53:37 2023 +0300
4a9cfe4 - Serhii Horodilov - Fri Jul 28 14:32:53 2023 +0300

Специфікатор

Опис Результатів

%H

Хеш комміту

%h

Скорочений хеш коміту

%T

Дерево хешу

%t

Скорочений хеш дерева

%P

Батьківські хеші

%p

Скорочені батьківські хеші

%an

Ім’я автора

%ae

Електронна пошта автора

%ad

Дата автора (формат відповідає параметру –date=option)

%ar

Дата автора, відносна

%cn

Ім’я коммітера

%ce

Електронна пошта коммітера

%cd

Дата коммітера

%cr

Дата коммітера, відносна

%s

Тема

Значення параметрів online і format особливо корисні з іншим параметром log, який називається --graph. Цей параметр додає невеликий гарний графік у форматі ASCII, який показує історію ваших гілок і злиття:

$ git log --pretty=format:"%h %s" --graph
* f9b988f Created base documentation structure
* 3fabf55 Started global course updated
*   06662ae Merge pull request #13 from edu-python-course/master
|\
| * 3579eea Update to suite edu-python-course/blog#74
|/
*   3fb7725 Merge remote-tracking branch 'origin/master'
|\
| *   181b66d Merge remote-tracking branch 'origin/master'
| |\
| * | 52e0ef8 add lesson21 hw
* | | 830a246 fix lesson32 hw
| |/
|/|
* | 59697e9 fix lesson2 typos
* | a6f77db fix lesson2 typos
* | 213b220 fix lesson2 typos
* | 9b69f5f fix lesson2 typos
* | 6a0b9c8 fix lesson2 typos
|/
* bda497f add lesson2

Існує набагато більше варіантів форматування виводу для git log. Загальними параметрами git log є наступні:

Опція

Опис

-p

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

–stat

Показувати статистику для файлів, змінених у кожному коміті.

–shortstat

Відображати лише змінений/вставлений/видалений рядок з команди –stat.

–name-only

Показати список файлів, змінених після фіксації інформації.

–name-status

Також покажіть список файлів, яких торкнулася додана/змінена/видалена інформація.

–abbrev-commit

Показувати лише перші кілька символів контрольної суми SHA-1 замість усіх 40.

–relative-date

Відображати дату у відносному форматі (наприклад, «2 тижні тому») замість повного формату дати.

–graph

Відобразити ASCII-графік гілки та історію злиття поряд з виведенням журналу.

–pretty

Показувати комміти в альтернативному форматі. Значення опції включають: online, short, full, fuller і format (де ви можете вказати свій власний формат).

–oneline

Скорочення для –pretty=online –abbrev-commit, що використовується разом.

Обмеження виводу журналу

На додаток до параметрів форматування виводу, git log приймає ряд корисних обмежувальних параметрів, тобто параметрів, які дозволяють вам показувати лише підмножину коммітів. Ви вже бачили одну з таких опцій - -<число> (наприклад, -2 або -10), яка показує лише вказану кількість останніх коммітів.

$ git log -5 --oneline
db87ca0 (HEAD -> feature/vcs) fixup! Add commit history section (git log)
df9d599 Add commit history section (git log)
8b755eb (origin/feature/vcs) Update gitflow diagram
1e131a0 fixup! Add translations to VSC documents
895dc24 Add translations to VSC documents

Однак, дуже корисними є опції, що обмежують час, такі як --since і --until. Наприклад, команда для отримання списку коммітів, зроблених за останні два тижні:

$ git log --since=2.weeks

Ця команда працює з багатьма форматами - ви можете вказати конкретну дату, наприклад, "2022-02-24", або відносну дату, наприклад, "2 роки 1 день 3 хвилини тому".

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

$ git log --oneline -- src/vcs/basics.txt
30cb1a2 Fix apostrophe for VCS files
4a9cfe4 Move mermaid diagrams to a dedicated folder (git)
80a1ab3 Add branching and merging document
3978779 Add committing changes section
a40712a Add git ignore section
e92b12f Add making changes section
c23f8ff Update getting repository section
582569d Add Git basics document (draft)

Виправлення помилок

На будь-якому етапі ви можете захотіти щось виправити.

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

$ git commit --amend

Наприклад.

$ git commit -m "Initial commit"
$ git add forgotten_file
$ git commit --amend

Скасування додавання файла до індексу

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

$ git add *
$ git status
On branch master

Changes to be committed:
    (use "git reset HEAD <file>..." to unstage)
        renamed: README.md -> README
        modified: CONTRIBUTING.md
$ git reset HEAD CONTRIBUTING.md
Unstaged changes after reset:
M CONTRIBUTING.md
$ git status
On branch master

Changes to be committed:
    (use "git reset HEAD <file>..." to unstage)
        renamed: README.md -> README

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: CONTRIBUTING.md

Скасування модифікації зміненого файлу

Що робити, якщо ви зрозуміли, що не хочете зберігати зміни у якомусь файлі? Ви можете легко скасувати зміни - повернути його до того, як він виглядав під час останнього компонування. git status також покаже вам, як це зробити:

(use "git checkout -- <file>..." to discard changes in working directory)

Він досить чітко розповідає, як відкинути зміни, які ви зробили.

$ git checkout -- CONTRIBUTING.md
$ git status
On branch master

Changes to be committed:
    (use "git reset HEAD <file>..." to unstage)
        renamed: README.md -> README

Скасування змін за допомогою git restore

Нове в версії 2.23.0: git restore є альтернативою git reset, починаючи з версії 2.23.0, Git використовуватиме git restore замість git reset для багатьох операцій скасування.

$ git add *
$ git status
On branch master

Changes to be committed:
    (use "git restore --staged <file>..." to unstage)
        modified: CONTRIBUTING.md
        renamed: README.md -> README
$ git restore --staged CONTRIBUTING.md
$ git status
On branch master

Changes to be committed:
    (use "git restore --staged <file>..." to unstage)
        renamed: README.md -> README

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: CONTRIBUTING.md
$ git restore CONTRIBUTING.md
$ git status
On branch master

Changes to be committed:
    (use "git restore --staged <file>..." to unstage)
        renamed: README.md -> README

Важливо

Важливо розуміти, що відновлення git’ом <файлу> є небезпечною командою. Усі локальні зміни, які ви зробили у цьому файлі, буде втрачено - Git просто замінить цей файл на останню версію, що перебуває у стадії виконання або фіксації. Ніколи не використовуйте цю команду, якщо ви точно не знаєте, що вам не потрібні ці незбережені локальні зміни.