Git
Chapters ▾ 2nd Edition

5.3 Розподілений Git - Супроводжування проекту

Супроводжування проекту

Окрім знань щодо того, як ефективно зробити внесок до проекту, вам можливо знадобиться вміння його супроводжувати. Це може включати прийняття та застосування латок, які були згенеровані format-patch та надіслані вам поштою, або інтегрування змін з віддалених гілок для сховищ, які ви додали як віддалене для вашого проекту. Чи ви супроводжуєте канонічний репозиторій, чи бажаєте допомогти перевіряти або схвалювати латки, вам треба знати, як приймати роботу в спосіб, який є найзрозумілішим для інших учасників та щоб ви були в змозі підтримувати його у майбутньому.

Робота з тематичними гілками

Коли ви збираєтесь інтегрувати нову роботу, зазвичай слушно випробувати її в тематичній гілці — тимчасова гілка, спеціально створена для перевірки нової роботи. У такому разі буде легко окремо налаштовувати латку та облишити її, якщо вона не працює, доки не зʼявиться час, щоб повернутися до неї. Якщо ви виберете просте імʼя для гілки, повʼязане з тематикою роботи, яку ви збираєтесь випробувати, наприклад ruby_client чи щось не менш змістовне, то легко зможете пригадати назву гілки, якщо ви покинули її на деякий час та вирішили повернутись до неї пізніше. Супроводжувач проекту Git переважно також розподіляє ці гілки за просторами імен — на кшталт sc/ruby_client, де sc є скороченням від імені автора роботи. Як ви памʼятаєте, можна відгалузити гілку від master таким чином:

$ git branch sc/ruby_client master

Або, якщо ви бажаєте відразу до неї переключитися, то можете використати checkout -b:

$ git checkout -b sc/ruby_client master

Тепер ви готові додати отриманий внесок до цієї тематичної гілки та визначити, чи варто це зливати до довготриваліших гілок.

Застосування латок, отриманих поштою

Якщо ви отримали латку через електронну пошту та потрібно її інтегрувати до проекту, то треба застосувати латку в тематичній гілці, щоб перевірити її. Є два методи застосувати надіслану латку: за допомогою git apply або git am.

Застосування латки за допомогою apply

Якщо ви отримали латку від когось, хто згенерував її командою git diff або якимось різновидом Unix diff (не рекомендовано; дивіться наступну підсекцію), то її можна застосувати за допомогою команди git apply. Припускаючи, що латку збережено в /tmp/patch-ruby-client.patch, її можна застосувати наступним чином:

$ git apply /tmp/patch-ruby-client.patch

Це змінює файли у вашій робочій директорії. Це майже те саме, що виконати команду patch -p1, щоб застосувати латку, хоча вона є більш параноїдною та приймає менше невизначених збігів, ніж patch. Вона також опрацьовує додавання, вилучення та перейменування файлів, якщо вони описані в форматі git diff, чого patch не зробить. Нарешті, git apply працює за принципом “застосувати все або скасувати все”: буде застосовано все або нічого, у той час як patch може частково застосувати латки, залишивши робочу директорію в дивному стані. Загалом git apply набагато консервативніша, ніж patch. Вона не створить для вас коміт — після виконання, вам доведеться індексувати та зберегти нові зміни вручну.

Ви також можете використати git apply, щоб побачити, чи латка може бути застосована чисто перед тим, як власно намагатись справді застосувати її — ви можете виконати git apply --check з латкою:

$ git apply --check 0001-seeing-if-this-helps-the-gem.patch
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply

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

Застосування латки за допомогою am

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

Щоб застосувати латку, що її згенерувала format-patch, скористуйтесь git am (команда називається am, бо використовується, щоб застосувати (apply) низку латок з поштової скриньки (mailbox)). Технічно, git am створено щоб прочитати файл mbox, що є простим, текстовим форматом для збереження одного чи більше поштових повідомлень в одному текстовому файлі. Виглядає він приблизно так:

From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
From: Jessica Smith <jessica@example.com>
Date: Sun, 6 Apr 2008 10:17:23 -0700
Subject: [PATCH 1/2] add limit to log function

Limit log functionality to the first 20

Це початок виводу команди git format-patch, яку ви бачили у попередній секції, а також відповідає поштовому формату mbox. Якщо хтось правильно надіслав вам латку, використовуючи git send-email, та ви завантажили її у форматі mbox, то ви можете вказати git am цей mbox файл, та він розпочне застосовувати всі латки, які зустріне. Якщо ви користуєтесь поштовим клієнтом, який може зберегти декілька листів у mbox форматі, то можете зберегти всю послідовність латок до одного файлу, а потім використати git am щоб застосувати їх усіх по одній.

Втім, якщо хтось відвантажив файл латки, який згенерував git format-patch, до системи завдань (ticketing system) чи чогось подібного, то файл можна зберегти локально та потім передати його з вашого диску до git am для застосування:

$ git am 0001-limit-log-function.patch
Applying: add limit to log function

Як бачите, команда чисто застосувала та автоматично створила новий коміт для вас. Інформація про автора взята зі заголовків листа From та Date, а повідомлення коміту взято зі Subject та тіла (перед латкою) листа. Наприклад, якби латка застосовувалась з наведеного вище прикладу mbox, згенерований коміт виглядав би приблизно так:

$ git log --pretty=fuller -1
commit 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
Author:     Jessica Smith <jessica@example.com>
AuthorDate: Sun Apr 6 10:17:23 2008 -0700
Commit:     Scott Chacon <schacon@gmail.com>
CommitDate: Thu Apr 9 09:19:06 2009 -0700

   add limit to log function

   Limit log functionality to the first 20

Інформація Commit містить людину, яка застосувала латку та час застосування. Інформація Author — особу, яка оригінально створила латку та коли це було зроблено.

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

$ git am 0001-seeing-if-this-helps-the-gem.patch
Applying: seeing if this helps the gem
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
Patch failed at 0001.
When you have resolved this problem run "git am --resolved".
If you would prefer to skip this patch, instead run "git am --skip".
To restore the original branch and stop patching run "git am --abort".

Ця команда додає позначки конфліктів до всіх файлів, з якими в неї є проблеми — так само, як при конфліктах злиття чи перебазування. Ви розв’язуєте ці проблеми так само — редагуєте файл, щоб розв’язати конфлікт, індексуєте оновлений файл, а потім виконуєте git am --resolved, щоб продовжити з наступною латкою:

$ (fix the file)
$ git add ticgit.gemspec
$ git am --resolved
Applying: seeing if this helps the gem

Якщо ви бажаєте, щоб Git спробував поводитись трохи розумніше при розв’язуванні конфлікту, то можете передати опцію -3, з якою Git спробує три-точкове злиття (three-way merge). Ця опція типово не ввімкнена, адже вона не працює, якщо коміту, на якому базується латка, немає у вашому репозиторії. Якщо ви маєте цей коміт — якщо латка базувалася на публічному коміті — то зазвичай опція -3 набагато кмітливіше застосовує конфліктну латку.

$ git am -3 0001-seeing-if-this-helps-the-gem.patch
Applying: seeing if this helps the gem
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
No changes -- Patch already applied.

У цьому випадку без опції -3 латка викликала б конфлікт. Але з опцією -3 латка застосовується без помилок.

Якщо ви застосовуєте декілька латок з mbox, ви також можете виконати команду am в інтерактивному режимі, який зупиняється після кожної знайденої латки та питає, чи варто її застосовувати:

$ git am -3 -i mbox
Commit Body is:
--------------------------
seeing if this helps the gem
--------------------------
Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all

Це зручно, якщо у вас збережено низку латок, адже ви можете спочатку переглянути латку, якщо не пам’ятаєте про що вона, або не застосовувати вже застосовані латки.

Коли всі латки для вашої гілки застосовані та збережені в комітах гілки, ви можете вибрати, як інтегрувати їх до довгостроковіших гілок.

Отримання віддалених гілок

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

Наприклад, якщо Джесіка надсилає вам листа, в якому розповідає про чудовий новий функціонал у гілці ruby-client її сховища, то ви можете подивитись на них, якщо додасте віддалене сховище та отримаєте цю гілку локально:

$ git remote add jessica git://github.com/jessica/myproject.git
$ git fetch jessica
$ git checkout -b rubyclient jessica/ruby-client

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

Це найзручніше, якщо ви працюєте з кимось постійно. Якщо ж це подеколи єдина латка для внеску, то на прийняття її листом може піти менше часу, ніж вимагати від когось мати власний сервер та постійно додавати та вилучати віддалені сховища задля отримання нових латок. Також, навряд чи вам сподобається мати сотні віддалених репозиторіїв, у кожен з яких було додано лише одну чи дві латки. Втім, скрипти та сервіси розгортання (hosted services) можуть полегшити це — переважно все залежить від того, як працюєте ви, та як працюють автори внесків.

Інша перевага цього підходу в тому, що ви також отримуєте історію комітів. Хоча у вас можуть бути справжні проблеми злиття, ви будете знати на чому з вашої історії вони базуються; належне три-точкове злиття є типовим — немає необхідності додавати -3 та сподіватись, що латку було згенеровано на базі публічного коміту, до якого ви маєте доступ.

Якщо ви не співпрацюєте з людиною постійно, проте все одно бажаєте отримати зміни в такий спосіб, то можете надати URL віддаленого сховища команді git pull. Це робить одноразове отримання змін та не зберігає URL як посилання на віддалений репозиторій:

$ git pull https://github.com/onetimeguy/project
From https://github.com/onetimeguy/project
 * branch            HEAD       -> FETCH_HEAD
Merge made by the 'recursive' strategy.

Як дізнатися, що додано

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

Буває корисним переглянути всі коміти, які є в поточній гілці, проте яких немає в гілці master. Коміти з головної гілки можна виключити за допомогою опції --not перед ім’ям гілки. Це робить те саме, що й формат master..contrib, що ми його використовували раніше. Наприклад, якщо вам надіслано дві латки та ви створили гілку під назвою contrib та застосували їх до неї, то можете виконати:

$ git log contrib --not master
commit 5b6235bd297351589efc4d73316f0a68d484f118
Author: Scott Chacon <schacon@gmail.com>
Date:   Fri Oct 24 09:53:59 2008 -0700

    seeing if this helps the gem

commit 7482e0d16d04bea79d0dba8988cc78df655f16a0
Author: Scott Chacon <schacon@gmail.com>
Date:   Mon Oct 22 19:38:36 2008 -0700

    updated the gemspec to hopefully work better

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

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

$ git diff master

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

Якщо master є прямим предком тематичної гілки, то це не буде проблемою; проте якщо ці дві історії розійшлися, різниця виглядатиме ніби ви додаєте все нове зі своєї тематичної гілки та видаляєте все, що зʼявилося лише в гілці master.

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

Технічно, ви можете зробити це явно зʼясувавши спільного предка та виконавши diff з ним:

$ git merge-base contrib master
36c7dba2c95e6bbb78dfa822519ecfec6e1ca649
$ git diff 36c7db

чи, стисліше:

$ git diff $(git merge-base contrib master)

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

$ git diff master...contrib

Ця команда показує лише зроблене у поточній тематичній гілці після спільного з master предка. Цей синтаксис дійсно варто запамʼятати.

Інтеграція внеску

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

Процеси роботи зливання

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

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

Історія з декількома тематичними гілками.
Figure 72. Історія з декількома тематичними гілками.
Після злиття тематичної гілки.
Figure 73. Після злиття тематичної гілки.

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

Якщо у вас достатньо важливий проект, то можна скористатися двофазним циклом зливання. У цьому сценарії, у вас є дві довгострокові гілки: master та develop. Ви домовляєтесь оновлювати master лише коли зʼявляється дуже стабільна версія, а весь новий код інтегрується до гілки develop. Ви регулярно надсилаєте зміни до обох цих гілок до публічного сховища. Щоразу, коли виникає готова до злиття тематична гілка (Перед злиттям тематичної гілки.), ви зливаєте її до develop (Після злиття тематичної гілки.); потім, коли ви створите теґ перевіреної версії, то перемотуєте вперед master до останнього коміту тепер стабільного develop (Після випуску проекту.).

Перед злиттям тематичної гілки.
Figure 74. Перед злиттям тематичної гілки.
Після злиття тематичної гілки.
Figure 75. Після злиття тематичної гілки.
Після випуску проекту.
Figure 76. Після випуску проекту.

Таким чином, коли хтось створює клон сховища вашого проекту, вони можуть або отримати master, щоб зібрати останню стабільну версію та легко оновлюватись, або можуть отримати develop, в якому зміст найновіше. Ви також можете розширити цю концепцію: додати гілку integrate, в якій вся робота зливається разом. Потім, коли код у цій гілці стає стабільним та проходитиме тести, ви зливаєте її до гілки develop; а вже коли вона дійсно довела свою стабільність, ви перемотуєте вперед гілку master.

Процеси роботи великих зливань

Проект Git має чотири довгострокових гілки: master, next та pu (proposed updates — пропоновані оновлення) для нової роботи, та main для виправлень старших версій. Коли учасники впроваджують щось нове, воно накопичується в тематичних гілках у сховищі супроводжувача — схоже на вищеописані методи (дивіться Керування складною послідовністю паралельних доданих тематичних гілок.). Потім тематичні гілки перевіряють, щоб визначити, чи вони є безпечними та готовими для використання, чи треба ще над ними працювати. Якщо вони безпечні, їх зливають до next, і цю гілку надсилають до сервера, аби всі могли спробувати злити тематичні гілки разом.

Керування складною послідовністю паралельних доданих тематичних гілок.
Figure 77. Керування складною послідовністю паралельних доданих тематичних гілок.

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

Зливання доданих тематичних гілок до довготривалих інтеграційних гілок.
Figure 78. Зливання доданих тематичних гілок до довготривалих інтеграційних гілок.

Коли тематичну гілку нарешті зливають до master, її вилучать з репозиторія. Проект Git також містить гілку main, яка відгалужена від останнього видання (release), щоб постачати латки до цієї версії, якщо необхідно супроводження цього видання. Отже, коли ви робите клон сховища Git, у вас є чотири гілки, на які ви можете переключитися, щоб випробувати проект на різних щаблях розробки, в залежності від того, наскільки новітня версія вам потрібна, чи яким чином ви бажаєте зробити внесок; та супроводжувач має структурований процес роботи, щоб йому було зручно оцінити нових учасників. Процес роботи проекту Git дуже спеціалізований. Щоб добре це зрозуміти, можете поглянути на Інструкцію супроводжувача Git.

Процеси роботи з перебазуванням та висмикуванням

Інші супроводжувачі надають перевагу перебазуванню та висмикуванню нової роботи поверху їхньої гілки master, замість зливання до неї, задля якомога лінійнішої історії. Коли у вас є робота в тематичній гілці, та ви вирішили, що бажаєте її інтегрувати, ви переходите до цієї гілки та виконуєте команду rebase, щоб перебудувати зміни поверху вашої поточної гілки master (або develop тощо). Якщо все вийшло добре, ви можете перемотати вперед свою гілку master, та отримаєте лінійну історію проекту.

Інший спосіб перемістити впроваджену роботу з однієї гілки до іншої — висмикнути її. Висмикування в Git — це ніби перебазування для єдиного коміту. Воно бере латку, яку запровадив коміт, та намагається застосувати його на поточній гілці. Це корисно, якщо у вас є декілька комітів у тематичній гілці, та ви бажаєте інтегрувати лише один з них, або якщо у вас лише один коміт у тематичній гілці, та вам легше висмикнути його, ніж виконувати перебазування. Наприклад, припустимо, що у вас є ось такий проект:

Приклад історії перед висмикуванням.
Figure 79. Приклад історії перед висмикуванням.

Якщо ви бажаєте додати коміт e43a6 до гілки master, ви можете виконати

$ git cherry-pick e43a6
Finished one cherry-pick.
[master]: created a0a41a9: "More friendly message when locking the index fails."
 3 files changed, 17 insertions(+), 3 deletions(-)

Це додає ті ж зміни, що були впроваджені в e43a6, проте ви отримуєте нове значення SHA-1 коміту, адже дата застосування інша. Тепер історія виглядає так:

Історія після висмикування коміту з тематичної гілки.
Figure 80. Історія після висмикування коміту з тематичної гілки.

Тепер ви можете вилучити тематичну гілку та викинути коміти, які ви не бажали додавати.

Rerere

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

Rerere означає “використовуй записані розвʼязання” (reuse recorded resolution) — це метод скоротити ручні розвʼязання конфліктів. Коли rerere ввімкнено, Git зберігає набір відбитків станів до та після успішних зливань, та, якщо бачить конфлікт, який виглядає саме так, як якийсь вже розвʼязаний, він просто використає попереднє розвʼязання, і не буде вас ним турбувати.

У цієї функції є дві частини: налаштування та команда. Налаштування називається rerere.enabled, та є достатньо корисним, щоб додати його до вашої глобальної конфігурації:

$ git config --global rerere.enabled true

Тепер, щоразу як ви робите зливання, яке розвʼязує конфлікти, розвʼязання буде збережено в памʼяті на випадок, якщо воно знадобиться в майбутньому.

Якщо потрібно, ви можете взаємодіяти з памʼяттю rerere за допомогою команди git rerere. Якщо викликати окремо, Git перевіряє базу даних розвʼязань та намагається знайти збіг з будь-яким поточним конфліктом злиття та розвʼязує їх (хоча це здійснюється автоматично, якщо rerere.enabled встановлено в true). Також існують підкоманди, для перегляду того, що буде записано, для стирання окремого розвʼязання з памʼяті, та щоб очистити всю памʼять. Ми розглянемо rerere докладніше в Rerere.

Теґування ваших видань (release)

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

$ git tag -s v1.5 -m 'my signed 1.5 tag'
You need a passphrase to unlock the secret key for
user: "Scott Chacon <schacon@gmail.com>"
1024-bit DSA key, ID F721C45A, created 2009-02-09

Якщо ви підписуєте свої теґи, то може виникнути проблема розповсюдження публічних ключів PGP, який використовується для підписання теґів. Супроводжувач проекту Git впорався з цією проблемою: включив публічний ключ як блоб в сховищі, та додав теґ, який вказує прямо на його вміст. Щоб це зробити, ви можете зрозуміти, який ключ вам потрібен за допомогою gpg --list-keys:

$ gpg --list-keys
/Users/schacon/.gnupg/pubring.gpg
---------------------------------
pub   1024D/F721C45A 2009-02-09 [expires: 2010-02-09]
uid                  Scott Chacon <schacon@gmail.com>
sub   2048g/45D02282 2009-02-09 [expires: 2010-02-09]

Потім, ви можете напряму імпортувати ключ до бази даних Git, якщо експортуєте його та пропустити через команду git hash-object, яка записує новий блоб з його вмістом до Git та видає SHA-1 цього блобу:

$ gpg -a --export F721C45A | git hash-object -w --stdin
659ef797d181633c87ec71ac3f9ba29fe5775b92

Тепер вміст вашого ключу є в Git, ви можете створити теґ, який вказує прямо на нього, якщо вкажете нове значення SHA-1, яке надала нам команда hash-object.

$ git tag -a maintainer-pgp-pub 659ef797d181633c87ec71ac3f9ba29fe5775b92

Якщо виконати git push --tags, то теґ maintainer-pgp-pub стане доступним всім. Якщо хтось забажає перевірити теґ, то він зможе напряму імпортувати ваш PGP ключ. Для цього йому треба дістати блоб напряму з бази даних та імпортувати його до GPG:

$ git show maintainer-pgp-pub | gpg --import

Він зможе використати ключ щоб перевірити всі підписані теґи. Також, якщо ви включите інструкції в повідомлення теґу, то виконання git show <теґ> дозволить вам надати користувачу більш детальні інструкції щодо перевірки теґу.

Генерація номеру збірки

Оскільки Git не має монотонно зростаючих номерів як v123 чи чогось подібного для кожного коміту, якщо ви бажаєте мати зручне для людини імʼя для коміту, ви можете виконати git describe для цього коміту. Git надає вам імʼя найближчого теґу разом з кількістю комітів поверху цього теґу, а також часткове значення SHA-1 для описаного коміту:

$ git describe master
v1.6.2-rc1-20-g8c5b85c

Таким чином, ви можете експортувати відбиток чи збірку та назвати його якось зрозуміло для людей. Насправді, якщо ви зберете Git з вихідного коду з клону сховища Git, то git --version надає вам щось дуже схоже. Якщо ви описуєте коміт, для котрого існує прямий теґ, то вам надається просто імʼя цього теґу.

Команда git describe схиляється до анотованих теґів (теґи, що їх створили з опцією -a або -s), отже теґи для видань (release) варто створювати таким чином при використанні git describe, щоб бути впевненим, що коміт буде названо належним чином при описі. Ви також можете використати цей рядок як ціль для команд checkout або show, хоча вона покладається на скорочене значення SHA-1 наприкінці, отже воно може не бути дійсним завжди. Наприклад, ядро Linux нещодавно стрибнуло з 8 до 10 символів, щоб подбати про унікальність SHA-1 обʼєктів, отже старіші імена з виводу git describe стали непридатними.

Підготовка видань

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

$ git archive master --prefix='project/' | gzip > `git describe master`.tar.gz
$ ls *.tar.gz
v1.6.2-rc1-20-g8c5b85c.tar.gz

Якщо хтось відкриє цей архів tar, то отримає останній відбиток вашого проекту в директорії проекту. Ви також можете створити архів zip майже так само — треба лише передати опцію --format=zip до git archive:

$ git archive master --prefix='project/' --format=zip > `git describe master`.zip

Тепер у вас є гарний архів tar та zip вашого видання проекту, яке ви можете відвантажити на вебсайт або надіслати комусь поштою.

Короткий журнал (shortlog)

Настав час написати до вашої поштової розсилки всім бажаючим знати, що коїться у вашому проекті. Чудовий спосіб швидко отримати короткий журнал змін, які були додані до проекту після попереднього видання — використати команду git shortlog. Вона робить підсумок всіх комітів з наданих їй комітів; наприклад, наступне надає вам підсумок всіх комітів після останнього видання, якщо воно називається v1.0.1:

$ git shortlog --no-merges master --not v1.0.1
Chris Wanstrath (8):
      Add support for annotated tags to Grit::Tag
      Add packed-refs annotated tag support.
      Add Grit::Commit#to_patch
      Update version and History.txt
      Remove stray `puts`
      Make ls_tree ignore nils

Tom Preston-Werner (4):
      fix dates in history
      dynamic version method
      Version bump to 1.0.2
      Regenerated gemspec for version 1.0.2

Ви отримуєте чистий підсумок всіх комітів після v1.0.1, згруповані за автором, який ви можете надіслати до вашої розсилки.