updated ru/branch.txt, without chapters "merging", "unint. workflow" and "work how...
[gitmagic/gitmagic.git] / ru / history.txt
blob88732bb1df483b3fd31217d6e3a28e27feb71181
1 == Уроки истории ==\r
2 \r
3 Вследствие распределенной природы Git, историю изменений можно легко редактировать. Однако, если вы вмешиваетесь в прошлое, будьте осторожны: изменяйте только ту часть истории, которой владеете вы и только вы. Иначе, как народы вечно выясняют, кто же именно совершил и какие бесчинства, так и у вас будут проблемы с примирением при попытке совместить разные деревья истории.\r
4 \r
5 Конечно, если вы также контролируете и все остальные деревья, то нет никаких проблем поскольку вы можете переписать их.\r
6 \r
7 Некоторые разработчики убеждены, что история должна быть неизменна со всеми огрехами и прочим.  \r
8 Другие считают, что деревья нужно делать презентабельными перед выпуском их в публичный доступ.\r
9 Git учитывает оба мнения. Также как клонирование, ветвление и слияние, переписывание истории — это лишь еще одна возможность, которую дает вам Git. Разумное ее использование зависит только от вас.\r
11 === Оставаясь корректным ===\r
13 Только что сделали коммит и поняли, что должны были ввести другое описание? Запустите\r
15  $ git commit --amend\r
17 чтобы изменить последнее сообщение коммита. Осознали, что забыли добавить файл? Запустите *git add*, чтобы это сделать, затем выполните вышеуказанную команду.\r
19 Захотелось добавить еще немного изменений в последний коммит? Так сделайте их и запустите\r
21  $ git commit --amend -a\r
23 === ...И кое-что еще ===\r
25 Давайте представим себе, что предыдущая проблема на самом деле в десять раз хуже. После длительной работы вы сделали ряд фиксаций, но вы не очень-то довольны тем, как они организованы и кое-какие описания коммитов надо бы слегка переформулировать. В этом случае запустите\r
27  $ git rebase -i HEAD~10\r
29 и записи в журнале от последних 10-ти фиксаций появятся в вашем любимом редаторе (задается переменной окружения $EDITOR). Например:\r
31     pick 5c6eb73 Добавил ссылку repo.or.cz\r
32     pick a311a64 Сменил порядок в "Работай как хочешь"\r
33     pick 100834f Добавил цель для push в Makefile\r
35 Теперь вы можете:\r
37 - Убирать коммиты, удаляя строки.\r
38 - Менять порядок коммитов, переставляя строки.\r
39 - Заменяем "pick" на "edit" для внесения правок в коммиты.\r
40 - Заменяем "pick" на "squash" для слияния коммита с предыдущим.\r
42 Если вы отметили коммит для исправлений, запустите\r
44  $ git commit --amend\r
46 Если нет, запустите\r
48  $ git rebase --continue\r
50 Одним словом, делайте коммиты как можно раньше и как можно чаще — вы всегда сможете прибраться при помощи rebase.\r
52 === Локальные изменения сохраняются ===\r
54 Предположим, вы работаете над активным проектом. За какое-то время вы делаете несколько коммитов, затем синхронизируетесь с официальным деревом через слияние. Цикл повторяется несколько раз, пока вы не будете готовы влить изменения в центральное дерево.\r
56 Однако теперь история изменений в локальном клоне Git представляет собой кашу из ваших и официальных изменений. Вам бы хотелось видеть все свои изменения непрерывной линией, а затем — все официальные изменения.\r
58 Это работа для команды *git rebase*, описанной выше. Зачастую, имеет смысл использовать флаг *--onto* и убрать переплетения.\r
60 Также см. *git help rebase* для получения подробных примеров использования этой замечательной команды. Вы можете расщеплять коммиты, вы можете даже переупорядочить ветки.\r
62 === Переписывая историю ===\r
64 Время от времени вам может понадобиться в системе контроля версий эквивалент «замазывания» людей на официальных фотографиях, как бы стирая их из истории в духе сталинизма. Например, предположим, что мы уже собираемся выпустить релиз проекта, но он содержит файл, который не должен стать достоянием общественности по каким-то причинам. К примеру, я сохранил номер своей кредитки в текстовый файл и случайно добавил его в проект. Удалить файл недостаточно: он может быть доступен из старых коммитов. Нам надо удалить файл из всех ревизий:\r
66  $ git filter-branch --tree-filter 'rm top/secret/file' HEAD\r
68 См. *git help filter-branch*, где обсуждается этот пример и предлагается более быстрый способ решения. Вообще, *filter-branch* позволяет изменять существенные части истории при помощи одной-единственной команды.\r
70 После этой команды директория +.git/refs/original+ будет описывать состояние, которое было до её вызова. Убедитесь, что команда filter-branch сделала то, что вы ожидали, и, если хотите опять использовать эту команду, удалите этот каталог.\r
72 И, наконец, замените клоны вашего проекта обновленной версией, если собираетесь в дальнейшем с ними взаимодействовать.\r
74 === Создавая Историю ===\r
76 [[makinghistory]]\r
77 Хотите перевести проект под управление Git? Если сейчас он находится под управлением какой-либо из хорошо известных систем контроля версий, то весьма велики шансы на то, что кто-нибудь уже позаботился и написал необходимые скрипты для экспорта всей истории проекта в Git.\r
79 Если нет, то смотрите в сторону команды *git fast-import*, которая считывает текстовый ввод в специальном формате для создания истории Git "с нуля". Обычно скрипт, использующий эту команду, бывает слеплен наспех для единичного запуска, переносящего весь проект за один раз.\r
81 В качестве примера вставьте такие строки во временный файл, вроде '/tmp/history':\r
83 ----------------------------------\r
84 commit refs/heads/master\r
85 committer Alice <alice@example.com> Thu, 01 Jan 1970 00:00:00 +0000\r
86 data <<EOT\r
87 Стартовый коммит.\r
88 EOT\r
90 M 100644 inline hello.c\r
91 data <<EOT \r
92 #include <stdio.h>\r
94 int main() {\r
95   printf("Hello, world!\n");\r
96   return 0;\r
97 }\r
98 EOT\r
100 commit refs/heads/master\r
101 committer Bob <bob@example.com> Tue, 14 Mar 2000 01:59:26 -0800\r
102 data <<EOT\r
103 Заменен printf() на write()\r
104 EOT\r
106 M 100644 inline hello.c\r
107 data <<EOT \r
108 #include <unistd.h>\r
110 int main() {\r
111   write(1, "Hello, world!\n", 14);\r
112   return 0;\r
114 EOT\r
116 ----------------------------------\r
118 Затем создайте репозиторий Git из этого временного файла при помощи команд:\r
120 $ mkdir project; cd project; git init\r
121 $ git fast-import < /tmp/history\r
123 Вы можете извлечь последнюю версию проекта командой\r
125  $ git checkout master .\r
127 Команда *git fast-export* преобразует любой репозиторий Git в формат, понимаемый командой *git fast-import*. Её вывод мож использовать как образец для написания скриптов преобразования, или для переноса репозиторев в понятном человеку формате. Конечно, с помощью этих команд можно пересылать репозитории текстовых файлов через каналы передачи текста.\r
129 === Когда же все пошло не так? ===\r
131 Вы только что обнаружили, что кое-какой функционал вашей программы не работает, но вы совершенно отчетливо помните, что он работал всего несколько месяцев назад. Ну вот, блин! Откуда же взялась ошибка? Вы же это проверяли сразу как разработали.\r
133 В любом случае, уже слишком поздно. Однако, если вы фиксировали свои изменения достаточно часто, то Git сможет точно указать проблему:\r
135  $ git bisect start\r
136  $ git bisect bad SHA1_OF_BAD_VERSION\r
137  $ git bisect good SHA1_OF_GOOD_VERSION\r
139 Git извлечёт состояние ровно посередине. Проверьте работает ли то, что сломалось, и если все еще нет,\r
141  $ git bisect bad\r
143 Если же работает, то замените «bad» на «good». Git снова переместит вас в состояние посередине между «хорошей» и «плохой» ревизиями, сужая круг поиска. После нескольких итераций, этот двоичный поиск приведет вас к тому коммиту, на котором возникла проблема. После окончания выяснения, вернитесь в исходное состояние командой\r
145  $ git bisect reset\r
147 Вместо ручного тестирования каждого изменения автоматизируйте этот процесс при помощи команды\r
149  $ git bisect run COMMAND\r
151 По возвращаемому значение заданной команды, обычно «одноразового» скрипта, Git будет отличать «хорошее» состояние от «плохого». Скрипт должен вернуть 0 если нынешний коммит «хороший», 125 если его надо пропустить и любое другое число от 1 до 127 если он «плохое». Отрицательное возвращаемое значение прерывает команду bisect.\r
153 Вы можете сделать многим больше: страница помощи поясняет, как визуализировать bisect, проанализировать или воспроизвести её журнал, или исключить заведомо хорошие изменения для ускорения поиска.\r
155 === Из-за кого все пошло не так? ===\r
157 Как и во многих других системах конроля версий, в Git есть команда blame:\r
159  $ git blame FILE\r
161 Она снабжает каждую строку выбранного файла примечаниями, раскрывающими, кто и когда последним её редактировал. В отличие же от многих других систем контроля версий, эта операция происходит оффлайн, беря данные с локального диска.\r
163 === Личный опыт ===\r
165 В централизованных системах контроля версий, изменения истории - достаточно сложная операция, доступная лишь администраторам. Клонирование, ветвление и слияние невозможны без сетевого соединения. Также обстоят дела и с такими базовыми операциями как просмотр истории или фиксация изменений. В некоторых системах сетевое соединение требуется даже для просмотра собственных изменений или открытия файла для редактирования.\r
167 Централизованные системы исключают возможность работать без сети и требуют более дорогой сетевой инфраструктуры, особенно с увеличением количества разработчиков. Что важнее, все операции происходят медленнее, обычно до такой степени, что пользователи избегают пользоваться «продвинутыми» командами без крайней необходимости. В радикальных случаях это касается даже большинства базовых команд. Когда пользователи вынуждены запускать медленные команды, производительность страдает из-за прерываний рабочего процесса.\r
169 Я испытал этот феномен на себе. Git был моей первой системой контроля версий. Я быстро привык нему и стал относится к его возможностям как к должному. Я предполагал, что и другие системы похожи на него: выбор системы контроля версий не должен отличаться от выбора текстового редактора или браузера.\r
171 Когда, немного позже, я был вынужден использовать централизованную систему контроля версий, я был шокирован. Мое не всегда надёжное интернет-соединение не имело большого значения при использовании Git, но сделало разработку невыносимой когда от него потребовалась надежность как у жесткого диска. Вдобавок я обнаружил, что стал избегать некоторых команды из-за задержек в их выполнения, а без них оказалось невозможным следовать привычному рабочему процессу.\r
173 Когда мне было нужно запустить «медленную» команду, нарушение хода моих мыслей оказывало несоизмеримый ущерб разработке. Ожидая окончания связи с сервером, я должен был заниматься чем-то другим, чтобы скоротать время; например, проверкой почты или написанием документации. К тому времени, как я возвращался к первоначальной задаче, выполнение команды было давно закончено, но мне приходилось тратить уйму времени, чтоб вспомнить, что именно я делал. Все-таки люди не очень приспособлены для многозадачности.\r
175 Кроме того, есть интересный эффект «трагедии общин»: предвидя будущую перегруженность сети, некоторые люди в попытке предотвратить будущие задержки начинают использовать более широкие каналы, чем им реально требуются для текущих задач. Суммарная активность увеличивает загрузку сети, поощряя людей задействовать всё более высокоскоростные каналы для избежания ещё больших задержек.\r