diff --git a/ru/basic.txt b/ru/basic.txt index 93f40dc..4dc484d 100644 --- a/ru/basic.txt +++ b/ru/basic.txt @@ -1,4 +1,4 @@ -== Базовые операции == +== Базовые операции == Прежде чем погружаться в дебри многочисленных команд Git, попробуйте воспользоваться приведёнными ниже простыми примерами, чтобы немного освоиться. Несмотря на свою простоту, каждый из них является полезным. @@ -10,7 +10,7 @@ $ git init $ git add . - $ git commit -m "Мой первый бекап" + $ git commit -m "Мой первый бэкап" Теперь, если ваши новые правки всё испортили, запустите: @@ -18,7 +18,7 @@ чтобы вернуться к исходному состоянию. Чтобы вновь сохраниться, выполните: - $ git commit -a -m "Другой бекап" + $ git commit -a -m "Другой бэкап" ==== Добавление, удаление, переименование ==== @@ -50,7 +50,7 @@ $ git checkout SHA1_HASH -Это перенесет вас назад во времени, до тех пор пока вы не сделаете новые коммиты. Как и в фантастических фильмах о путешествиях во времени, если вы редактируете и коммитите код, вы будете находиться в альтернативной реальности, потому что ваши действия отличаются от тех, что вы делали до этого. +Это перенесет вас назад во времени, до тех пор, пока вы не сделаете новые коммиты. Как и в фантастических фильмах о путешествиях во времени, если вы редактируете и коммитите код, вы будете находиться в альтернативной реальности, потому что ваши действия отличаются от тех, что вы делали до этого. Эта альтернативная реальность называется «ветвь» (branch, прим. пер.), и <>. А сейчас просто запомните: @@ -63,7 +63,7 @@ - *`git reset --hard`*: загружает ранее сохраненную игру и удаляет все версии, сохраненные после только что загруженной. -- *`git checkout`*: загружает старую игру, но если вы продолжаете играть, состояние игры будет отличаться от более новых сохранений, которые вы сделали в первый раз. Любая игра, которую вы теперь сохраняете, попадает в отдельную ветвь, представляющую альтенативную реальность, в которую вы вошли. +- *`git checkout`*: загружает старую игру, но если вы продолжаете играть, состояние игры будет отличаться от более новых сохранений, которые вы сделали в первый раз. Любая игра, которую вы теперь сохраняете, попадает в отдельную ветвь, представляющую альтернативную реальность, в которую вы вошли. <>. Вы можете выбрать для восстановления только определенные файлы и поддиректории путём перечисления их имён после команды: @@ -118,7 +118,7 @@ === Публичный доступ === -Предположим, вы написали скрипт, которым хотите поделиться с другими. Можно просто позволить всем загружать его с вашего компьютера, но, если они будут делать это в то время, как вы дорабатываете его или добавляете экспериментальную функциональность, у них могут возникнуть проблемы. Конечно, это одна из причин существования цикла разработки. Разработчики могут долго работать над проектом, но открывать доступ к коду следует только после того, как код приведен в приличный вид. +Предположим, вы написали скрипт, которым хотите поделиться с другими. Можно просто позволить всем загружать его с вашего компьютера, но, если они будут делать это тогда, когда вы дорабатываете его или добавляете экспериментальную функциональность, у них могут возникнуть проблемы. Конечно, это одна из причин существования цикла разработки. Разработчики могут долго работать над проектом, но открывать доступ к коду следует только после того, как код приведен в приличный вид. Чтобы сделать это с помощью Git, выполните в директории, где лежит ваш скрипт: @@ -130,11 +130,11 @@ $ git clone ваш.компьютер:/path/to/script -для того чтобы загрузить ваш скрипт. Это подразумевает что у вас есть доступ по ssh. Если нет, запустите *git daemon* и скажите остальным использовать для запуска: +для того чтобы загрузить ваш скрипт. Это подразумевает, что у вас есть доступ по ssh. Если нет, запустите *git daemon* и скажите остальным использовать для запуска: $ git clone git://ваш.компьютер/path/to/script -Теперь, всякий раз когда ваш скрипт готов к релизу, выполняйте: +Теперь, всякий раз, когда ваш скрипт готов к релизу, выполняйте: $ git commit -a -m "Следующий релиз" @@ -165,8 +165,7 @@ $ git whatchanged --since="2 weeks ago" Часто я смотрю историю при помощи http://sourceforge.net/projects/qgit[qgit] вместо стандартного способа, -из-за приятного интерфейса, или с помощью http://jonas.nitro.dk/tig[tig] с текстовым интерфейсом, -который хорошо работает при медленном соединении. В качестве альтернативы, можно запустить веб-сервер, +из-за приятного интерфейса, или с помощью http://jonas.nitro.dk/tig[tig] с текстовым интерфейсом, который хорошо работает при медленном соединении. В качестве альтернативы, можно запустить веб-сервер, введя *git instaweb*, и запустить любой веб-браузер. === Упражнение === @@ -189,5 +188,5 @@ $ git revert B Какой способ лучший? -Тот, который вам больше нравится. С Git легко сделать все, что вы хотите, причём часто существует много разных способов сделать одно и то-же. +Тот, который вам больше нравится. С Git легко сделать все, что вы хотите, причём часто существует много разных способов сделать одно и то же. diff --git a/ru/branch.txt b/ru/branch.txt index 2cbc7fd..27bdb1b 100644 --- a/ru/branch.txt +++ b/ru/branch.txt @@ -1,4 +1,4 @@ -== Чудеса ветвления == +== Чудеса ветвления == Возможности мгновенного разветвления и слияния - самые уникальные особенности Git. *Задача*: какие-то причины требуют переключения процессов. В новой версии внезапно возникает серьезная ошибка. Срок завершения работы над определенным свойством близится к концу. Разработчик, помощь которого очень нужна Вам в работе над ключевым разделом, собирается в отпуск. Итак, Вам нужно срочно бросить все, над чем Вы трудитесь в настоящий момент, и переключиться на совершенно другие дела. @@ -9,11 +9,11 @@ *Решение*: у Git есть более удобный инструмент для этих целей, который, в отличие от клонирования, сэкономит и время, и дисковое пространство - это *git branch*. -С этой волшебной командой файлы в вашей директории мгновенно изменяются с одной версии на другую. Это изменение позволяет сделать намного больше, чем просто вернуться назад или продвинуться вперед в истории. Ваши файлы могут изменится с последней версии на экспериментальную, с экспериментальной - на опытную, с опытной - на версию вашего друга и так далее. +С этой волшебной командой файлы в вашей директории мгновенно изменяются с одной версии на другую. Это изменение позволяет сделать намного больше, чем просто вернуться назад или продвинуться вперед в истории. Ваши файлы могут измениться с последней версии на экспериментальную, с экспериментальной - на опытную, с опытной - на версию вашего друга и так далее. === Кнопка босса === -Наверняка, вы играли в одну из тех игр, где при нажатии определеной клавиши ("кнопка босса"), игра быстро сворачивается и на экране отображается рабочая таблица или что-нибудь другое? То есть, если в офис зашел начальник, а вы играете в игру, вы должны уметь быстро ее скрыть. +Наверняка, вы играли в одну из тех игр, где при нажатии определённой клавиши ("кнопка босса"), игра быстро сворачивается и на экране отображается рабочая таблица или что-нибудь другое? То есть, если в офис зашел начальник, а вы играете в игру, вы должны уметь быстро ее скрыть. В какой-нибудь директории: @@ -22,7 +22,7 @@ $ git add . $ git commit -m "Начальный коммит" -Мы создали Git-репозиторий который содержит один текстовый файл с определенным сообщением. Теперь выполните: +Мы создали Git-репозиторий, который содержит один текстовый файл с определенным сообщением. Теперь выполните: $ git checkout -b boss # вероятно, это последнее изменение $ echo "Мой босс меня умнее" > myfile.txt @@ -36,14 +36,13 @@ $ git checkout boss # перейти на специальную версию для босса -Вы можете переключаться между двумя версиями этого файла так часто, как вам хочется и делать коммиты в каждый из них независимо. +Вы можете переключаться между двумя версиями этого файла так часто, как вам хочется, и делать коммиты в каждый из них независимо. === Грязная работа === [[branch]] -Допустим, вы работаете над созданием какой-либо функции, и по каким-то причинам необходимо вернуться назад к -старой версии и временно загрузить старый код, чтобы посмотреть как что-либо работало, тогда введите: +Допустим, вы работаете над созданием какой-либо функции, и по каким-то причинам необходимо вернуться назад к старой версии и временно загрузить старый код, чтобы посмотреть, как что-либо работало, тогда введите: $ git commit -a $ git checkout SHA1_HASH @@ -58,7 +57,7 @@ $ git checkout -b dirty -а затем сделайте коммит перед тем, как переключетесь на ветвь master. Всякий раз когда вы захотите вернуться к черновым изменениям, просто выполните: +а затем сделайте коммит перед тем, как переключитесь на ветвь master. Всякий раз, когда вы захотите вернуться к черновым изменениям, просто выполните: $ git checkout dirty @@ -108,7 +107,7 @@ $ git checkout part2 $ git merge master -И теперь - тоже самое. После того, как первая часть утверждена и выложена: +И теперь – то же самое. После того, как первая часть утверждена и выложена: $ git checkout master $ git merge part2 @@ -130,7 +129,7 @@ $ git checkout sanitized $ git cherry-pick SHA1_HASH -применит данный коммит для ветви"sanitized". С правильно выбранными элементами вы сможете собрать ветвь, которая будет содержать только проверенный код и соответствующие коммиты, сгруппированные вместе. +применит данный коммит для ветви "sanitized". С правильно выбранными элементами вы сможете собрать ветвь, которая будет содержать только проверенный код и соответствующие коммиты, сгруппированные вместе. === Управление Ветками === @@ -150,15 +149,15 @@ Через какое-то время вы можете обнаружить, что создаете множество временных веток для одной и той краткосрочной цели: нужно сохранить текущее состояние, чтобы была возможность вернуться назад и исправить грубую ошибку или сделать что-то еще. -Это похоже на то, как вы переключаете телевизионные каналы, чтобы посмотреть что показывают по другим. Но здесь, вместо того, чтобы нажать на пару кнопок на пульте, нужно будет создать, сделать отладку, а затем удалить временные ветки и коммиты. К счастью, в Git есть удобные ярлыки, имитирующие работу дистанционного пульта правления. +Это похоже на то, как вы переключаете телевизионные каналы, чтобы посмотреть, что показывают по другим. Но здесь, вместо того, чтобы нажать на пару кнопок на пульте, нужно будет создать, сделать отладку, а затем удалить временные ветки и коммиты. К счастью, в Git есть удобные ярлыки, имитирующие работу дистанционного пульта правления. $ git stash -Это сохраняет текущее состояние в во временном месте ('копилке') и востанавливает предыдущее состояние. Ваша директория становиться точно такой, как и была до того, как вы начали редактирование, и вы можете исправить ошибки, загрузить удаленные изменения и прочее. Когда вы хотите вернуться назад в состояние копилки, наберите: +Это сохраняет текущее состояние во временном месте ('копилке') и восстанавливает предыдущее состояние. Ваша директория становиться точно такой, как и была до того, как вы начали редактирование, и вы можете исправить ошибки, загрузить удаленные изменения и прочее. Когда вы хотите вернуться назад в состояние копилки, наберите: $ git stash apply # Возможно, понадобится устранить какие-либо конфликты. -Можно создавать несколько копилок, приумножать их и использовать по-разному. Смотрите *git help stash*. Как вы могли догадаться, этот чудесный прием возможен благодаря способности Git поддерживать создание закрытых "тайных" веток. +Можно создавать несколько копилок, приумножать их и использовать по-разному. Смотрите *git help stash*. Как вы могли догадаться, этот чудесный прием возможен благодаря способности Git создавать закрытые "тайные" ветки. === Работайте как вам нравится === diff --git a/ru/clone.txt b/ru/clone.txt index f603ee0..cc3fa09 100644 --- a/ru/clone.txt +++ b/ru/clone.txt @@ -2,7 +2,7 @@ В старых системах контроля версий checkout - это стандартная операция для получения файлов. Вы получаете файлы в нужном сохраненном состоянии. -В Git и других распределенных системах контроля версий, клонирование - это обычно дело. Для получение файлов вы создаете клон всего репозитория. Другими словами, вы создаете зеркало центрального сервера. При этом все что можно делать в основном репозитории, можно делать и в локальном. +В Git и других распределенных системах контроля версий, клонирование - это обычно дело. Для получения файлов вы создаете клон всего репозитория. Другими словами, вы создаете зеркало центрального сервера. При этом все, что можно делать в основном репозитории, можно делать и в локальном. === Синхронизация компьютеров === @@ -56,7 +56,7 @@ === Создание форка проекта === -Не нравится путь развития проекта? Думаете можете сделать лучше? Тогда на Вашем сервере: +Не нравится путь развития проекта? Думаете, можете сделать лучше? Тогда на Вашем сервере: $ git clone git://main.server/path/to/files diff --git a/ru/drawbacks.txt b/ru/drawbacks.txt index d6728f8..1ba7f6e 100644 --- a/ru/drawbacks.txt +++ b/ru/drawbacks.txt @@ -1,12 +1,12 @@ == Недостатки Git == -Есть некоторые проблемы Git, которые я спрятал под сукно. Некоторые из них можно легко решить с помощью сценариев и хуков, некоторые требуют реорганизации или пересмотра проекта, и из нескольких оставшихся неприятности, одну придется терпеть. Или еще лучше, взяться за нее и решить! +Есть некоторые проблемы Git, которые я спрятал под ковер. Некоторые из них можно легко решить с помощью сценариев и хуков, некоторые требуют реорганизации или пересмотра проекта, и из нескольких оставшихся неприятности, одну придется терпеть. Или еще лучше, взяться за нее и решить! === Недостатки SHA1 === -Со временем, криптографы обнаружать более слабые SHA1. Уже нахождения хэш столкновений является допустимым для хорошо финансируемой организации. За годы, возможно, даже типичный ПК будет иметь достаточную вычислительную мощность, чтобы потихоньку скоррумпировать Git репозиторий. +Со временем, криптографы обнаруживают все больше и больше слабостей в SHA1. Уже сейчас нахождение коллизий хеша не проблема для хорошо финансируемых проектов. Через несколько лет, возможно, даже типичный ПК будет иметь достаточно вычислительной мощности, чтобы самостоятельно скоррумпировать Git репозиторий. -Надеюсь Git мигрирует к лучшей хэш-функции до того, как дальнейшие исследования разрушат SHA1. +Надеюсь, Git перейдет на лучшую хэш-функцию до того, как дальнейшие исследования разрушат SHA1. === Microsoft Windows === @@ -14,7 +14,7 @@ Git на Microsoft Windows может быть накладным: - http://cygwin.com/[Cygwin], Linux-среда для Windows, содержит http://cygwin.com/packages/git/[порт Git на Windows]. --http://code.google.com/p/msysgit/[Git на MSys] вариант, требующий минимальной рантайм поддержки, хотя для нескольких команд, нужна доработка. +-http://code.google.com/p/msysgit/[Git на MSys] вариант, требующий минимальной поддержки, хотя для нескольких команд, нужна доработка. === Несвязанные файлы === @@ -22,7 +22,7 @@ Git на Microsoft Windows может быть накладным: Решение - разбить проект на части, каждая из которых состоит из связанных файлов. Используйте *git submodule* если вы все еще хотите держать все в одном репозитории. -=== Кто и что редактировал ? === +=== Кто и что редактировал? === Некоторые системы контроля версий заставляют вас отметить файл до редактирования. Хотя это особенно раздражает, когда речь идет о работе с центральным сервером, этот способ имеет два преимущества: @@ -36,7 +36,7 @@ Git на Microsoft Windows может быть накладным: Поскольку Git записывает изменения всего проекта, то чтобы восстановить историю одного файла требуется больше работы, чем в системах управления версиями, которые позволяют отслеживать отдельные файлы. -Потери, как правило, небольшие, а также стоит иметь в виду, что другие операции являются невероятно эффективными. Например, `git checkout` быстрее, чем `cp -a`, и вся дельта проекта сжимаются лучше, чем коллекций на основе дельт файлов. +Потери, как правило, небольшие, а также стоит иметь в виду, что другие операции являются невероятно эффективными. Например, `git checkout` быстрее, чем `cp -a`, и вся дельта проекта сжимаются лучше, чем коллекции на основе дельт файлов. === Начальное Клонирование === @@ -52,19 +52,19 @@ Git был написан, чтобы быть быстрым по отноше Причины, почему эти изменения бывают настолько велики, должны быть изучены. Возможно, формат файла должен быть изменен. Малые изменения должны быть причиной малых изменений в самих файлах. -Или, возможно, то, что вам было нужно, это базы данных или система резервного копирования или архивы, а не система контроля версий. Например, контроль версий может быть плохо приспособлен для управления фотографиями периодически получаемых с веб-камеры. +Или, возможно, то, что вам было нужно, это базы данных или система резервного копирования или архивы, а не система контроля версий. Например, контроль версий может быть плохо приспособлен для управления периодически получаемыми с веб-камеры фотографиями. -Если файлы действительно должны постоянно изменяться, и они действительно должно быть версионироваться, возможно использовать Git централизованным образом. Можно создать мелкие клоны, с небольшой или без истории проекта. Конечно, многие инструменты Git будут недоступны, и исправления должны быть представлены в виде патчей. Вероятно, это штраф, потому как неясно, почему кто-то хочет вести историю дико неустойчиво файлов. +Если файлы действительно должны постоянно изменяться, и они действительно должны версионироваться, возможно использовать Git централизованным образом. Можно создать мелкие клоны, с небольшой или без истории проекта. Конечно, многие инструменты Git будут недоступны, и исправления должны быть представлены в виде патчей. Вероятно, это хорошо, поскольку неясно, почему кто-то хочет вести историю дико неустойчивых файлов. Другим примером является проект, зависимый от прошивки, которая принимает форму огромного бинарного файла. История этой микропрограммы неинтересна для пользователей, и обновления сжимаются плохо, так версии микропрограммы могут излишне увеличить размера хранилища. -В этом случае исходный код должен храниться в хранилище Git, а бинарные файлы - отдельно. Чтобы сделать жизнь проще, можно было бы распространять скрипт, который используется Git чтобы клонировать код и Rsync или мелкий клон Git для прошивки. +В этом случае исходный код должен храниться в хранилище Git, а бинарные файлы - отдельно. Чтобы сделать жизнь проще, можно было бы распространять скрипт, который использует Git чтобы клонировать код и Rsync или мелкий клон Git для прошивки. === Глобальный счетчик === -Некоторые централизованные системы контроля версий, используют положительные числа, которые возрастают, когда происходит новый коммит. Git идентифицирует изменения их хэшем, который лучше во многих обстоятельствах. +Некоторые централизованные системы контроля версий, используют положительные числа, которые возрастают, когда происходит новый коммит. Git идентифицирует изменения их хешем, который лучше во многих обстоятельствах. -Но некоторым люди нравится эти целые вокруг. К счастью, легко написать сценарии, чтобы при каждом обновлении центральный репозиторий Git увеличивал целое число, возможно, в теге, и связывает его с хэшем последним коммитом. +Но некоторым люди нравится эти числа вокруг. К счастью, легко написать скрипт, который при каждом обновлении центрального Git репозитория увеличивал целое число, возможно, в теге, и связывал его с хешем последним коммитом. Каждый клон может поддерживать такой счетчик, но это, вероятно, будет бесполезным, поскольку только центральный репозиторий имеет значение для всех. @@ -72,16 +72,16 @@ Git был написан, чтобы быть быстрым по отноше Пустые подкаталоги не могут быть отслежены. Создайте пустой файл, чтобы обойти эту проблему. -В этом виноват не дизайн Git, а его текущая реализация. Если повезет и пользователи Git уделят больше внимания этой функции, возможно она будет реализована. +В этом виноват не замысел Git, а его текущая реализация. Если повезет, и пользователи Git уделят больше внимания этой функции, возможно, она будет реализована. === Первоначальный коммит === -Обычный ученый в области информатики считает от 0, а не от 1. К сожалению, Git с его коммитами не присоединяется к этой конвенции. Многие команды плохо работают до первого коммита. Кроме того, некоторые частные случаи должны быть обработаны специально, такие, как rebase веток с различными начальными коммитами. +Обычный ученый в области информатики считает от 0, а не от 1. К сожалению, Git с его коммитами не придерживается этой конвенции. Многие команды плохо работают до первого коммита. Кроме того, некоторые частные случаи должны быть обработаны специально, такие, как rebase веток с различными начальными коммитами. -Git'у желательно определение нулевого совершения: как только будет построено хранилище, HEAD будет установлен в строку, состоящую из 20 нулевых байтов. Этот специальный коммит представляет собой пустое дерево, без родителей, предшествовавшее всему в Git репозитории. +Git'у желательно определение нулевого коммита: как только будет построен репозиторий, HEAD будет установлен в строку, состоящую из 20 нулевых байтов. Этот специальный коммит представляет собой пустое дерево, предшествующее всему в Git репозитории. -Затем запустить *git log*, например, будет показывать пользователю, что коммиты еще не были сделаны вместо выхода с фатальной ошибкой. Аналогично для других инструментов. +Если затем запустить *git log*, например, то вместо выхода с фатальной ошибкой он будет показывать пользователю, что коммиты еще не были сделаны. Аналогично для других инструментов. -Каждая первоначальная фиксация - неявный потомок этого нулевого коммита. Например, несвязанный с какой-либо веткой rebase в целом будет привита на эту цель. В настоящее время применяются все, кроме первоначального коммита, в результате чего получается конфликт слияния. Один из способов заключается в использовании `git checkout` после `git commit -C` первоначального коммита, тогда rebase пройдет нормально. +Каждый первоначальный коммит - неявный потомок этого нулевого коммита. Например, несвязанный с какой-либо веткой rebase в целом будет применен к нему. В настоящее время применяются все, кроме первоначального коммита, в результате чего получается конфликт слияния. Один из способов заключается в использовании `git checkout` после `git commit -C` первоначального коммита, тогда rebase пройдет нормально. К сожалению, в худшем случае, если несколько ветвей с различными начальными коммитами сливаются, то rebase результата требует значительного ручного вмешательства. diff --git a/ru/grandmaster.txt b/ru/grandmaster.txt index 16d1d9a..7ce42fb 100644 --- a/ru/grandmaster.txt +++ b/ru/grandmaster.txt @@ -5,14 +5,13 @@ === Релизы исходников === В моих проектах Git управляет только теми файлами, которые я собираюсь архивировать и пускать в релиз. -Чтобы создать тарбол с исходниками, я выполняю: +Чтобы создать архив с исходниками, я выполняю: $ git archive --format=tar --prefix=proj-1.2.3/ HEAD === Сохранение изменений === -Вручную сообщать Git о том, что вы добавили, удалили или переименовали файлы, может стать непростой задачей - в некоторых проектах. Вместо этого вы можете выполнить команды: +Вручную сообщать Git о том, что вы добавили, удалили или переименовали файлы, может стать непростой задачей в некоторых проектах. Вместо этого вы можете выполнить команды: $ git add . $ git add -u @@ -33,7 +32,7 @@ Git просмотрит файлы в текущем каталоге и обр $ git add -p -Для каждого внесенного изменения Git покажет измененный участок кода и спросит, должно ли это изменение пройти в следующем коммите. Отвечаем "y" или "n". Если вы хотите сделать что-то другое, например отложить выбор, введите "?" чтобы получить дополнительную информацию. +Для каждого внесенного изменения Git покажет измененный участок кода и спросит, должно ли это изменение пройти в следующем коммите. Отвечаем "y" или "n". Если вы хотите сделать что-то другое, например, отложить выбор, введите "?" чтобы получить дополнительную информацию. Как только все будет готово, выполните: @@ -47,9 +46,9 @@ Git просмотрит файлы в текущем каталоге и обр До сих пор мы избегали такой известной части Git, как 'index', но теперь мы должны разобраться с ней, чтобы пояснить вышесказанное. Индекс представляет собой временную область. Git редко перемещает данные непосредственно между вашим проектом и его историей. Вместо этого, Git сначала записывает данные в индекс, а уж затем копирует данные из индекса по месту назначения. -Например, *commit -a* это на самом деле двухэтапный процесс. Сначала снапшот текущего состояния отслеживаемых файлов помещается в индекс. Затем снапшот, находящийся в индексе, записывается в историю. Коммит без опции *-a* выполняет только второй этап, и имеет смысл только после выполнения команд, которые изменяют индекс, например *git add*. +Например, *commit -a* это на самом деле двухэтапный процесс. Сначала снимок текущего состояния отслеживаемых файлов помещается в индекс. Затем снимок, находящийся в индексе, записывается в историю. Коммит без опции *-a* выполняет только второй этап, и имеет смысл только после выполнения команд, которые изменяют индекс, например *git add*. -Обычно мы можем не обращать внимания на индекс и считать, что взаимодействуем с историей напрямую. Но в такого рода сложных случаях нам нужен усиленный контроль над тем, что записывается в историю, и мы вынуждены работать с индексом. Мы помещаем снапшот только части наших изменений в индекс, а потом записываем этот аккуратно сформированный снапшот. +Обычно мы можем не обращать внимания на индекс и считать, что взаимодействуем с историей напрямую. Но в таких сложных случаях нам нужен усиленный контроль над тем, что записывается в историю, и мы вынуждены работать с индексом. Мы помещаем снимок только части наших изменений в индекс, а потом записываем этот аккуратно сформированный снимок. === Не теряй HEAD === @@ -73,17 +72,17 @@ Git просмотрит файлы в текущем каталоге и обр Предположим ORIG_HEAD недостаточно. Предположим, что вы только что осознали, что допустили громадную ошибку, и вам нужно вернуться в очень старый коммит давно забытой ветки. -По умолчанию Git хранит коммиты по крайней мере в течении двух недель, даже если вы сказали ему уничтожить ветку с ними. Проблема в нахождении подходящего хеша. +По умолчанию Git хранит коммиты, по крайней мере, в течение двух недель, даже если вы сказали ему уничтожить ветку с ними. Проблема в нахождении подходящего хеша. Вы можете просмотреть хеши в `.git/objects` и методом проб и ошибок найти нужный. Но есть путь значительно легче. -Git записывает все хеши коммитов в `.git/logs`. В папке `refs` содержится история активности на всех ветках, а файл `HEAD` содержит каждое значение хеша, которое когда-либо принимал HEAD. Второе можно использовать чтобы найти хеши коммитов на случайно обрубленных ветках. +Git записывает все хеши коммитов в `.git/logs`. В папке `refs` содержится история активности на всех ветках, а файл `HEAD` содержит каждое значение хеша, которое когда-либо принимал HEAD. Второе можно использовать, чтобы найти хеши коммитов на случайно обрубленных ветках. Команда reflog предоставляет удобный интерфейс работы с этими логами. Используйте: $ git reflog -Вместо копипейста хешей из reflog, попробуйте: +Вместо копирования хешей из reflog, попробуйте: $ git checkout "@{10 minutes ago}" @@ -92,7 +91,7 @@ Git записывает все хеши коммитов в `.git/logs`. В п $ git checkout "@{5}" Смотрите секцию "Specifying Revisions" *git help rev-parse*, если вам нужна дополнительная информация. -Вам может потребоваться установить более долгий период сохранения удаляемых коммитов. +Вам может потребоваться установить более долгий период сохранения удаленных коммитов. Например, выполнение: @@ -108,12 +107,9 @@ Git записывает все хеши коммитов в `.git/logs`. В п === Git как основа === -Дизайн Git'a, разработанный в UNIX стиле, позволяет использовать Git как низкоуровневый компонент других программ: GUI, веб-интерфейсов, альтернативных командных строк, инструментов управления патчами, импортирования, преобразования, и т.д. На самом деле, многие команды Git - сами по себе скрипты, стоящие на плечах гигантов. -Немного поигравшись с Git, вы можете заставить его удовлетворять многие ваши потребности. +Дизайн Git'a, разработанный в UNIX стиле, позволяет использовать Git как низкоуровневый компонент других программ: GUI, веб-интерфейсов, альтернативных командных строк, инструментов управления патчами, импортирования, преобразования, и т.д. На самом деле, многие команды Git - сами по себе скрипты, стоящие на плечах гигантов. Немного поигравшись с Git, вы можете заставить его удовлетворять многие ваши потребности. -Простейший трюк - использование алиасов Git для выполнения часто - - используемых команд: +Простейший трюк - использование алиасов Git для выполнения часто используемых команд: $ git config --global alias.co checkout $ git config --global --get-regexp alias # отображает текущие алиасы @@ -126,25 +122,21 @@ Git записывает все хеши коммитов в `.git/logs`. В п $ git symbolic-ref HEAD -выводит название текущей ветки. Для практического использования вы -скорее всего захотите убрать "refs/heads/" и сообщения об ошибках: +выводит название текущей ветки. Для практического использования вы, скорее всего, захотите убрать "refs/heads/" и сообщения об ошибках: $ git symbolic-ref HEAD 2> /dev/null | cut -b 12- -Папка `contrib` это целая сокровищница инструментов, построенных на Git. -Со временем некоторые из них могут становиться официальными командами. Под Debian и Ubuntu эта папка находится в `/usr/share/doc/git-core/contrib`. +Папка `contrib` это целая сокровищница инструментов, построенных на Git. Со временем некоторые из них могут становиться официальными командами. Под Debian и Ubuntu эта папка находится в `/usr/share/doc/git-core/contrib`. `workdir/git-new-workdir` - один из популярных и часто используемых инструментов. С помощью хитрых симлинков этот скрипт создает новую рабочую папку, которая будет иметь общую историю с оригинальным репозиторием: $ git-new-workdir an/existing/repo new/directory -Можно думать о новой папке и о файлах в ней, как о клоне, за исключением того, что так как история общая, -два дерева автоматически синхронизируются. Нет необходимости в *merge*, *push* и *pull*. +Можно думать о новой папке и о файлах в ней, как о клоне, за исключением того, что, так как история общая, два дерева автоматически синхронизируются. Нет необходимости в *merge*, *push* и *pull*. === Опасные трюки === -Случайно уничтожить данные очень сложно с сегодняшними версиями Git. -Но если вы знаете, что делаете, вы можете обойти защиту для общих команд. +Случайно уничтожить данные очень сложно с сегодняшними версиями Git. Но если вы знаете, что делаете, вы можете обойти защиту для общих команд. *Checkout*: Незакоммиченные изменения не дают сделать чекаут. Чтобы все-таки сделать чекаут нужного коммита, уничтожив свои изменения, используется флаг *-f*: @@ -164,9 +156,9 @@ Git записывает все хеши коммитов в `.git/logs`. В п $ git branch -M [SOURCE] TARGET #вместо -m -В отличии от чекаута и ресета, эти две команды задерживают удаление данных. Изменения остаются в папке .git и могут быть восстановлены с помощью нужного хеша из `.git/logs`(смотрите параграф "Охота за HEAD'ами" выше). +В отличие от чекаута и ресета, эти две команды задерживают удаление данных. Изменения остаются в папке .git и могут быть восстановлены с помощью нужного хеша из `.git/logs`(смотрите параграф "Охота за HEAD'ами" выше). -По умолчанию они будут храниться по крайней мере две недели. +По умолчанию они будут храниться, по крайней мере, две недели. *Clean*: Некоторые команды не будут выполняться, если они могут повредить неотслеживаемые файлы. Если вы уверены, что все неотслеживаемые файлы и папки вам не нужны, то безжалостно удаляйте их командой: @@ -178,7 +170,7 @@ Git записывает все хеши коммитов в `.git/logs`. В п История многих моих проектов полна глупых ошибок. Самое ужасное это кучи недостающих файлов, которые появляются, когда забываешь выполнить *git add*. К счастью, я пока не терял важных файлов из-за того, что пропускал их, потому что я редко удаляю оригинальные рабочие папки. Обычно я замечаю ошибку несколько коммитов спустя, так что единственный вред это отсутствующая история и осознание своей вины. -Также я регулярно совершаю(и коммичу) меньшее зло - завершающие пробелы. Несмотря на безвредность, я не хотел бы, чтобы это появлялось в публичных записях. +Также я регулярно совершаю (и коммичу) меньшее зло - завершающие пробелы. Несмотря на безвредность, я не хотел бы, чтобы это появлялось в публичных записях. И наконец, я беспокоюсь о неразрешенных конфликтах, хотя пока они не приносили вреда. Обычно я замечаю их во время билда, но в некоторых случаях могу проглядеть. Если бы я только поставил защиту от дурака, используя хук, который бы предупреждал меня об этих проблемах... @@ -187,7 +179,7 @@ Git записывает все хеши коммитов в `.git/logs`. В п $ cp pre-commit.sample pre-commit # В старых версиях Git: chmod +x pre-commit Теперь Git отменяет коммит, если обнаружены ненужные пробелы или неразрешенные конфликты. -Для этого руководства я в конце концов добавил следующее в начало *pre-commit* хука, чтобы защититься от своей рассеянности: +Для этого руководства я, в конце концов, добавил следующее в начало *pre-commit* хука, чтобы защититься от своей рассеянности: if git ls-files -o | grep '\.txt$'; then echo FAIL! Неотслеживаемые .txt файлы. diff --git a/ru/history.txt b/ru/history.txt index 221371e..8c929a2 100644 --- a/ru/history.txt +++ b/ru/history.txt @@ -1,180 +1,177 @@ -== Уроки истории == - -Вследствие распределенной природы Git, историю изменений можно легко редактировать. Однако, если вы вмешиваетесь в прошлое, будьте осторожны: изменяйте только ту часть истории, которой владеете вы и только вы. И также как государства бесконечно выясняют, кто же именно совершил и какие бесчинства, так и у вас будут проблемы с примирением после взаимодействия деревьев истории. - -Конечно, если вы также контролируете и все остальные деревья, то нет никаких проблем поскольку вы можете переписать их. - -Некоторые разработчики убеждены, что история должна быть неизменна со всеми огрехами и прочим. -Другие считают, что деревья должны быть презентабельными, до того как они выпустят их в публичный доступ. -Git учитывает оба мнения. Также как клонирование, ветвление и слияние, переписывание истории - это просто еще одна возможность, которую дает вам Git. Разумное ее использование зависит только от вас. - -=== Оставаясь корректным === - -Только что сделали коммит и уже хотите изменить запись в журнале? Запустите: - - $ git commit --amend - -чтобы изменить последнее сообщение коммита. Осознали, что забыли добавить файл? Запустите *git add*, чтобы это сделать и выполните вышеуказанную команду. - -Захотелось добавить еще немного изменений в последний коммит? Так сделайте их и запустите: - - $ git commit --amend -a - -=== ...И кое-что еще === - -Давайте представим себе, что предыдущая проблема на самом деле в десять раз хуже. После длительной работы вы сделали ряд фиксаций, но вы не очень-то довольны тем, как они организованы и кое-какие записи в журнале (commit messages) надо бы слегка переформулировать. В этом случае запустите: - - $ git rebase -i HEAD~10 - -и записи в журнале от последних 10-ти фиксаций появятся в вашем любимом редаторе (задается переменной окружения $EDITOR). Вот кусок примера: - - pick 5c6eb73 Добавил ссылку repo.or.cz - pick a311a64 Сменил порядок в "Работай как хочешь" - pick 100834f Добавил цель для push в Makefile - -После чего: - -- Убираем коммиты, удаляя строки. -- Меняем порядок коммитов, меняя порядок строк. -- Заменяем "pick" на "edit", если требуется внести изменения в коммиты. -- Заменяем "pick" на "squash" для слияния коммита с предыдущим. - -Если вы отметили коммит для исправлений, запустите: - - $ git commit --amend - -Если нет, запустите: - - $ git rebase --continue - -В общем, делайте коммиты как можно раньше и как можно чаще - всегда потом сможете за собой подчистить при помощи rebase. - -=== Локальные изменения сохраняются === - -Предположим, вы работаете над активным проектом. За какое-то время были проведены несколько коммитов, после чего синхронизируетесь с официальным деревом через слияние. Цикл повторяется несколько раз до тех пор, пока вы не готовы отправить (push) изменения в центральное дерево. - -Однако теперь история изменений в локальном клоне Git представляет собой кашу из ваших и официальных изменений. Вам бы хотелось видеть все изменения непрерывной секцией даже после слияния с официальными. - -Это работа для команды *git rebase* в виде, описанном выше. Зачастую, имеет смысл использовать флаг *--onto*, чтобы не использовать интерактивный режим. - -Также стоит взглянуть на вывод команды *git help rebase* для получения подробных примеров использования этой замечательной команды. Вы можете объединять фиксации, вы можете даже перестраивать ветки. - -=== Переписывая историю === - -Время от времени вам может понадобиться эквивалент "замазывания" людей на официальных фотографиях, только для систем контроля версий, как бы стирая их из истории в духе сталинизма. Например, предположим, что мы уже собираемся выпустить релиз проекта, но он содержит файл, который не должен стать достоянием общественности по каким-то причинам. Может я сохранил номер своей кредитки в текстовый файл и случайно добавил этот файл к файлам проекта? Просто стирать файл бесполезно - из-за контроля версий всегда можно вытащить такую из старых версий, где этот документ еще есть. Нам надо удалить файл из всех версий когда-либо существовавших. Для этого: - - $ git filter-branch --tree-filter 'rm top/secret/file' HEAD - -Стоит посмотреть вывод команды *git help filter-branch*, где обсуждается этот пример и даже предлагается более быстрый метод решения. Короче говоря, *filter-branch* позволяет изменять существенные части истории при помощи одной-единственной команды. - -В результате директория +.git/refs/original+ будет описывать состояние дел до выполнения операции. Убедитесь, что команда filter-branch проделала все, что вы хотели, и, если хотите опять использовать команду, удалите эту директорию. - -И, наконец, замените клоны вашего проекта обновленной версией, если собираетесь в дальнейшем с ними иметь дело. - -=== Создавая Историю === - -[[makinghistory]] -Хотите перевести проект под управление Git? Если сейчас он находится под управлением какой-либо из хорошо известных систем контроля версий, то весьма велики шансы на то, что кто-нибудь уже позаботился и написал необходимые скрипты для экспорта всей истории проекта в Git. - -А если все-таки нет? Тогда смотрите в сторону команды *git fast-import*, которая считывает текстовый ввод в специальном формате для создания истории Git "с нуля". - -Обычно скрипт, использующий эту команду - это наспех состряпанное нечто, -предназначенное для однократного использования, чтоб "перетащить" проект за один раз. - -В качестве примера, вставьте следующий листинг в какой-нибудь файл, типа '/tmp/history': - ----------------------------------- -commit refs/heads/master -committer Alice Thu, 01 Jan 1970 00:00:00 +0000 -data < - -int main() { - printf("Hello, world!\n"); - return 0; -} -EOT - -commit refs/heads/master -committer Bob Tue, 14 Mar 2000 01:59:26 -0800 -data < - -int main() { - write(1, "Hello, world!\n", 14); - return 0; -} -EOT - ----------------------------------- - -Затем создайте репозиторий Git из этого временного файла при помощи команд: - -$ mkdir project; cd project; git init -$ git fast-import < /tmp/history - -Вы можете извлечь (checkout) последнюю версию проекта при помощи команды: - - $ git checkout master . - -Команда *git fast-export* преобразует любой репозиторий Git в формат, понимаемый командой *git fast-import*. То есть, ее выход может быть использован как образец для тех кто пишет скрипты-преобразователи и для того, чтобы переносить репозитории в формате, хоть как-то пригодном для чтения человеком. Естественно, при помощи этих команд можно пересылать репозитории текстовых файлов через каналы передачи текста. - -=== Когда же все пошло не так? === - -Вы только что обнаружили, что кое-какой функционал вашей программы не работает, но вы совершенно отчетливо помните, что он работал всего несколько месяцев назад. Ну вот, блин! Откуда же взялась ошибка? Вы же это проверяли сразу как разработали. - -В любом случае, уже поздно сожалеть. Однако, если вам хватило ума фиксировать свои изменения часто, то Git сможет сильно помочь точно определить проблему. - - $ git bisect start - $ git bisect bad SHA1_OF_BAD_VERSION - $ git bisect good SHA1_OF_GOOD_VERSION - -Git извлечет состояние ровно посередине. Проверьте работает ли то, что сломалось, и если все еще нет, то введите: - - $ git bisect bad - -Если же работает, то замените "bad" на "good" в предыдущей команде. Git снова переместит вас в состояние посередине между "хорошей" и "плохой" ревизиями, при этом сузив круг подозреваемых ревизий вдвое. - -После нескольких итераций, этот бинарный поиск приведет вас к тому коммиту, на котором все и сломалось. После окончания выяснения, вернуть исходное состояние можно командой: - - $ git bisect reset - -Вместо того, чтоб вручную тестировать каждое изменение - автоматизируйте этот процесс при помощи команды: - - $ git bisect run COMMAND - -Git использует возвращаемое значение заданной команды, обычно "одноразового" скрипта, чтоб определить "хорошее" это было изменение или "плохое". Скрипт должен вернуть 0, если "хорошее", 125 если изменение надо пропустить и любое число от 1 до 127 если "плохое". Отрицательное возвращаемое значение прерывает бинарный поиск. - -На самом деле возможностей еще больше! На странице помощи объясняется как визуализировать бинарный поиск, проанализировать или даже воспроизвести журнал поиска, исключить изменения в которых точно все в порядке для ускорения поиска. - -=== Из-за кого все пошло наперекосяк? === - -Как и многие другие системы конроля версий, Git поддерживает команду blame: - - $ git blame FILE - -которая показывает кто и когда изменил каждую строку выбранного файла. В отличие же от многих других систем контроля версий эта операция происходит оффлайн, то есть данные берутся с локального диска. - -=== Личный опыт === - -В централизованных системах контроля версий, изменения истории - достаточно сложная операция и для ее проведения необходимо привлечение администраторов. Процедуры клонирования, ветвления и слияния невозможно осуществить без сетевого соединения. Также обстоят дела и с такими базовыми операциями как просмотр журнала изменений или фиксация изменений. В некоторых системах сетевое соединение требуется даже для просмотра собственных изменений или открытия файла для редактирования. - -Централизованные системы исключают возможность работать оффлайн и требуют более дорогой сетевой инфраструктуры, особенно с увеличением количества разработчиков. Еще более важно, из-за того все операции происходят медленнее, пользователи избегают пользоваться "продвинутыми" командами до тех пор пока не "припечет как следует". В особо "запущенных" случаях это касается и большинства базовых команд тоже. Продуктивность страдает из-за остановок в работе, когда пользователи вынуждены запускать "долгоиграющие" команды. - -Я испытал этот феномен на себе. Git был моей первой системой контроля версий. Я быстро привык нему и стал относится к его возможностям как к должному. Я предположил, что и другие системы похожи на него: выбор системы контроля версий не должен отличаться от выбора текстового редактора или браузера. - -Когда, немного позже, я был вынужден использовать централизованную систему контроля версий, я был шокирован. При использовании Git, мое, зачастую капризное, интернет-соединение не имело большого значения, но теперь разработка стала невыносимой когда от него потребовалась надежность как у жесткого диска. Плюс к этому, я обнаружил, что стал избегать использовать некоторые команды из-за получающихся в результате их выполнения задержек, а без них оказалось невозможным следовать моему стилю разработки. - -Когда мне было нужно запустить "медленную" команду, нарушение хода цепочки моих мыслей оказывало несоизмеримый ущерб разработке. Ожидая окончания связи с сервером, я должен был заниматься чем-то другим, чтоб скоротать время, например, чтением почты или написанием документации. Через некоторое время я возвращался к первоначальной задаче, но приходилось тратить уйму времени, чтоб вспомнить на чем же я остановился и что хотел делать дальше. Все-таки люди не очень приспособлены для многозадачности. - -Есть еще один интересный эффект, так называемая, трагедия общин: предвидя будущую загрузку сети, некоторые люди начинают использовать более "широкие" каналы чем им реально требуются для текущих операций в попытке предотвратить будущие задержки. Суммарная активность увеличивает загрузку сети, поощряя людей задействовать еще более высокоскоростные каналы в следующий раз, чтоб избежать еще больших задержек. +== Уроки истории == + +Вследствие распределенной природы Git, историю изменений можно легко редактировать. Однако, если вы вмешиваетесь в прошлое, будьте осторожны: изменяйте только ту часть истории, которой владеете вы и только вы. И также как государства бесконечно выясняют, кто же именно совершил и какие бесчинства, так и у вас будут проблемы с примирением после взаимодействия деревьев истории. + +Конечно, если вы также контролируете и все остальные деревья, то нет никаких проблем, поскольку вы можете переписать их. + +Некоторые разработчики убеждены, что история должна быть неизменна со всеми огрехами и прочим. Другие считают, что деревья должны быть презентабельными, до того как они выпустят их в публичный доступ. Git учитывает оба мнения. Также как клонирование, ветвление и слияние, переписывание истории - это просто еще одна возможность, которую дает вам Git. Разумное ее использование зависит только от вас. + +=== Оставаясь корректным === + +Только что сделали коммит и уже хотите изменить запись в журнале? Запустите: + + $ git commit --amend + +чтобы изменить последнее сообщение коммита. Осознали, что забыли добавить файл? Запустите *git add*, чтобы это сделать и выполните вышеуказанную команду. + +Захотелось добавить еще немного изменений в последний коммит? Так сделайте их и запустите: + + $ git commit --amend -a + +=== ...И кое-что еще === + +Давайте представим себе, что предыдущая проблема на самом деле в десять раз хуже. После длительной работы вы сделали ряд фиксаций, но вы не очень-то довольны тем, как они организованы и кое-какие записи в журнале (commit messages) надо бы слегка переформулировать. В этом случае запустите: + + $ git rebase -i HEAD~10 + +и записи в журнале от последних 10-ти фиксаций появятся в вашем любимом редакторе (задается переменной окружения $EDITOR). Вот кусок примера: + + pick 5c6eb73 Добавил ссылку repo.or.cz + pick a311a64 Сменил порядок в "Работай как хочешь" + pick 100834f Добавил цель для push в Makefile + +После чего: + +- Убираем коммиты, удаляя строки. +- Меняем порядок коммитов, меняя порядок строк. +- Заменяем "pick" на "edit", если требуется внести изменения в коммиты. +- Заменяем "pick" на "squash" для слияния коммита с предыдущим. + +Если вы отметили коммит для исправлений, запустите: + + $ git commit --amend + +Если нет, запустите: + + $ git rebase --continue + +В общем, делайте коммиты как можно раньше и как можно чаще - всегда потом сможете за собой подчистить при помощи rebase. + +=== Локальные изменения сохраняются === + +Предположим, вы работаете над активным проектом. За какое-то время были проведены несколько коммитов, после чего синхронизируетесь с официальным деревом через слияние. Цикл повторяется несколько раз до тех пор, пока вы не готовы отправить (push) изменения в центральное дерево. + +Однако теперь история изменений в локальном клоне Git представляет собой кашу из ваших и официальных изменений. Вам бы хотелось видеть все изменения непрерывной секцией даже после слияния с официальными. + +Это работа для команды *git rebase* в виде, описанном выше. Зачастую, имеет смысл использовать флаг *--onto*, чтобы не использовать интерактивный режим. + +Также стоит взглянуть на вывод команды *git help rebase* для получения подробных примеров использования этой замечательной команды. Вы можете объединять фиксации, вы можете даже перестраивать ветки. + +=== Переписывая историю === + +Время от времени вам может понадобиться эквивалент "замазывания" людей на официальных фотографиях, только для систем контроля версий, как бы стирая их из истории в духе сталинизма. Например, предположим, что мы уже собираемся выпустить релиз проекта, но он содержит файл, который не должен стать достоянием общественности по каким-то причинам. Может я сохранил номер своей кредитки в текстовый файл и случайно добавил этот файл к файлам проекта? Просто стирать файл бесполезно - из-за контроля версий всегда можно вытащить его из старых версий, где этот документ еще есть. Нам надо удалить файл из всех версий когда-либо существовавших. Для этого: + + $ git filter-branch --tree-filter 'rm top/secret/file' HEAD + +Стоит посмотреть вывод команды *git help filter-branch*, где обсуждается этот пример и даже предлагается более быстрый метод решения. Короче говоря, *filter-branch* позволяет изменять существенные части истории при помощи одной-единственной команды. + +В результате директория +.git/refs/original+ будет описывать состояние дел до выполнения операции. Убедитесь, что команда filter-branch проделала все, что вы хотели, и, если хотите опять использовать команду, удалите эту директорию. + +И, наконец, замените клоны вашего проекта обновленной версией, если собираетесь в дальнейшем с ними иметь дело. + +=== Создавая Историю === + +[[makinghistory]] +Хотите перевести проект под управление Git? Если сейчас он находится под управлением какой-либо из хорошо известных систем контроля версий, то весьма велики шансы на то, что кто-нибудь уже позаботился и написал необходимые скрипты для экспорта всей истории проекта в Git. + +А если все-таки нет? Тогда смотрите в сторону команды *git fast-import*, которая считывает текстовый ввод в специальном формате для создания истории Git "с нуля". + +Обычно скрипт, использующий эту команду - это наспех состряпанное нечто, предназначенное для однократного использования, чтоб "перетащить" проект за один раз. + +В качестве примера, вставьте следующий листинг в какой-нибудь файл, типа '/tmp/history': + +---------------------------------- +commit refs/heads/master +committer Alice Thu, 01 Jan 1970 00:00:00 +0000 +data < + +int main() { + printf("Hello, world!\n"); + return 0; +} +EOT + +commit refs/heads/master +committer Bob Tue, 14 Mar 2000 01:59:26 -0800 +data < + +int main() { + write(1, "Hello, world!\n", 14); + return 0; +} +EOT + +---------------------------------- + +Затем создайте репозиторий Git из этого временного файла при помощи команд: + +$ mkdir project; cd project; git init +$ git fast-import < /tmp/history + +Вы можете извлечь (checkout) последнюю версию проекта при помощи команды: + + $ git checkout master . + +Команда *git fast-export* преобразует любой репозиторий Git в формат, понимаемый командой *git fast-import*. То есть, ее выход может быть использован как образец для тех, кто пишет скрипты-преобразователи и для того, чтобы переносить репозитории в формате, хоть как-то пригодном для чтения человеком. Естественно, при помощи этих команд можно пересылать репозитории текстовых файлов через каналы передачи текста. + +=== Когда же все пошло не так? === + +Вы только что обнаружили, что кое-какой функционал вашей программы не работает, но вы совершенно отчетливо помните, что он работал всего несколько месяцев назад. Ну вот, блин! Откуда же взялась ошибка? Вы же это проверяли сразу, как разработали. + +В любом случае, уже поздно сожалеть. Однако, если вам хватило ума фиксировать свои изменения часто, то Git сможет сильно помочь точно определить проблему. + + $ git bisect start + $ git bisect bad SHA1_OF_BAD_VERSION + $ git bisect good SHA1_OF_GOOD_VERSION + +Git извлечет состояние ровно посередине. Проверьте, работает ли то, что сломалось, и если все еще нет, то введите: + + $ git bisect bad + +Если же работает, то замените "bad" на "good" в предыдущей команде. Git снова переместит вас в состояние посередине между "хорошей" и "плохой" ревизиями, при этом сузив круг подозреваемых ревизий вдвое. + +После нескольких итераций, этот бинарный поиск приведет вас к тому коммиту, на котором все и сломалось. После окончания выяснения, вернуть исходное состояние можно командой: + + $ git bisect reset + +Вместо того, чтобы вручную тестировать каждое изменение - автоматизируйте этот процесс при помощи команды: + + $ git bisect run COMMAND + +Git использует возвращаемое значение заданной команды, обычно "одноразового" скрипта, чтоб определить "хорошее" это было изменение или "плохое". Скрипт должен вернуть 0, если "хорошее", 125, если изменение надо пропустить и любое число от 1 до 127 если "плохое". Отрицательное возвращаемое значение прерывает бинарный поиск. + +На самом деле возможностей еще больше! На странице помощи объясняется, как визуализировать бинарный поиск, проанализировать или даже воспроизвести журнал поиска, исключить изменения, в которых точно все в порядке для ускорения поиска. + +=== Из-за кого все пошло наперекосяк? === + +Как и многие другие системы контроля версий, Git поддерживает команду blame: + + $ git blame FILE + +которая показывает, кто и когда изменил каждую строку выбранного файла. В отличие же от многих других систем контроля версий эта операция происходит офлайн, то есть данные берутся с локального диска. + +=== Личный опыт === + +В централизованных системах контроля версий, изменения истории - достаточно сложная операция и для ее проведения необходимо привлечение администраторов. Процедуры клонирования, ветвления и слияния невозможно осуществить без сетевого соединения. Также обстоят дела и с такими базовыми операциями как просмотр журнала изменений или фиксация изменений. В некоторых системах сетевое соединение требуется даже для просмотра собственных изменений или открытия файла для редактирования. + +Централизованные системы исключают возможность работать офлайн и требуют более дорогой сетевой инфраструктуры, особенно с увеличением количества разработчиков. Еще более важно, из-за того все операции происходят медленнее, пользователи избегают пользоваться "продвинутыми" командами до тех пор пока не "припечет как следует". В особо "запущенных" случаях это касается и большинства базовых команд тоже. Продуктивность страдает из-за остановок в работе, когда пользователи вынуждены запускать "долгоиграющие" команды. + +Я испытал этот феномен на себе. Git был моей первой системой контроля версий. Я быстро привык нему и стал относиться к его возможностям как к должному. Я предположил, что и другие системы похожи на него: выбор системы контроля версий не должен отличаться от выбора текстового редактора или браузера. + +Когда, немного позже, я был вынужден использовать централизованную систему контроля версий, я был шокирован. При использовании Git, мое, зачастую капризное, интернет-соединение не имело большого значения, но теперь разработка стала невыносимой, когда от него потребовалась надежность как у жесткого диска. Плюс к этому, я обнаружил, что стал избегать использовать некоторые команды из-за получающихся в результате их выполнения задержек, а без них оказалось невозможным следовать моему стилю разработки. + +Когда мне было нужно запустить "медленную" команду, нарушение хода цепочки моих мыслей оказывало несоизмеримый ущерб разработке. Ожидая окончания связи с сервером, я должен был заниматься чем-то другим, чтоб скоротать время, например, чтением почты или написанием документации. Через некоторое время я возвращался к первоначальной задаче, но приходилось тратить уйму времени, чтоб вспомнить, на чем же я остановился и что хотел делать дальше. Все-таки люди не очень приспособлены для многозадачности. + +Есть еще один интересный эффект, так называемая, трагедия общин: предвидя будущую загрузку сети, некоторые люди начинают использовать более "широкие" каналы, чем им реально требуются для текущих операций в попытке предотвратить будущие задержки. Суммарная активность увеличивает загрузку сети, поощряя людей задействовать еще более высокоскоростные каналы в следующий раз, чтоб избежать еще больших задержек. diff --git a/ru/intro.txt b/ru/intro.txt index 053b146..8d88d97 100644 --- a/ru/intro.txt +++ b/ru/intro.txt @@ -1,4 +1,4 @@ -== Введение == +== Введение == Я буду использовать аналогии, чтобы объяснить, что такое контроль версий. Если вам нужно более точное объяснение, обратитесь к http://en.wikipedia.org/wiki/Revision_control[статье википедии]. @@ -16,7 +16,7 @@ Давайте усложним условия. Пусть у вас есть несколько файлов, используемых вместе, например, исходный код проекта или файлы для вебсайта. Теперь, чтобы сохранить старую версию, вы должны скопировать весь каталог. Поддерживать множество таких версий вручную неудобно, и быстро становится дорогим удовольствием. -В некоторых играх сохранение — это и есть каталог с кучей файлов внутри. Эти игры скрывают детали от игрока и предоставляют удобный интерфейс для управления различными версиям этого каталога. +В некоторых играх сохранение — это и есть каталог с кучей файлов внутри. Эти игры скрывают детали от игрока и предоставляют удобный интерфейс для управления различными версиями этого каталога. В системах контроля версий всё точно так же. У них у всех есть приятный интерфейс для управления каталогом, полным-полно всяких данных. Вы можете сохранять состояние каталога так часто, как пожелаете, и вы можете восстановить любую из предыдущих сохраненных версий. Но, в отличие от компьютерных игр, они умнее используют дисковое пространство. Обычно только несколько файлов меняется от версии к версии, не более. Сохранение различий, а не всей копии каталога, не так сильно расходует свободное место. @@ -40,7 +40,7 @@ Широко распространенное заблуждение состоит в том, что распределенные системы непригодны для проектов, требующих официального централизованного репозитория. Ничто не может быть более далеким от истины. Получение фотоснимка не приводит к тому, что мы крадем чью-то душу. Проще говоря, клонирование главного репозитория не уменьшает его важность. -В первом приближении можно сказать, что все, что делает централизованная система контроля версий, хорошо сконструированная распределенная система может сделать лучше. Сетевые ресурсы просто дороже локальных. Хотя дальше мы увидим, что в распределенном подходе есть свои недостатки, менее вероятно провести ложные аналогии руководствуясь этим приближенным правилом. +В первом приближении можно сказать, что все, что делает централизованная система контроля версий, хорошо сконструированная распределенная система может сделать лучше. Сетевые ресурсы просто дороже локальных. Хотя дальше мы увидим, что в распределенном подходе есть свои недостатки, менее вероятно провести ложные аналогии, руководствуясь этим приближенным правилом. Небольшому проекту может понадобиться лишь часть функций, предлагаемых такой системой. Но будете ли вы использовать римские цифры в расчетах с небольшими числами? Более того, ваш проект может вырасти за пределы ваших первоначальных ожиданий. Использовать Git с самого начала — это как держать наготове швейцарский армейский нож, даже если вы только открываете им бутылки. Однажды вам безумно понадобится отвертка и вы будете рады, что под рукой у вас нечто большее, чем простая открывалка. diff --git a/ru/multiplayer.txt b/ru/multiplayer.txt index 8407fd6..6b3164f 100644 --- a/ru/multiplayer.txt +++ b/ru/multiplayer.txt @@ -1,204 +1,169 @@ -== Групповая работа в Git == - -Сначала я использовал Git для личного проекта, в котором был единственным разработчиком. -Среди команд, связанных с распределенными свойствами Git, мне требовались только *pull* и *clone*, чтобы хранить один и тот же проект в разных местах. - -Позднее я захотел опубликовать свой код при помощи Git и включить изменения помощников. Мне пришлось научиться управлять проектами, которые разрабатываются множеством людей со всего мира. К счастью, это преимущество Git и, возможно, смысл ее существования. - -=== Кто я? === - -Каждый коммит содержит имя автора и адрес электронной почты, которые отображаются по команде *git log*. -По умолчанию Git использует системные настройки для заполнения этих полей. -Чтобы установить их явно, введите: - - $ git config --global user.name "John Doe" - $ git config --global user.email johndoe@example.com - -Чтобы установить эти параметры только для текущего репозитория, опустите флаг --global. - -=== Git через SSH, HTTP === - -Предположим, у вас есть SSH доступ к веб-серверу, но Git не установлен. Git может связываться через HTTP, хотя это и менее эффективно, чем его собственный протокол. - -Скачайте, скомпилируйте, установите Git в вашем аккаунте; создайте репозиторий в директории, доступной через web: - - $ GIT_DIR=proj.git git init - -В директории "proj.git" запустите: - - $ git --bare update-server-info - $ cp hooks/post-update.sample hooks/post-update - -Для старых версий Git команда копирования выдаст ошибку, и вы должны будете запустить: - - $ chmod a+x hooks/post-update - -Теперь вы можете публиковать свои последние правки через SSH из любой копии: - - $ git push web.server:/path/to/proj.git master - -и кто угодно сможет взять ваш проект через HTTP: - - $ git clone http://web.server/proj.git - -=== Git через что угодно === - -Хотите синхронизировать репозитории без серверов или даже без сетевого подключения? -Необходимо импровизировать в чрезвычайной ситуации? -Мы рассмотрели, как <>. Мы можем обмениваться такими файлами между репозиториями -git с помощью любых носителей, но более эффективным инструментом является *git bundle*. - -Отправитель создает пакет ('bundle'): - - $ git bundle create somefile HEAD - -Затем перенесите bundle, +somefile+, такими средствами, как: email, флешка, дискета, *xxd* печать и последующее распознавание символов, чтение битов по телефону, дымовые сигналы и т.д. Получатель восстанавливает коммиты из пакета, вводя: - - $ git pull somefile - -Получатель может сделать это даже с пустым хранилищем. Несмотря на свой размер, +somefile+ содержит весь исходный Git репозиторий. - -В больших проектах для уменьшения объема пакет содержит только изменения, которых нет в других репозиториях: - - $ git bundle create somefile HEAD ^COMMON_SHA1 - -Если это делается часто, то можно легко забыть, какой коммит был отправлен последним. Справка -предлагает для решения этой проблемы использовать метки. А именно, после передачи пакета введите: - - - $ git tag -f lastbundle HEAD - -и создавайте пакеты обновления с помощью: - - $ git bundle create newbundle HEAD ^lastbundle - -=== Патчи: Общее применения === - -Патчи представляют собой текст изменений, который может быть легко понят как человеком, так и компьютером. Это делает его очень привлекательным форматом обмена. Можно послать электронное письмо с патчем для разработчиков, независимо от того, какую систему контроля версий они используют. Пока ваши корреспонденты могут читать электронную почту, они могут увидеть ваши изменения. Аналогичным образом с Вашей стороны все, что Вам требуется, - это адрес электронной почты: нет необходимости в установке онлайн хранилища Git. - -Напомним, в первой главе: - - $ git diff COMMIT - -выводит патч, который может быть вставлен в сообщение электронной почты для обсуждения. В Git репозитории, введите: - - $ git apply < FILE - -чтобы применить патч. - -В более формальной обстановке, когда имя автора и подписи должны быть зарегистрированы, генерируйте соответствующие патчи с определенной точки, набрав: - - $ git format-patch START_COMMIT - -Полученные файлы могут быть отправлены с помощью *git-send-email* или вручную. Вы также можете указать диапазон коммитов: - - $ git format-patch START_COMMIT..END_COMMIT - -На принимающей стороне сохраните email в файл и введите: - - $ git am < FILE - -Это применит входящие исправления, а также создаст коммит, включающий такую информацию, как автор. - -С web-клиентом электронной почты вам, возможно, потребуется нажать кнопку, чтобы посмотреть электронную почту в своем первоначальном виде до сохранения исправлений в файл. - -Есть небольшие различия для Mbox-подобных клиентов электронной почты, но если вы используете один -из них, то вы, вероятно, тот человек, который может легко настроить его без чтения руководства! - -=== К сожалению, мы переехали === - -Из предыдущих главах, мы видели, что после клонирования репозитория, набор *git push* или *git pull* автоматически проталкивает или стягивает с оригинального URL. Каким образом Git это делает? Секрет кроется в параметрах конфигурации инициализированных при создании клона. Давайте выполним команду: - - $ git config --list - -Опция +remote.origin.url+ контролирует исходный URL; "origin" - имя исходного -репозитория. Как и имя ветки "master" - это соглашение, мы можем -изменить или удалить этот ник, но как правило, нет причин для этого. - -Если адрес оригинального репозитория изменился, можно обновить его с помощью команды: - - $ git config remote.origin.url NEW_URL - -Опция +branch.master.merge+ задает удаленную ветвь по умолчанию для -*git pull*. В ходе первоначального клонирования, он установлен на текущую ветвь -исходного репозитория, так что даже если HEAD исходного репозитария впоследствии -переходит на другую ветку, pull будет продолжать выполняться для исходной ветви. - -Этот параметр применим только к хранилищу, которое мы впервые клонировали, в его настройках -записана +branch.master.remote+. Если мы выполняем pull из других -хранилищ, то мы должны указать необходиму нам ветку: - - $ git pull ANOTHER_URL master - -Это объясняет, почему некоторых из наших более ранних примеров push и pull -не имели аргументов. - -=== Удаленные Ветки === - -Когда вы клонируете репозиторий, вы также клонируете все его ветки. Вы можете не -заметить это, потому что Git скрывает их: вы должны указать это явно. -Это предотвращает пересечение веток в удаленном хранилище с вашими, а также делает -Git проще для начинающих. - -Список удаленных веток можно посмотреть коммандой: - - $ git branch -r - -Вы должны увидеть что-то вроде: - - origin/HEAD - origin/master - origin/experimental - -Они представляют собой ветки и HEAD в удаленном хранилище, и могут быть использованы -в обычных командах Git. Например, предположим, что вы сделали много коммитов, и -хотели бы сравнить с последней загруженной версией. Вы можете найти через -журналы для соответствующего SHA1 хэш, но это гораздо легче набрать: - - - $ git diff origin/HEAD - -Также можно увидеть лог ветки "experimental" набрав: - - $ git log origin/experimental - -=== Несколько Удаленных Веток === - -Предположим, что два других разработчиков работает над нашим проектом, и мы хотим -следить за обоими. Мы можем наблюдать более чем за одним хранилище одновременно введя: - - $ git remote add other ANOTHER_URL - $ git pull other some_branch - -Сейчас мы объединились в ветвь второго хранилища, и мы получили -легкий доступ для всех ветвей во всех репозиториях: - - $ git diff origin/experimental^ other/some_branch~5 - -Но что, если мы просто хотим сравнить их изменения, не затрагивающие нашу собственную -работу? Иными словами, мы хотим, чтобы изучить их ветки без изменения нашей рабочей папки. -В этом случае вместо pull наберите: - - $ git fetch # Fetch from origin, the default. - $ git fetch other # Fetch from the second programmer. - -Это выбирает их историю, и ничего больше, так что, хотя рабочий каталог остается -нетронутыми, мы можем обратиться в любую ветвь в любом хранилище командами Git. -Кстати, за кулисами, pull просто fetch за которым следует *git merge*; -а последний добавляется в рабочую директорию. -Обычно мы используем pull, потому что мы хотим объединить после выполнения fetch; -эта ситуация представляет собой заметное исключение. - -См. *git help remote* о том, как удалить удаленные хранилища, игнорировать определенные -ветки и многое другое. - -=== Мои Настройки === - -Для моих проектов я люблю использовать готовые Git репозитории, в которые я могу сделать pull. Некоторые Git хостинги позволяют создавать собственные ветки проекта нажатием одной кнопки. - -После того как я выгрузил дерево, я запускаю Git команды для навигации и изучения изменении, которые в идеале хорошо организованны и описаны. Я объединяю мои собственные неопубликованные изменения, и, возможно, делаю дальнейшие изменения. После изменения, я выгружаю изменения в официальный репозиторий. - -Хотя я редко получают взносы, я считаю, этот подход хорошо масштабируется. Смотрите http://torvalds-family.blogspot.com/2009/06/happiness-is-warm-scm.html[этот пост в блоге Линуса Торвальдса]. - -Пребывание в мире Git немного более удобно, чем патч-файлы, как это экономит мне шаги конвертации их в коммиты Git. Кроме того, Git автоматически обрабатывает информацию, такую как запись с именем автора и адресом электронной почты, а также время и дату, и просит автора описывать свои собственные изменения. +== Групповая работа в Git == + +Сначала я использовал Git для личного проекта, в котором был единственным разработчиком. Среди команд, связанных с распределенными свойствами Git, мне требовались только *pull* и *clone*, чтобы хранить один и тот же проект в разных местах. + +Позднее я захотел опубликовать свой код при помощи Git и включить изменения помощников. Мне пришлось научиться управлять проектами, которые разрабатываются множеством людей со всего мира. К счастью, это преимущество Git и, возможно, смысл ее существования. + +=== Кто я? === + +Каждый коммит содержит имя автора и адрес электронной почты, которые отображаются по команде *git log*. По умолчанию Git использует системные настройки для заполнения этих полей. Чтобы установить их явно, введите: + + $ git config --global user.name "John Doe" + $ git config --global user.email johndoe@example.com + +Чтобы установить эти параметры только для текущего репозитория, опустите флаг --global. + +=== Git через SSH, HTTP === + +Предположим, у вас есть SSH доступ к веб-серверу, но Git не установлен. Git может связываться через HTTP, хотя это и менее эффективно, чем его собственный протокол. + +Скачайте, скомпилируйте, установите Git в вашем аккаунте; создайте репозиторий в директории, доступной через web: + + $ GIT_DIR=proj.git git init + +В директории "proj.git" запустите: + + $ git --bare update-server-info + $ cp hooks/post-update.sample hooks/post-update + +Для старых версий Git команда копирования выдаст ошибку, и вы должны будете запустить: + + $ chmod a+x hooks/post-update + +Теперь вы можете публиковать свои последние правки через SSH из любой копии: + + $ git push web.server:/path/to/proj.git master + +и кто угодно сможет взять ваш проект через HTTP: + + $ git clone http://web.server/proj.git + +=== Git через что угодно === + +Хотите синхронизировать репозитории без серверов или даже без сетевого подключения? Необходимо импровизировать в чрезвычайной ситуации? Мы рассмотрели, как <>. Мы можем обмениваться такими файлами между репозиториями git с помощью любых носителей, но более эффективным инструментом является *git bundle*. + +Отправитель создает пакет ('bundle'): + + $ git bundle create somefile HEAD + +Затем перенесите bundle, +somefile+, такими средствами, как: email, флешка, дискета, *xxd* печать и последующее распознавание символов, чтение битов по телефону, дымовые сигналы и т.д. Получатель восстанавливает коммиты из пакета, вводя: + + $ git pull somefile + +Получатель может сделать это даже с пустым хранилищем. Несмотря на свой размер, +somefile+ содержит весь исходный Git репозиторий. + +В больших проектах для уменьшения объема пакет содержит только изменения, которых нет в других репозиториях: + + $ git bundle create somefile HEAD ^COMMON_SHA1 + +Если это делается часто, то можно легко забыть, какой коммит был отправлен последним. Справка предлагает для решения этой проблемы использовать метки. А именно, после передачи пакета введите: + + $ git tag -f lastbundle HEAD + +и создавайте пакеты обновления с помощью: + + $ git bundle create newbundle HEAD ^lastbundle + +=== Патчи: Общее применения === + +Патчи представляют собой текст изменений, который может быть легко понят как человеком, так и компьютером. Это делает его очень привлекательным форматом обмена. Можно послать электронное письмо с патчем для разработчиков, независимо от того, какую систему контроля версий они используют. Пока ваши корреспонденты могут читать электронную почту, они могут увидеть ваши изменения. Аналогичным образом с Вашей стороны все, что Вам требуется, - это адрес электронной почты: нет необходимости в установке онлайн хранилища Git. + +Напомним, в первой главе: + + $ git diff COMMIT + +выводит патч, который может быть вставлен в сообщение электронной почты для обсуждения. В Git репозитории, введите: + + $ git apply < FILE + +чтобы применить патч. + +В более формальной обстановке, когда имя автора и подписи должны быть зарегистрированы, генерируйте соответствующие патчи с определенной точки, набрав: + + $ git format-patch START_COMMIT + +Полученные файлы могут быть отправлены с помощью *git-send-email* или вручную. Вы также можете указать диапазон коммитов: + + $ git format-patch START_COMMIT..END_COMMIT + +На принимающей стороне сохраните email в файл и введите: + + $ git am < FILE + +Это применит входящие исправления, а также создаст коммит, включающий такую информацию, как автор. + +С web-клиентом электронной почты вам, возможно, потребуется нажать кнопку, чтобы посмотреть электронную почту в своем первоначальном виде до сохранения исправлений в файл. + +Есть небольшие различия для Mbox-подобных клиентов электронной почты, но если вы используете один из них, то вы, вероятно, тот человек, который может легко настроить его без чтения руководства! + +=== К сожалению, мы переехали === + +Из предыдущих главах, мы видели, что после клонирования репозитория, набор *git push* или *git pull* автоматически проталкивает или стягивает изменения с оригинального URL. Каким образом Git это делает? Секрет кроется в параметрах конфигурации инициализированных при создании клона. Давайте выполним команду: + + $ git config --list + +Опция +remote.origin.url+ контролирует исходный URL; "origin" - имя исходного репозитория. Как и имя ветки "master" - это соглашение, мы можем изменить или удалить этот ник, но, как правило, нет причин для этого. + +Если адрес оригинального репозитория изменился, можно обновить его с помощью команды: + + $ git config remote.origin.url NEW_URL + +Опция +branch.master.merge+ задает удаленную ветвь по умолчанию для *git pull*. В ходе первоначального клонирования, он установлен на текущую ветвь исходного репозитория, так что даже если HEAD исходного репозитория впоследствии переходит на другую ветку, pull будет продолжать выполняться для исходной ветви. + +Этот параметр применим только к хранилищу, которое мы впервые клонировали, в его настройках записана +branch.master.remote+. Если мы выполняем pull из других хранилищ, то мы должны указать необходимую нам ветку: + + $ git pull ANOTHER_URL master + +Это объясняет, почему некоторых из наших более ранних примеров push и pull не имели аргументов. + +=== Удаленные Ветки === + +Когда вы клонируете репозиторий, вы также клонируете все его ветки. Вы можете не заметить это, потому что Git скрывает их: вы должны указать это явно. Это предотвращает пересечение веток в удаленном хранилище с вашими, а также делает Git проще для начинающих. + +Список удаленных веток можно посмотреть командой: + + $ git branch -r + +Вы должны увидеть что-то вроде: + + origin/HEAD + origin/master + origin/experimental + +Они представляют собой ветки и HEAD в удаленном хранилище, и могут быть использованы в обычных командах Git. Например, предположим, что вы сделали много коммитов, и хотели бы сравнить с последней загруженной версией. Вы можете найти через журнал соответствующий SHA1 хеш, но гораздо легче набрать: + + $ git diff origin/HEAD + +Также можно увидеть лог ветки "experimental" набрав: + + $ git log origin/experimental + +=== Несколько Удаленных Веток === + +Предположим, что два других разработчиков работает над нашим проектом, и мы хотим следить за обоими. Мы можем наблюдать более чем за одним хранилище одновременно, введя: + + $ git remote add other ANOTHER_URL + $ git pull other some_branch + +Сейчас мы объединились в ветвь второго хранилища, и мы получили легкий доступ для всех ветвей во всех репозиториях: + + $ git diff origin/experimental^ other/some_branch~5 + +Но что, если мы просто хотим сравнить их изменения, не затрагивающие нашу собственную работу? Иными словами, мы хотим, чтобы изучить их ветки без изменения нашей рабочей папки. В этом случае вместо pull наберите: + + $ git fetch # Fetch from origin, the default. + $ git fetch other # Fetch from the second programmer. + +Это выбирает их историю, и ничего больше, так что, хотя рабочий каталог остается нетронутыми, мы можем обратиться в любую ветвь в любом хранилище командами Git. Кстати, за кулисами, pull это просто fetch, за которым следует *git merge*; а последний добавляется в рабочую директорию. Обычно мы используем pull, потому что мы хотим объединить после выполнения fetch; эта ситуация представляет собой заметное исключение. + +См. *git help remote* о том, как удалить удаленные хранилища, игнорировать определенные ветки и многое другое. + +=== Мои Настройки === + +Для моих проектов я люблю использовать готовые Git репозитории, в которые я могу сделать pull. Некоторые Git хостинги позволяют создавать собственные ветки проекта нажатием одной кнопки. + +После того как я выгрузил дерево, я запускаю Git команды для навигации и изучения изменений, которые в идеале хорошо организованны и описаны. Я объединяю мои собственные неопубликованные изменения, и, возможно, делаю дальнейшие изменения. После изменения, я выгружаю изменения в официальный репозиторий. + +Хотя я редко получают взносы, я считаю, этот подход хорошо масштабируется. Смотрите http://torvalds-family.blogspot.com/2009/06/happiness-is-warm-scm.html[этот пост в блоге Линуса Торвальдса]. + +Пребывание в мире Git немного более удобно, чем патч-файлы, как это экономит мне шаги конвертации их в коммиты Git. Кроме того, Git автоматически обрабатывает информацию, такую как запись с именем автора и адресом электронной почты, а также время и дату, и просит автора описывать свои собственные изменения. diff --git a/ru/preface.txt b/ru/preface.txt index 6a63af8..7691e52 100644 --- a/ru/preface.txt +++ b/ru/preface.txt @@ -1,16 +1,16 @@ -= Магия Git = += Магия Git = Ben Lynn Август 2007 == Предисловие == -http://git.or.cz/[Git] это Швейцарский армейский нож контроля версий. Надежный универсальный многоцелевой инструмент контроля версий, чья черезвычайная гибкость делает его сложным в изучении даже для многих профессионалов. +http://git.or.cz/[Git] это Швейцарский армейский нож контроля версий. Надежный универсальный многоцелевой инструмент контроля версий, чья чрезвычайная гибкость делает его сложным в изучении даже для многих профессионалов. Как говорил Артур Кларк - любая достаточно развитая технология неотличима от магии. Это отличный способ подхода Git: новички могут игнорировать принципы его внутренней работы и рассматривать Git как гизмо, который может поражать друзей и приводить в бешенство врагов своими чудесными способностями. -Вместо того, чтобы вдаваться в подробности, мы предоставляем грубую инструкцию для конкретных действий. После частого использования вы постепенно поймете как работает каждый трюк и как адаптировать рецепты для ваших нужд. +Вместо того чтобы вдаваться в подробности, мы предоставляем грубую инструкцию для конкретных действий. После частого использования вы постепенно поймете как работает каждый трюк и как адаптировать рецепты для ваших нужд. -.Переводчики +Переводчики - http://docs.google.com/View?id=dfwthj68_675gz3bw8kj[ Китайский (упрощенный)]: JunJie, Meng и JiangWei. Хостинг - Google Docs. - link:/~blynn/gitmagic/intl/es/[Испанский]: Rodrigo Toledo. diff --git a/ru/secrets.txt b/ru/secrets.txt index dddfc0d..9b82dff 100644 --- a/ru/secrets.txt +++ b/ru/secrets.txt @@ -1,4 +1,4 @@ -== Раскрываем тайны == +== Раскрываем тайны == Мы заглянем под капот и объясним, как Git творит свои чудеса. Я опущу некоторые детали. Для более подробного изучения описаний обратитесь к http://www.kernel.org/pub/software/scm/git/docs/user-manual.html[Руководству пользователя]. @@ -6,21 +6,21 @@ Как Git может быть таким ненавязчивым? Помимо коммитов время от времени и слияния, вы можете работать так, как будто вы не знали, что контроль версий существует. То есть, пока вам это не нужно, вы его не замечаете, и вот, когда он понадобился вы рады, что Git наблюдал за вами все это время. -Другие системы контроля версий, не позволят вам забыть о них. Права доступа к файлам может быть только для чтения, пока вы явно не укажите серверу, какие файлы вы хотите изменить. Центральный сервер может отслеживать кто извлекал какой код и когда. Когда сеть падает вы можете от этого пострадать. Разработчики постоянно борются с виртуальной волокитой и бюрократизмом. +Другие системы контроля версий, не позволят вам забыть о них. Права доступа к файлам может быть только для чтения, пока вы явно не укажите серверу, какие файлы вы хотите изменить. Центральный сервер может отслеживать, кто извлекал какой код и когда. Когда сеть падает, вы можете от этого пострадать. Разработчики постоянно борются с виртуальной волокитой и бюрократизмом. -Секрет заключается в каталоге `.git` в вашей рабочей директории. Git хранит историю вашего проекта здесь. Из-за имени, начинающегося с точки каталог не отображается в выводе команды `ls`. Кроме комманд *git push* и *git pull* все остальные операции контроля версий работают в этом каталоге. +Секрет заключается в каталоге `.git` в вашей рабочей директории. Git хранит историю вашего проекта здесь. Из-за имени, начинающегося с точки, каталог не отображается в выводе команды `ls`. Кроме команд *git push* и *git pull* все остальные операции контроля версий работают в этом каталоге. -Вы имеете полный контроль над судьбой ваших файлов потому что Gitу не важно, что вы делаете с ними. Git можно легко восстановить сохраненное в `.git` состояние в любое время. +Вы имеете полный контроль над судьбой ваших файлов, потому что Git'у не важно, что вы делаете с ними. Git можно легко восстановить сохраненное в `.git` состояние в любое время. === Целостность === Большинство людей ассоциируют с криптографией поддержание информации в секрете, но другой не менее важной задачей является поддержание информации в сохранности. Правильное использование криптографических хеш-функций может предотвратить случайные или злонамеренные повреждения данных. -SHA1 хэш может рассматриваться как уникальный 160-битный идентификационный номер для каждой строки байт, с которой вы сталкиваетесь в вашей жизни. На самом деле гораздо больше: каждая строка байтов, которую любой человек когда-нибудь использует в течение многих жизней. +SHA1 хеш может рассматриваться как уникальный 160-битный идентификационный номер для каждой строки байт, с которой вы сталкиваетесь в вашей жизни. На самом деле гораздо больше: каждая строка байтов, которую любой человек когда-нибудь использует в течение многих жизней. -Так как SHA1 хэш сам является последовательностью байтов, мы можем получить хэш строки байтов, содержащей другие хэши. Это простое наблюдение на удивление полезно: смотрите 'hash chains' (цепи хешей). Позднее мы увидим, как Git использует их для эффективного обеспечения целостности данных. +Так как SHA1 хеш сам является последовательностью байтов, мы можем получить хеш строки байтов, содержащей другие хеши. Это простое наблюдение на удивление полезно: смотрите 'hash chains' (цепи хешей). Позднее мы увидим, как Git использует их для эффективного обеспечения целостности данных. -Короче говоря, Git хранит ваши данные в подкаталоге ".git/objects", где вместо обычных файлов, вы увидите только ID. С помощью идентификаторов как имен файлов, а также нескольких лок-файлов и трюков с временем создания файлов, Git преобразует любую скромную файловую систему в эффективную и надежную базу данных. +Короче говоря, Git хранит ваши данные в подкаталоге ".git/objects", где вместо обычных файлов, вы увидите только ID. С помощью таких идентификаторов как имен файлов, а также нескольких лок-файлов и трюков со временем создания файлов, Git преобразует любую скромную файловую систему в эффективную и надежную базу данных. === Интеллект === @@ -30,16 +30,15 @@ Git эвристически находит переименованные фа === Индексация === -Для каждого отслеживаемого файла, Git записывает информацию, такую как размер, время создания и время последнего изменения в файл, известный как "индекс". Чтобы определить, что файл был изменен, Git сравнивает его текущее состояние с тем, что сохранено в индексе. Если они совпадают, то Git может пропустить перечитывание это файла. +Для каждого отслеживаемого файла, Git записывает информацию, такую как размер, время создания и время последнего изменения в файл, известный как "индекс". Чтобы определить, что файл был изменен, Git сравнивает его текущее состояние с тем, что сохранено в индексе. Если они совпадают, то Git может пропустить проверку этого файла. Поскольку чтение этой информации значительно быстрее, чем чтение всего файла, то если вы редактировали только несколько файлов, Git может обновить свой индекс почти мгновенно. === Голые репозитории === -Вам, возможно, было интересно, какой формат используется в этих онлайн Git репозиториях. -Они такие-же хранилища Git, как ваш каталог `.git`, кроме того что обычно называются `proj.git`, и они не имеют рабочую директорию связанную с ними. +Вам, возможно, было интересно, какой формат используется в этих онлайн Git репозиториях. Там такие же хранилища Git, как и ваш каталог `.git`, разве что он обычно называются `proj.git`, и они не имеют рабочую директорию, связанную с ними. -Большинство команд Git рассчитывают что индекс Git находится в каталоге `.git`, и не смогут работать на этих голых хранилищах. Исправить это можно, установив переменную окружения `GIT_DIR` в значение, равное пути к репозиторию, или запустить Git в этом каталоге с опцией `--bare`. +Большинство команд Git рассчитывают, что индекс Git находится в каталоге `.git`, и не смогут работать на этих голых хранилищах. Исправить это можно, установив переменную окружения `GIT_DIR` в значение, равное пути к репозиторию, или запустить Git в этом каталоге с опцией `--bare`. === Происхождение Git === @@ -60,7 +59,7 @@ Git эвристически находит переименованные фа Вы увидите +.git/objects/aa/823728ea7d592acc69b36875a482cdf3fd5c8d+. -Откуда я знаю это, не зная имени файла? Это потому, что SHA1 хэш строки: +Откуда я знаю это, не зная имени файла? Это потому, что SHA1 хеш строки: "blob" SP "6" NUL "sweet" LF @@ -71,13 +70,13 @@ Git эвристически находит переименованные фа Кстати, это написано с учетом особенностей оболочки Bash, другие оболочки возможно способны обработать NUL в командной строке, что исключает необходимость использовать костыль с *tr*. -Git является 'контент-адресуемым': файлы хранятся в независимости от их имени, а по хэшу содержимого, которое мы называем 'BLOB объект'. Мы можем думать о хеше как о уникальном идентификаторе для содержимого файла, так что в некотором смысле мы обращаемся к файлам по их содержимому. Начальный "blob 6" является лишь заголовком, состоящий из типа объекта и его длины в байтах; она упрощает внутренний учет. +Git является 'контент-адресуемым': файлы хранятся в независимости от их имени, а по хешу содержимого, которое мы называем 'BLOB объект'. Мы можем думать о хеше как об уникальном идентификаторе для содержимого файла, так что в некотором смысле мы обращаемся к файлам по их содержимому. Начальный "blob 6" является лишь заголовком, состоящий из типа объекта и его длины в байтах; она упрощает внутренний учет. Таким образом, я могу легко предсказать, что вы увидите. Имя файла не имеет никакого отношения: только данные внутри используется для построения BLOB объекта. -Вам может быть интересно, что происходит с идентичными файлами. Попробуйте добавить копии с любыми именами файлов вообще. Содержание +.git/objects+ останется тем-же независимо от того, сколько копий вы добавите. Git только хранит данные один раз. +Вам может быть интересно, что происходит с идентичными файлами. Попробуйте добавить копии с любыми именами файлов вообще. Содержание +.git/objects+ останется тем же независимо от того, сколько копий вы добавите. Git только хранит данные один раз. -Кстати, файлы в директории +.git/objects+ сжимаются с Zlib поэтому вы не сможете просмотреть их непосредственно. Пропустите их через фильтр http://www.zlib.net/zpipe.c [zpipe-D], или введите: +Кстати, файлы в директории +.git/objects+ сжимаются с Zlib, поэтому вы не сможете просмотреть их непосредственно. Пропустите их через фильтр http://www.zlib.net/zpipe.c [zpipe-D], или введите: $ git cat-file -p aa823728ea7d592acc69b36875a482cdf3fd5c8d @@ -85,20 +84,19 @@ Git является 'контент-адресуемым': файлы хран ==== Деревья ==== -Но где же имена файлов? Они должны храниться где-то на определенном этапе. -Git получает информацию об имени во время коммита: +Но где же имена файлов? Они должны храниться где-то на определенном этапе. Git получает информацию об имени во время коммита: $ git commit # Type some message. $ find .git/objects -type f -Теперь вы должны увидеть 3 объекта. На этот раз я не могу сказать вам, какие 2 новые файлы, так как это частично зависит от выбранного имени файла. Допустим вы назвали его "rose". Если это не так, то вы можете переписать историю, чтобы она выглядела как будто вы это сделали: +Теперь вы должны увидеть 3 объекта. На этот раз я не могу сказать вам, какие 2 новые файлы, так как это частично зависит от выбранного имени файла. Допустим, вы назвали его "rose". Если это не так, то вы можете переписать историю, чтобы она выглядела как будто вы это сделали: $ git filter-branch --tree-filter 'mv YOUR_FILENAME rose' $ find .git/objects -type f Теперь вы должны увидеть файл +.git/objects/05/b217bb859794d08bb9e4f7f04cbda4b207fbe9+, потому что это -SHA1 хэш его содержимого: +SHA1 хеш его содержимого: "tree" SP "32" NUL "100644 rose" NUL 0xaa823728ea7d592acc69b36875a482cdf3fd5c8d @@ -110,11 +108,11 @@ SHA1 хэш его содержимого: $ zpipe -d < .git/objects/05/b217bb859794d08bb9e4f7f04cbda4b207fbe9 | sha1sum -Проверка хеша сложнее чем через CAT-файла, поскольку его вывод содержит больше, чем сырой несжатый объектный файл. +Проверка хеша сложнее, чем через CAT-файл, поскольку его вывод содержит больше, чем сырой несжатый объектный файл. -Этот файл является объектом 'tree': список цепочек, состоящих из типа файла, имени файла, и хэша. В нашем примере это тип файла "100644", это означает что "rose", является обычным файлом и хэш BLOB объект, в котором находится содержимое "rose". Другие возможные типы файлов - исполняемые файлы, символические ссылки или каталоги. В последнем случае, хэш указывает на дереве объектов. +Этот файл является объектом 'tree': список цепочек, состоящих из типа файла, имени файла, и хеша. В нашем примере это тип файла "100644", это означает что "rose", является обычным файлом и хеш BLOB объект, в котором находится содержимое "rose". Другие возможные типы файлов - исполняемые файлы, символические ссылки или каталоги. В последнем случае, хеш указывает на дереве объектов. -Если вы запускали filter-branch, у вас будут старые объекты которые вам больше не нужны. Хотя они будут автоматически выброшены сразу после истечения льготного периода, мы удалим их сейчас, чтобы наш игрушечный пример было легче исследовать: +Если вы запускали filter-branch, у вас будут старые объекты, которые вам больше не нужны. Хотя они будут автоматически выброшены сразу после истечения льготного периода, мы удалим их сейчас, чтобы наш игрушечный пример было легче исследовать: $ rm -r .git/refs/original $ git reflog expire --expire=now --all @@ -138,7 +136,7 @@ SHA1 хэш его содержимого: Теперь вы должны увидеть +.git/objects/49/993fe130c4b3bf24857a15d7969c396b7bc187+ -который является SHA1 хэшем его содержание: +который является SHA1 хешем его содержание: "commit 158" NUL "tree 05b217bb859794d08bb9e4f7f04cbda4b207fbe9" LF @@ -147,7 +145,7 @@ SHA1 хэш его содержимого: LF "Shakespeare" LF -Как и раньше, вы можете запустить zpipe или cat-file, чтобы увидить это самостоятельно. +Как и раньше, вы можете запустить zpipe или cat-file, чтобы увидеть это самостоятельно. Это первый коммит, и поэтому нет родительского коммита, но последующие коммиты всегда будет содержать хотя бы одну строку идентифицирующую родительский коммит. @@ -155,14 +153,10 @@ SHA1 хэш его содержимого: Там мало сказано. Мы только что открыли секрет мощи Git. Это кажется слишком простым: похоже, что вы могли бы смешать вместе несколько скриптов оболочки и добавить немного кода на C, сделанного в считанные часы. По сути, это точное описание ранних версий Git. Тем не менее, помимо гениальных трюков упаковки, чтобы сэкономить место, и трюков индексации, чтобы сэкономить время, мы теперь знаем, как ловко Git преображает файловую систему в базу данных, идеально подходящую для контроля версий. -Например, если какой-то файл объекта базы данных повредила ошибка диска, то его хэш больше не совпадает, предупреждая о проблеме. При хешировании хэшей других объектов, мы сохраняем целостность на всех уровнях. Коммит являются атомными, то есть, никогда нельзя закоммитить лишь часть изменений: мы можем только вычислить хэш коммита и сохранить его в базу данных после того как мы сохраним все соответствующие деревья, блобы и родительские коммиты. Объектная база данных застрахована от неожиданных прерываний работы с ней таких как перебои в подаче электроэнергии. +Например, если какой-то файл объекта базы данных повредила ошибка диска, то его хеш больше не совпадает, предупреждая о проблеме. При создании хешей других объектов, мы сохраняем целостность на всех уровнях. Коммит являются атомными, то есть, никогда нельзя закоммитить лишь часть изменений: мы можем только вычислить хеш коммита и сохранить его в базу данных после того как мы сохраним все соответствующие деревья, блобы и родительские коммиты. Объектная база данных застрахована от неожиданных прерываний работы с ней, таких как перебои в подаче электроэнергии. -Мы наносим поражение даже самым хитрым противникам. Пусть кто-то попытается тайно изменить содержимое файла в древней версии проекта. Чтобы сохранить объектную базу данных согласованной, они также должны изменить хеш соответствующего объекта BLOB, поскольку это теперь другая последовательность байтов. Это означает, что нужно поменять хэш всех деревьев, содержащих ссылки на объект этого файла, что в свою очередь изменит хэши коммитов всех объектов с участием таких деревьев, в дополнение к хэшам всех потомков этих коммитов. Это означает, хэш официальной головной ревизии будет отличаться от хеша в этом плохом хранилище. По следам несовпадения хэшей мы можем локализовать изуродованный файл, а также коммит, где он впервые был поврежден. +Мы наносим поражение даже самым хитрым противникам. Пусть кто-то попытается тайно изменить содержимое файла в древней версии проекта. Чтобы сохранить объектную базу данных согласованной, они также должны изменить хеш соответствующего объекта BLOB, поскольку это теперь другая последовательность байтов. Это означает, что нужно поменять хеш всех деревьев, содержащих ссылки на объект этого файла, что в свою очередь изменит хеши коммитов всех объектов с участием таких деревьев, в дополнение к хешам всех потомков этих коммитов. Это означает, хеш официальной головной ревизии будет отличаться от хеша в этом плохом хранилище. По следам несовпадения хешей мы можем локализовать изуродованный файл, а также коммит, где он впервые был поврежден. -Короче говоря, пока 20 байт представляющие последний коммит в безопасности, невозможно изменить репозиторий Git. +Короче говоря, пока 20 байт, представляющие последний коммит, в безопасности, невозможно изменить репозиторий Git. -Как насчет знаменитых черт Git? Создание ветки? Слияние? Теги? Более подробно. -Текущая HEAD хранится в файле +.git/HEAD+, который содержит хэш объекта фиксации. -Хэш обновляется во время коммита, а также при выполнении многих других команд. -Ветки почти одинаковы: они представляют собой файлы в +.git/refs/heads+. -Тэги тоже: они живут в +.git/refs/tags+, но они обновляться различными наборами команд. +Как насчет знаменитых черт Git? Создание ветки? Слияние? Теги? Более подробно. Текущий HEAD хранится в файле +.git/HEAD+, который содержит хеш объекта фиксации. Хеш обновляется во время коммита, а также при выполнении многих других команд. Ветки почти одинаковы: они представляют собой файлы в +.git/refs/heads+. Тэги тоже: они живут в +.git/refs/tags+, но они обновляться различными наборами команд. diff --git a/ru/translate.txt b/ru/translate.txt index d62adbb..b374c3e 100644 --- a/ru/translate.txt +++ b/ru/translate.txt @@ -1,7 +1,6 @@ -== Приложение А: Перевод этого руководства == +== Приложение А: Перевод этого руководства == -Клонируйте исходные тексты, затем создайте соответствующую директорию http://www.iana.org/assignments/language-subtag-registry[языковой тег IETF]: см -http://www.w3.org/International/articles/language-tags/Overview.en.php[статья W3C по интернационализации]. К примеру, английский язык "en", японский "ja", традиционный китайский "zh-Hant". Скопируйте в директорию файлы +txt+ из "en" поддиректории и переведите их. +Клонируйте исходные тексты, затем создайте соответствующую директорию http://www.iana.org/assignments/language-subtag-registry[языковой тег IETF]: см http://www.w3.org/International/articles/language-tags/Overview.en.php[статья W3C по интернационализации]. К примеру, английский язык "en", японский "ja", традиционный китайский "zh-Hant". Скопируйте в директорию файлы +txt+ из "en" поддиректории и переведите их. К примеру, для перевода руководства на http://en.wikipedia.org/wiki/Klingon_language[Klingon], вы можете набрать: @@ -17,11 +16,4 @@ http://www.w3.org/International/articles/language-tags/Overview.en.php[стат $ make LANG=tlh $ firefox book.html -Почаще делайте коммиты, потом дайте знать когда ваш перевод готов -На GitHub.com есть веб-интерфейс, который позволяет упростить всю работу: -сделать форк "gitmagic" проекта, внести ваши изменения, потом попросить меня о слиянии. -Я бы хотел чтобы переводы придерживались такой схемы и мои скрипты могли легко создать -HTML и PDF версии. Также эта схема позволяет удобно хранить все переводы в официальном -репозитории. Но пожалуйста, поступайте как вам удобнее: к примеру, китайский переводчик -использовал Google Docs. Я рад тому что ваша работа открывает доступ большему числу людей -к моей работе. +Почаще делайте коммиты, потом дайте знать когда ваш перевод готов На GitHub.com есть веб-интерфейс, который позволяет упростить всю работу: сделать форк "gitmagic" проекта, внести ваши изменения, потом попросить меня о слиянии. Я бы хотел, чтобы переводы придерживались такой схемы и мои скрипты могли легко создать HTML и PDF версии. Также эта схема позволяет удобно хранить все переводы в официальном репозитории. Но пожалуйста, поступайте как вам удобнее: к примеру, китайский переводчик использовал Google Docs. Я рад тому, что ваша работа открывает доступ большему числу людей к моей работе.