ru/branch.txt editing: two chapters left
[gitmagic/gitmagic.git] / ru / secrets.txt
blobdddfc0ddd913e6ad3f409556aaf353ad4f0b5068
1 == Раскрываем тайны ==
3 Мы заглянем под капот и объясним, как Git творит свои чудеса. Я опущу некоторые детали. Для более подробного изучения описаний обратитесь к http://www.kernel.org/pub/software/scm/git/docs/user-manual.html[Руководству пользователя].
5 === Невидимость ===
7 Как Git может быть таким ненавязчивым? Помимо коммитов время от времени и слияния, вы можете работать так, как будто вы не знали, что контроль версий существует. То есть, пока вам это не нужно, вы его не замечаете, и вот, когда он понадобился вы рады, что Git наблюдал за вами все это время.
9 Другие системы контроля версий, не позволят вам забыть о них. Права доступа к файлам может быть только для чтения, пока вы явно не укажите серверу, какие файлы вы хотите изменить. Центральный сервер может отслеживать кто извлекал какой код и когда. Когда сеть падает вы можете от этого пострадать. Разработчики постоянно борются с виртуальной волокитой и бюрократизмом.
11 Секрет заключается в каталоге `.git` в вашей рабочей директории. Git хранит историю вашего проекта здесь. Из-за имени, начинающегося с точки каталог не отображается в выводе команды `ls`. Кроме комманд *git push* и *git pull* все остальные операции контроля версий работают в этом каталоге.
13 Вы имеете полный контроль над судьбой ваших файлов потому что Gitу не важно, что вы делаете с ними. Git можно легко восстановить сохраненное в `.git` состояние в любое время.
15 === Целостность ===
17 Большинство людей ассоциируют с криптографией поддержание информации в секрете, но другой не менее важной задачей является поддержание информации в сохранности. Правильное использование криптографических хеш-функций может предотвратить случайные или злонамеренные повреждения данных.
19 SHA1 хэш может рассматриваться как уникальный 160-битный идентификационный номер для каждой строки байт, с которой вы сталкиваетесь в вашей жизни. На самом деле гораздо больше: каждая строка байтов, которую любой человек когда-нибудь использует в течение многих жизней.
21 Так как SHA1 хэш сам является последовательностью байтов, мы можем получить хэш строки байтов, содержащей другие хэши. Это простое наблюдение на удивление полезно: смотрите 'hash chains' (цепи хешей). Позднее мы увидим, как Git использует их для эффективного обеспечения целостности данных.
23 Короче говоря, Git хранит ваши данные в подкаталоге ".git/objects", где вместо обычных файлов, вы увидите только ID. С помощью идентификаторов как имен файлов, а также нескольких лок-файлов и трюков с временем создания файлов, Git преобразует любую скромную файловую систему в эффективную и надежную базу данных.
25 === Интеллект ===
27 Каким образом Git знает, что вы переименовали файл, даже если вы никогда не упоминается тот факт явно? Конечно, вы можете запустить *git mv*, но это точно так же, как *git rm* и после *git add*.
29 Git эвристически находит переименованные файлы и копирует их в последующие версии. В самом деле, он может обнаружить, что куски кода были перемещены или скопированы между файлами! Хотя она не может охватить все случаи, это достойная работа, и эта функция всегда улучшается. Если это не работает, попробуйте включить опцию обнаружения копирования и рассмотреть вопрос апгрейда.
31 === Индексация ===
33 Для каждого отслеживаемого файла, Git записывает информацию, такую как размер, время создания и время последнего изменения в файл, известный как "индекс". Чтобы определить, что файл был изменен, Git сравнивает его текущее состояние с тем, что сохранено в индексе. Если они совпадают, то Git может пропустить перечитывание это файла.
35 Поскольку чтение этой информации значительно быстрее, чем чтение всего файла, то если вы редактировали только несколько файлов, Git может обновить свой индекс почти мгновенно.
37 === Голые репозитории ===
39 Вам, возможно, было интересно, какой формат используется в этих онлайн Git репозиториях.
40 Они такие-же хранилища Git, как ваш каталог `.git`, кроме того что обычно называются `proj.git`, и они не имеют рабочую директорию связанную с ними.
42 Большинство команд Git рассчитывают что индекс Git находится в каталоге `.git`, и не смогут работать на этих голых хранилищах. Исправить это можно, установив переменную окружения `GIT_DIR` в значение, равное пути к репозиторию, или запустить Git в этом каталоге с опцией `--bare`.
44 === Происхождение Git ===
46 Этот http://lkml.org/lkml/2005/4/6/121 [пост] в Linux Kernel Mailing List описывает цепь событий, которые привели к появлению Git. Весь этот трейд - увлекательные археологические раскопки для историков Git.
48 === База данных объектов ===
50 Вот как писать Git-подобной операционной системы с нуля в течение нескольких часов.
52 ==== Blobs ====
54 Первый волшебный трюк. Выберите имя файла, любое имя файла. В пустой директории:
56  $ echo sweet > YOUR_FILENAME
57  $ git init
58  $ git add .
59  $ find .git/objects -type f
61 Вы увидите +.git/objects/aa/823728ea7d592acc69b36875a482cdf3fd5c8d+.
63 Откуда я знаю это, не зная имени файла? Это потому, что SHA1 хэш строки:
65  "blob" SP "6" NUL "sweet" LF
67 является aa823728ea7d592acc69b36875a482cdf3fd5c8d,
68 где SP это пробел, NUL является нулевым байтом и LF переводом строки. Вы можете проверить это, напечатав:
70   $ echo "blob 6"$'\001'"sweet" | tr '\001' '\000' | sha1sum
72 Кстати, это написано с учетом особенностей оболочки Bash, другие оболочки возможно способны обработать NUL в командной строке, что исключает необходимость использовать костыль с *tr*.
74 Git является 'контент-адресуемым': файлы хранятся в независимости от их имени, а по хэшу содержимого, которое мы называем 'BLOB объект'. Мы можем думать о хеше как о уникальном идентификаторе для содержимого файла, так что в некотором смысле мы обращаемся к файлам по их содержимому. Начальный "blob 6" является лишь заголовком, состоящий из типа объекта и его длины в байтах; она упрощает внутренний учет.
76 Таким образом, я могу легко предсказать, что вы увидите. Имя файла не имеет никакого отношения: только данные внутри используется для построения BLOB объекта.
78 Вам может быть интересно, что происходит с идентичными файлами. Попробуйте добавить копии с любыми именами файлов вообще. Содержание +.git/objects+ останется тем-же независимо от того, сколько копий вы добавите. Git только хранит данные один раз.
80 Кстати, файлы в директории +.git/objects+ сжимаются с Zlib поэтому вы не сможете просмотреть их непосредственно. Пропустите их через фильтр http://www.zlib.net/zpipe.c [zpipe-D], или введите:
82  $ git cat-file -p aa823728ea7d592acc69b36875a482cdf3fd5c8d
84 который просто выведет данный объект.
86 ==== Деревья ====
88 Но где же имена файлов? Они должны храниться где-то на определенном этапе.
89 Git получает информацию об имени во время коммита:
91  $ git commit  # Type some message.
92  $ find .git/objects -type f
94 Теперь вы должны увидеть 3 объекта. На этот раз я не могу сказать вам, какие 2 новые файлы, так как это частично зависит от выбранного имени файла. Допустим вы назвали его "rose". Если это не так, то вы можете переписать историю, чтобы она выглядела как будто вы это сделали:
96  $ git filter-branch --tree-filter 'mv YOUR_FILENAME rose'
97  $ find .git/objects -type f
99 Теперь вы должны увидеть файл
100 +.git/objects/05/b217bb859794d08bb9e4f7f04cbda4b207fbe9+, потому что это
101 SHA1 хэш его содержимого:
103  "tree" SP "32" NUL "100644 rose" NUL 0xaa823728ea7d592acc69b36875a482cdf3fd5c8d
105 Проверьте - этот файл действительно содержит указанную выше строку - наберите:
107  $ echo 05b217bb859794d08bb9e4f7f04cbda4b207fbe9 | git cat-file --batch
109 С zpipe легко проверить хеш:
111  $ zpipe -d < .git/objects/05/b217bb859794d08bb9e4f7f04cbda4b207fbe9 | sha1sum
113 Проверка хеша сложнее чем через CAT-файла, поскольку его вывод содержит больше, чем сырой несжатый объектный файл.
115 Этот файл является объектом 'tree': список цепочек, состоящих из типа файла, имени файла, и хэша. В нашем примере это тип файла "100644", это означает что "rose", является обычным файлом и хэш BLOB объект, в котором находится содержимое "rose". Другие возможные типы файлов - исполняемые файлы, символические ссылки или каталоги. В последнем случае, хэш указывает на дереве объектов.
117 Если вы запускали filter-branch, у вас будут старые объекты которые вам больше не нужны. Хотя они будут автоматически выброшены сразу после истечения льготного периода, мы удалим их сейчас, чтобы наш игрушечный пример было легче исследовать:
119  $ rm -r .git/refs/original
120  $ git reflog expire --expire=now --all
121  $ git prune
123 Для реальных проектов, обычно вы должна избегать использовать такие команды, как эта, так как вы разрушаете резервные копии. Если вы хотите чистое хранилище, то обычно лучше сделать новый клон. Кроме того, будьте внимательны при непосредственном манипулировании +.git+: Что делать, если другая команда Git будет запущена в то же время, или внезапного произойдет отключение питания? В общем случае, ссылки должны быть удалены с помощью *git update-ref -d*, хотя обычно удалить +refs/original+ вручную безопасно.
125 ==== Коммиты ====
127 Мы объяснили 2 из 3 объектов. Третий объект - 'коммит'. Его содержимое зависит от сообщения коммита, а также от даты и времени его создания. Для демонстрации того, что мы здесь имеем, мы должны настроить Git немного:
129  $ git commit --amend -m Shakespeare  # Change the commit message.
130  $ git filter-branch --env-filter 'export
131      GIT_AUTHOR_DATE="Fri 13 Feb 2009 15:31:30 -0800"
132      GIT_AUTHOR_NAME="Alice"
133      GIT_AUTHOR_EMAIL="alice@example.com"
134      GIT_COMMITTER_DATE="Fri, 13 Feb 2009 15:31:30 -0800"
135      GIT_COMMITTER_NAME="Bob"
136      GIT_COMMITTER_EMAIL="bob@example.com"'  # Rig timestamps and authors.
137  $ find .git/objects -type f
139 Теперь вы должны увидеть
140 +.git/objects/49/993fe130c4b3bf24857a15d7969c396b7bc187+
141 который является SHA1 хэшем его содержание:
143  "commit 158" NUL
144  "tree 05b217bb859794d08bb9e4f7f04cbda4b207fbe9" LF
145  "author Alice <alice@example.com> 1234567890 -0800" LF
146  "committer Bob <bob@example.com> 1234567890 -0800" LF
147  LF
148  "Shakespeare" LF
150 Как и раньше, вы можете запустить zpipe или cat-file, чтобы увидить это самостоятельно.
152 Это первый коммит, и поэтому нет родительского коммита, но последующие коммиты всегда будет содержать хотя бы одну строку идентифицирующую родительский коммит.
154 ==== Неотличимо от магии ====
156 Там мало сказано. Мы только что открыли секрет мощи Git. Это кажется слишком простым: похоже, что вы могли бы смешать вместе несколько скриптов оболочки и добавить немного кода на C, сделанного в считанные часы. По сути, это точное описание ранних версий Git. Тем не менее, помимо гениальных трюков упаковки, чтобы сэкономить место, и трюков индексации, чтобы сэкономить время, мы теперь знаем, как ловко Git преображает файловую систему в базу данных, идеально подходящую для контроля версий.
158 Например, если какой-то файл объекта базы данных повредила ошибка диска, то его хэш больше не совпадает, предупреждая о проблеме. При хешировании хэшей других объектов, мы сохраняем целостность на всех уровнях. Коммит являются атомными, то есть, никогда нельзя закоммитить лишь часть изменений: мы можем только вычислить хэш коммита и сохранить его в базу данных после того как мы сохраним все соответствующие деревья, блобы и родительские коммиты. Объектная база данных застрахована от неожиданных прерываний работы с ней таких как перебои в подаче электроэнергии.
160 Мы наносим поражение даже самым хитрым противникам. Пусть кто-то попытается тайно изменить содержимое файла в древней версии проекта. Чтобы сохранить объектную базу данных согласованной, они также должны изменить хеш соответствующего объекта BLOB, поскольку это теперь другая последовательность байтов. Это означает, что нужно поменять хэш всех деревьев, содержащих ссылки на объект этого файла, что в свою очередь изменит хэши коммитов всех объектов с участием таких деревьев, в дополнение к хэшам всех потомков этих коммитов. Это означает, хэш официальной головной ревизии будет отличаться от хеша в этом плохом хранилище. По следам несовпадения хэшей мы можем локализовать изуродованный файл, а также коммит, где он впервые был поврежден.
162 Короче говоря, пока 20 байт представляющие последний коммит в безопасности, невозможно изменить репозиторий Git.
164 Как насчет знаменитых черт Git? Создание ветки? Слияние? Теги? Более подробно.
165 Текущая HEAD хранится в файле +.git/HEAD+, который содержит хэш объекта фиксации.
166 Хэш обновляется во время коммита, а также при выполнении многих других команд.
167 Ветки почти одинаковы: они представляют собой файлы в +.git/refs/heads+.
168 Тэги тоже: они живут в +.git/refs/tags+, но они обновляться различными наборами команд.