zwischendurch
[gitmagic.git] / uk / grandmaster.txt
blob00f9a79e7bae25967d394a10343b1acfcefc7329
1 == Гросмейстерство Git ==
3 Тепер ви вже повинні вміти орієнтуватися в сторінках *git help* і розуміти майже все. Однак точний вибір команди, необхідної для вирішення конкретної проблеми, може бути виснажливим. Можливо, я збережу вам трохи часу: нижче наведені рецепти, які знадобилися мені в минулому.
5 === Релізи вихідних кодів ===
7 У моїх проектах Git управляє в точності тими файлами, які я збираюся архівувати і пускати в реліз. Щоб створити тарбол з вихідними кодами, я виконую:
9  $ git archive --format=tar --prefix=proj-1.2.3/ HEAD
11 === Комміт змін ===
13 У деяких проектах може бути трудомістким повідомляти Git про кожне додавання, видаленні та перейменування файлу. Замість цього ви можете виконати команди
15  $ git add .
16  $ git add -u
18 Git прогляне файли в поточному каталозі і сам подбає про деталі. Замість другої команди add, виконайте `git commit -a`, якщо ви збираєтеся відразу зробити комміт. Дивіться * git help ignore *, щоб дізнатися як вказати файли, які повинні ігноруватися.
20 Ви можете виконати все це одним махом:
22  $ git ls-files -d -m -o -z | xargs -0 git update-index --add --remove
24 Опції *-z* і *-0* запобігають невірну обробку файлових імен, що містять спеціальні символи. Оскільки ця команда додає ігноровані файли, ви можливо захочете використовувати опції `-x` або `-X`.
26 === Мій комміт занадто великий ===
28 Ви нехтували коммітамі занадто довго? Затято писали код і згадали про управління вихідними кодами тільки зараз? Внесли ряд незв'язаних змін, тому що це ваш стиль?
30 Немає причин для занепокоєння. Виконайте
32  $ git add -p
34 Для кожної зробленої вами правки Git покаже змінену ділянку коду і запитає, чи повинна ця зміна потрапити в наступний комміт. Відповідайте "y" (так) або "n" (ні). У вас є й інші варіанти, наприклад відкласти вибір; введіть "?" Щоб дізнатися більше.
36 Коли закінчите, виконайте
38  $ git commit
40 для внесення саме тих правок, що ви вибрали ('буферизованих' змін). Переконайтеся, що ви не вказали опцію *-a*, інакше Git закоммітить всі правки.
42 Що робити, якщо ви змінили безліч файлів в багатьох місцях? Перевірка кожної окремої зміни стає обтяжливою рутиною. У цьому випадку використовуйте *git add -i*. Її інтерфейс не такий простий, але більш гнучкий. У декілька натискань можна додати або прибрати з буфера кілька файлів одночасно, або переглянути і вибрати зміни лише в окремих файлах. Як варіант, запустіть *git commit \--interactive*, яка автоматично зробить комміт коли ви закінчите.
44 === Індекс — буферна зона Git ===
46 До цих пір ми уникали знаменитого 'індексу' Git, але тепер ми повинні розглянути його, для пояснення вищесказаного. Індекс це тимчасовий буфер. Git рідко переміщує дані безпосередньо між вашим проектом і його історією. Замість цього Git спочатку записує дані в індекс, а вже потім копіює їх з індексу за місцем призначення.
48 Наприклад, *commit -a* насправді двоетапний процес. Спочатку зліпок поточного стану кожного з відстежуваних файлів поміщається в індекс. Потім зліпок, що знаходиться в індексі, записується в історію. Комміт без опції *-a* виконує тільки другий крок, і має сенс тільки після виконання команд, що змінюють індекс, таких як *git add*.
50 Зазвичай ми можемо не звертати уваги на індекс і робити вигляд, що взаємодіємо безпосередньо з історією. Але в даному випадку ми хочемо більш тонкого контролю, тому управляємо індексом. Ми поміщаємо зліпок деяких (але не всіх) наших змін в індекс, після чого остаточно записуємо цей акуратно сформований зліпок.
52 === Не втрачай "голови" ===
54 Тег HEAD подібний курсору, який зазвичай вказує на останній комміт, просуваючись з кожним новим коммітом. Деякі команди Git дозволяють переміщати цей курсор. Наприклад,
56  $ git reset HEAD~3
58 перемістить HEAD на три комміти назад. Тепер всі команди Git будуть працювати так, ніби ви не робили останніх трьох коммітів, хоча файли залишаться в поточному стані. У довідці описано кілька способів використання цього прийому.
60 Але як повернутися назад у майбутнє? Адже попередні комміти про нього нічого не знають.
62 Якщо у вас є SHA1 вихідної "голови", то:
64  $ git reset 1b6d
66 Але припустимо, ви його не записували. Не турбуйтеся: для комнад такого роду Git зберігає оригінальну "голову" як тег під назвою ORIG_HEAD, і ви можете повернутися надійно і безпечно:
68  $ git reset ORIG_HEAD
70 === Полювання за "головами" ===
72 Припустимо ORIG_HEAD недостатньо. Приміром, ви тільки що усвідомили, що допустили величезну помилку, і вам потрібно повернутися до давнього комміту в давно забутій гілці.
74 За замовчуванням Git зберігає комміти не менше двох тижнів, навіть якщо ви наказали знищити гілку, що їх містить. Проблема в знаходженні відповідного хешу. Ви можете проглянути всі значення хешів в `.git/objects` і методом проб та помилок знайти потрібний. Але є шлях значно легший.
76 Git записує кожен підрахований ним хеш комміта в `.git/logs`. У підкаталозі `refs` міститься повна історія активності на всіх гілках, а файл `HEAD` містить кожне значення хешу, яке коли-небудь приймав HEAD. Останній можна використовувати щоб ​​знайти хеши коммітів на випадково обрубаних гілках.
78 Команда reflog надає зручний інтерфейс роботи з цими журналами. Використовуйте
80  $ git reflog
82 Замість копіювання хешів з reflog, спробуйте
84  $ git checkout "@{10 minutes ago}"
86 Чи зробіть чекаут п'ятого з кінця з відвіданих коммітів за допомогою
88  $ git checkout "@{5}"
90 Дивіться розділ ``Specifying Revisions'' в *git help rev-parse* для додаткової інформації.
92 Ви можете захотіти подовжити відстрочку для коммітів, приречених на видалення. Наприклад,
94  $ git config gc.pruneexpire "30 days"
96 означає, що комміти, які видаляються, будуть остаточно зникати тільки після 30 днів і після запуску *git gc*.
98 Також ви можете захотіти відключити автоматичний виклик *git gc*:
100  $ git config gc.auto 0
102 У цьому випадку комміти будуть видалятися тільки коли ви будете запускати *git gc* вручну.
104 === Git як основа ===
106 Дизайн Git, в істинному дусі UNIX, дозволяє легко використовувати його як низькорівневий компонент інших програм: графічних та веб-інтерфейсів; альтернативних інтерфейсів командного рядка; інструментів управління патчами; засобів імпорту або конвертації, і так далі. Багато команд Git насправді - скрипти, які стоять на плечах гігантів. Невеликим доопрацюванням ви можете переробити Git на свій смак.
108 Найпростіший трюк — використання аліасів Git для скорочення часто використовуваних команд:
110  $ git config --global alias.co checkout
111  $ git config --global --get-regexp alias       # відображає поточні аліаси
112  alias.co checkout
113  $ git co foo        # те ж саме, що і 'git checkout foo'
115 Інший приклад: можна виводити поточну гілку в запрошенні командного рядка або заголовку вікна терміналу. Запуск
117  $ git symbolic-ref HEAD
119 виводить назву поточної гілки. На практиці ви швидше за все захочете прибрати "refs/heads/" і повідомлення про помилки:
121  $ git symbolic-ref HEAD 2> /dev/null | cut -b 12-
123 Підкаталог +contrib+ — це ціла скарбниця інструментів, побудованих на Git. З часом деякі з них можуть ставати офіційними командами. В Debian та Ubuntu цей каталог знаходиться у +/usr/share/doc/git-core/contrib+.
125 Один популярний інструмент з цього каталогу — +workdir/git-new-workdir+. Цей скрипт створює за допомогою символічних посилань новий робочий каталог, який має спільну історію з оригінальним сховищем:
127  $ git-new-workdir існуюче/сховище новий/каталог
129 Новий каталог і файли в ньому можна сприймати як клон, з тією різницею, що два дерева автоматично залишаються синхронізованими зважаючи на спільну історію. Немає необхідності в merge, push і pull.
131 === Ризиковані трюки ===
133 Нинішній Git робить випадкове знищення даних дуже складним.
134 Але якщо ви знаєте, що робите, ви можете обійти захист для розповсюджених команд.
136 *Checkout*: Наявність незакомміченних змін перериває виконання checkout. Щоб перейти до потрібного комміту, навіть знищивши свої зміни, використовуйте прапор змушування (force) *-f*:
138  $ git checkout -f HEAD^
140 З іншої сторони, якщо ви вкажете checkout конкретні шляхи, перевірки на безпеку не буде: вказані файли мовчки перезапишуть. Будьте обережні при такому використанні checkout.
142 *Reset*: скидання також переривається при наявності незакомміченних змін. Щоб змусити його спрацювати, запустіть
144  $ git reset --hard 1b6d
146 *Branch*: Видалення гілки припиниться, якщо воно призвело б до втрати змін. Для примусового видалення введіть
148  $ git branch -D мертва_гілка # замість -d
150 Аналогічно, спроба перезапису гілки шляхом переміщення буде перервана, якщо може призвести до втрати даних. Для примусового переміщення гілки введіть
152  $ git branch -M джерело ціль # замість -m
154 У відмінності від checkout і reset, ці дві команди дають відстрочку у видаленні даних. Зміни залишаються в каталозі.git і можуть бути повернуті відновленням потрібного хешу з `.git/logs` (дивіться вище розділ "Полювання за головами"). За замовчуванням вони будуть зберігатися принаймні два тижні.
156 *Clean*: Деякі команди можуть не спрацювати через побоювання пошкодити невідслідковувані файли. Якщо ви впевнені, що все невідслідковувані файли і каталоги не потрібні, то безжально видаляйте їх командою
158  $ git clean -f -d
160 Наступного разу ця прикра команда спрацює!
162 === Запобігаємо поганим коммітам ===
164 Дурні помилки забруднюють мої сховища. Найжахливіше це проблема відсутніх файлів, викликана забутим *git add*.
166 Приклади менш серйозних проступків: завершальні пропуски і невирішені конфлікти злиття. Незважаючи на нешкідливість, я не хотів би, щоб це з'являлося в публічних записах.
168 Якби я тільки поставив захист від дурня, використовуючи _хук_, який би попереджав мене про ці проблеми:
170  $ cd .git/hooks
171  $ cp pre-commit.sample pre-commit # В старих версіях Git: chmod +x pre-commit
173 Тепер Git скасує комміт, якщо виявить зайві пробіли або невирішені конфлікти.
175 Для цього керівництва я в кінці кінців додав наступне в початок хука *pre-commit*, щоб захиститися від своєї неуважності:
177 if git ls-files -o | grep '\.txt$'; then
178  echo ПЕРЕРВАНО! Невідслідковувані .txt файли.
179  exit 1
182 Хукі підтримуються кількома різними операціями Git, дивіться *git help hooks*. Ми використовували приклад хука *post-update* раніше, при обговоренні використання Git через http. Він запускався при кожному переміщенні голови. Простий скрипт post-update оновлює файли, які потрібні Git для зв'язку через  засоби повідомлення такі як HTTP.