From 3f7a435c6605932f84c26b22183f238657b6e528 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=D0=92=D0=BE=D0=BB=D0=BE=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20?= =?utf8?q?=D0=91=D0=BE=D0=B4=D0=B5=D0=BD=D1=87=D1=83=D0=BA?= Date: Sat, 13 Oct 2012 00:59:38 +0300 Subject: [PATCH] =?utf8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=BA=D0=BB=D0=B0=D0=B4?= =?utf8?q?=D0=B5=D0=BD=D0=BE=20=D0=B4=D0=BE=2050=20=D1=80=D1=8F=D0=B4?= =?utf8?q?=D0=BA=D0=B0=20uk/grandmaster.txt?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- uk/grandmaster.txt | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 uk/grandmaster.txt diff --git a/uk/grandmaster.txt b/uk/grandmaster.txt new file mode 100644 index 0000000..4ad48f3 --- /dev/null +++ b/uk/grandmaster.txt @@ -0,0 +1,182 @@ +== Гросмейстерство Git == + +Тепер ви вже повинні вміти орієнтуватися в сторінках *git help* і розуміти майже все. Однак точний вибір команди, необхідної для вирішення конкретної проблеми, може бути виснажливим. Можливо, я збережу вам трохи часу: нижче наведені рецепти, які знадобилися мені в минулому. + +=== Релізи вихідних кодів === + +У моїх проектах Git управляє в точності тими файлами, які я збираюся архівувати і пускати в реліз. Щоб створити тарбол з вихідними кодами, я виконую: + + $ git archive --format=tar --prefix=proj-1.2.3/ HEAD + +=== Комміт змін === + +У деяких проектах може бути трудомістким повідомляти Git про кожне додавання, видаленні та перейменування файлу. Замість цього ви можете виконати команди + + $ git add . + $ git add -u + +Git прогляне файли в поточному каталозі і сам подбає про деталі. Замість другої команди add, виконайте `git commit -a`, якщо ви збираєтеся відразу зробити комміт. Дивіться * git help ignore *, щоб дізнатися як вказати файли, які повинні ігноруватися. + +Ви можете виконати все це одним махом: + + $ git ls-files -d -m -o -z | xargs -0 git update-index --add --remove + +Опції *-z* і *-0* запобігають невірну обробку файлових імен, що містять спеціальні символи. Оскільки ця команда додає ігноровані файли, ви можливо захочете використовувати опції `-x` або `-X`. + +=== Мій комміт занадто великий === + +Ви нехтували коммітамі занадто довго? Затято писали код і згадали про управління вихідними кодами тільки зараз? Внесли ряд незв'язаних змін, тому що це ваш стиль? + +Немає причин для занепокоєння. Виконайте + + $ git add -p + +Для кожної зробленої вами правки Git покаже змінену ділянку коду і запитає, чи повинна ця зміна потрапити в наступний комміт. Відповідайте "y" (так) або "n" (ні). У вас є й інші варіанти, наприклад відкласти вибір; введіть "?" Щоб дізнатися більше. + +Коли закінчите, виконайте + + $ git commit + +для внесення саме тих правок, що ви вибрали ('буферизованих' змін). Переконайтеся, що ви не вказали опцію *-a*, інакше Git закоммітить всі правки. + +Що робити, якщо ви змінили безліч файлів в багатьох місцях? Перевірка кожної окремої зміни стає обтяжливою рутиною. У цьому випадку використовуйте *git add -i*. Її інтерфейс не такий простий, але більш гнучкий. У декілька натискань можна додати або прибрати з буфера кілька файлів одночасно, або переглянути і вибрати зміни лише в окремих файлах. Як варіант, запустіть *git commit \--interactive*, яка автоматично зробить комміт коли ви закінчите. + +=== Індекс - буферна зона Git === + +До цих пір ми уникали знаменитого 'індексу' Git, але тепер ми повинні розглянути його, для пояснення вищесказаного. Індекс це тимчасовий буфер. Git рідко переміщує дані безпосередньо між вашим проектом і його історією. Замість цього Git спочатку записує дані в індекс, а вже потім копіює їх з індексу за місцем призначення. + +Наприклад, *commit -a* насправді двоетапний процес. Спочатку зліпок поточного стану кожного з відстежуваних файлів поміщається в індекс. Потім зліпок, що знаходиться в індексі, записується в історію. Комміт без опції *-a* виконує тільки другий крок, і має сенс тільки після виконання команд, що змінюють індекс, таких як *git add*. + +Зазвичай ми можемо не звертати уваги на індекс і робити вигляд, що взаємодіємо безпосередньо з історією. Але в даному випадку ми хочемо більш тонкого контролю, тому управляємо індексом. Ми поміщаємо зліпок деяких (але не всіх) наших змін в індекс, після чого остаточно записуємо цей акуратно сформований зліпок. + +=== Не теряй «головы» === + +Тег HEAD (англ. «голова», прим. пер.) — как курсор, который обычно указывает на последний коммит, продвигаясь с каждым новым коммитом. Некоторые команды Git позволяют перемещать этот курсор. Например, + + $ git reset HEAD~3 + +переместит HEAD на три коммита назад. Теперь все команды Git будут работать так, как будто вы не делали последних трех коммитов, хотя файлы останутся в текущем состоянии. В справке описано несколько способов использования этого приема. + +Но как вернуться назад в будущее? Ведь предыдущие коммиты о нем ничего не знают. + +Если у вас есть SHA1 изначальной «головы», то: + + $ git reset 1b6d + +Но допустим, вы его не записывали. Не беспокойтесь: для комнад такого рода Git сохраняет оригинальную «голову» как тег под названием ORIG_HEAD, и вы можете вернуться надежно и безопасно: + + $ git reset ORIG_HEAD + +=== Охота за «головами» === + +Предположим ORIG_HEAD недостаточно. К примеру, вы только что осознали, что допустили громадную ошибку, и вам нужно вернуться к древнему коммиту в давно забытой ветке. + +По умолчанию Git хранит коммиты не меньше двух недель, даже если вы приказали уничтожить содержащую их ветку. Проблема в нахождении соответствующего хеша. Вы можете просмотреть все значения хешей в .git/objects и методом проб и ошибок найти нужный. Но есть путь значительно легче. + +Git записывает каждый подсчитанный им хеш коммита в .git/logs. В подкатлоге refs содержится полная история активности на всех ветках, а файл HEAD содержит каждое значение хеша, которое когда-либо принимал HEAD. Последнее можно использовать чтобы найти хеши коммитов на случайно обрубленных ветках. + +Команда reflog предоставляет удобный интерфейс работы с этими журналами. Используйте + + $ git reflog + +Вместо копирования хешей из reflog, попробуйте + + $ git checkout "@{10 minutes ago}" # 10 минут назад, прим. пер. + +Или сделайте чекаут пятого с конца из посещенных коммитов с помощью + + $ git checkout "@{5}" + +Смотрите раздел «Specifying Revisions» в *git help rev-parse* для дополнительной информации. + +Вы можете захотеть удлинить отсрочку для коммитов, обреченных на удаление. Например, + + $ git config gc.pruneexpire "30 days" + +означает, что удаляемые коммиты будут окончательно исчезать только по прошествии 30 дней и после запуска *git gc*. + +Также вы можете захотеть отключить автоматический вызов *git gc*: + + $ git config gc.auto 0 + +В этом случае коммиты будут удаляться только когда вы будете запускать *git gc* вручную. + +=== Git как основа === + +Дизайн Git, в истинном духе UNIX, позволяет легко использовать его как низкоуровневый компонент других программ: графических и веб-интерфейсов; альтернативных интерфейсов командной строки; инструментов управления патчами; средств импорта или конвертации, и так далее. Многие команды Git на самом деле — скрипты, стоящие на плечах гигантов. Небольшой доработкой вы можете переделать Git на свой вкус. + +Простейший трюк — использование алиасов Git для сокращения часто используемых команд: + + $ git config --global alias.co checkout + $ git config --global --get-regexp alias # отображает текущие алиасы + alias.co checkout + $ git co foo # то-же, что и «git checkout foo» + +Другой пример: можно выводить текущую ветку в приглашении командной строки или заголовке окна терминала. Запуск + + $ git symbolic-ref HEAD + +выводит название текущей ветки. На практике вы скорее всего захотите убрать «refs/heads/» и сообщения об ошибках: + + $ git symbolic-ref HEAD 2> /dev/null | cut -b 12- + +Подкаталог +contrib+ это целая сокровищница инструментов, построенных на Git. Со временем некоторые из них могут становиться официальными командами. В Debian и Ubuntu этот каталог находится в +/usr/share/doc/git-core/contrib+. + +Один популярный инструмент из этого каталога — +workdir/git-new-workdir+. Этот скрипт создает с помощью символических ссылок новый рабочий каталог, имеющий общую историю с оригинальным хранилищем: + + $ git-new-workdir существующее/хранилище новый/каталог + +Новый каталог и файлы в нем можно воспринимать как клон, с той разницей, что два дерева автоматически остаются синхронизированными ввиду общей истории. Нет необходимости в merge, push и pull. + +=== Рискованные трюки === + +Нынешний Git делает случайное уничтожение данных очень сложным. +Но если вы знаете, что делаете, вы можете обойти защиту для распространенных команд. + +*Checkout*: Наличие незакоммиченных изменений прерывает выполнение checkout. Чтобы перейти к нужному коммиту, даже уничтожив свои изменения, используйте «принуждающий» (force, прим. пер.) флаг *-f*: + + $ git checkout -f HEAD^ + +С другой стороны, если вы укажете checkout конкретные пути, проверки на безопасность не будет: указанные файлы молча перезапишутся. Будьте осторожны при таком использовании checkout. + +*Reset*: сброс также прерывается при наличии незакоммиченных изменений. Чтобы заставить его сработать, запустите + + $ git reset --hard 1b6d + +*Branch*: Удаление ветки прервётся, если оно привело бы к потере изменений. Для принудительного удаления введите + + $ git branch -D мертвая_ветка # вместо -d + +Аналогично, попытка перезаписи ветки путем перемещения будет прервана, если может привести к потере данных. Для принудительного перемещений ветки введите + + $ git branch -M источник цель # вместо -m + +В отличии от checkout и reset, эти две команды дают отсрочку в удалении данных. Изменения остаются в каталоге .git и могут быть возвращены восстановлением нужного хеша из .git/logs (смотрите выше раздел «Охота за „головами“»). По умолчанию они будут храниться по крайней мере две недели. + +*Clean*: Некоторые команды могут не сработать из опасений повредить неотслеживаемые файлы. Если вы уверены, что все неотслеживаемые файлы и каталоги не нужны, то безжалостно удаляйте их командой + + $ git clean -f -d + +В следующий раз эта досадная команда сработает! + +=== Предотвращаем плохие коммиты === + +Глупые ошибки загрязняют мои хранилища. Самое ужасное это проблема недостающих файлов, вызванная забытым *git add*. + +Примеры менее серьезных проступков: завершающие пробелы и неразрешённые конфликты слияния. Несмотря на безвредность, я не хотел бы, чтобы это появлялось в публичных записях. + +Если бы я только поставил защиту от дурака, используя _хук_, который бы предупреждал меня об этих проблемах: + + $ cd .git/hooks + $ cp pre-commit.sample pre-commit # В старых версиях Git: chmod +x pre-commit + +Теперь Git отменит коммит, если обнаружит лишние пробелы или неразрешенные конфликты. + +Для этого руководства я в конце концов добавил следующее в начало хука *pre-commit*, чтобы защититься от своей рассеянности: + +if git ls-files -o | grep '\.txt$'; then + echo ПРЕРВАНО! Неотслеживаемые .txt файлы. + exit 1 +fi + +Хуки поддерживаются несколькими различными операциями Git, смотрите *git help hooks*. Мы использовали пример хука *post-update* раньше, при обсуждении использования Git через http. Он запускался при каждом перемещении «головы». Пример скрипта *post-update* обновляет файлы, которые нужны Git для связи через не считающиеся с ним средства сообщения, такие как HTTP. -- 2.11.4.GIT