From f7e9275e5fdff15d7a257753445144104c705946 Mon Sep 17 00:00:00 2001 From: Dexter Morganov Date: Mon, 18 Feb 2019 11:01:31 +0300 Subject: [PATCH] Translated section 05.03 --- .../sections/maintaining.asc | 391 +++++++++--------- 1 file changed, 197 insertions(+), 194 deletions(-) diff --git a/book/05-distributed-git/sections/maintaining.asc b/book/05-distributed-git/sections/maintaining.asc index aa2bd1ba..8c36e16d 100644 --- a/book/05-distributed-git/sections/maintaining.asc +++ b/book/05-distributed-git/sections/maintaining.asc @@ -1,59 +1,59 @@ -=== Maintaining a Project +=== Сопровождение проекта (((maintaining a project))) -In addition to knowing how to effectively contribute to a project, you'll likely need to know how to maintain one. -This can consist of accepting and applying patches generated via `format-patch` and e-mailed to you, or integrating changes in remote branches for repositories you've added as remotes to your project. -Whether you maintain a canonical repository or want to help by verifying or approving patches, you need to know how to accept work in a way that is clearest for other contributors and sustainable by you over the long run. +В дополнение к эффективному участию в проекте, было бы неплохо знать как его сопровождать. +Сопровождение может включать в себя принятие и применение патчей, сгенерированных с помощью `format-patch` и отправленных вам по почте, или интеграцию изменений в ветках удаленных репозиториев. +Независимо от того, поддерживаете ли вы канонический репозиторий или просто хотите помочь в проверке или применении патчей, вам необходимо знать каким образом следует принимать работу, чтобы это было наиболее понятно для других участников и было бы приемлемым для вас в долгосрочной перспективе. -==== Working in Topic Branches +==== Работа с тематическими ветками (((branches, topic))) -When you're thinking of integrating new work, it's generally a good idea to try it out in a topic branch – a temporary branch specifically made to try out that new work. -This way, it's easy to tweak a patch individually and leave it if it's not working until you have time to come back to it. -If you create a simple branch name based on the theme of the work you're going to try, such as `ruby_client` or something similarly descriptive, you can easily remember it if you have to abandon it for a while and come back later. -The maintainer of the Git project tends to namespace these branches as well – such as `sc/ruby_client`, where `sc` is short for the person who contributed the work. -As you'll remember, you can create the branch based off your master branch like this: +Перед интеграцией новых изменений желательно проверить их в тематической ветке -- временной ветке, сециально созданной для проверки работоспособности новых изменений. +Таким образом, можно применять патчи по одному и пропускать неработающие, пока не найдётся время к ним вернуться. +Если вы создадите ветку с коротким и понятным названием, основанным на тематике изменений, например, `ruby_client` или что-то похожее, то без труда можно будет вернуться к ней, если пришлось на какое-то время отказаться от работы с ней. +Сопровождающему Git проекта свойственно использовать пространство имен для веток, например, `sc/ruby_client`, где `sc` - это сокращение от имени того, кто проделал работу. +Как известно, ветки можно создавать на основании базовой ветки, например: [source,console] ----- $ git branch sc/ruby_client master ----- -Or, if you want to also switch to it immediately, you can use the `checkout -b` option: +Если вы хотите сразу переключиться на создаваемую ветку, то используйте опцию `checkout -b`: [source,console] ----- $ git checkout -b sc/ruby_client master ----- -Now you're ready to add your contributed work into this topic branch and determine if you want to merge it into your longer-term branches. +Теперь вы можете добавить новые изменения в созданную тематическую ветку и определить хотите ли слить эти изменения в ваши долгосрочные ветки. [[r_patches_from_email]] -==== Applying Patches from E-mail +==== Применение патчей, полученных по почте (((email, applying patches from))) -If you receive a patch over e-mail that you need to integrate into your project, you need to apply the patch in your topic branch to evaluate it. -There are two ways to apply an e-mailed patch: with `git apply` or with `git am`. +Если вы получили патч по почте и его нужно интегрировать в проект, то следует проанализировать его, применив сначала в тематической ветке. +Существует два варианта применения полученного по почте патча: `git apply` или `git am`. -===== Applying a Patch with apply +===== Применение патча командой apply (((git commands, apply))) -If you received the patch from someone who generated it with the `git diff` or a Unix `diff` command (which is not recommended; see the next section), you can apply it with the `git apply` command. -Assuming you saved the patch at `/tmp/patch-ruby-client.patch`, you can apply the patch like this: +Если полученный по почте патч был создан командой `git diff` или Unix командой `diff` (что не рекомендуется делать), то применить его можно командой `git apply`. +Предположим, патч сохранен здесь `/tmp/patch-ruby-client.patch`, тогда применить его можно вот так: [source,console] ----- $ git apply /tmp/patch-ruby-client.patch ----- -This modifies the files in your working directory. -It's almost identical to running a `patch -p1` command to apply the patch, although it's more paranoid and accepts fewer fuzzy matches than patch. -It also handles file adds, deletes, and renames if they're described in the `git diff` format, which `patch` won't do. -Finally, `git apply` is an ``apply all or abort all'' model where either everything is applied or nothing is, whereas `patch` can partially apply patchfiles, leaving your working directory in a weird state. -`git apply` is overall much more conservative than `patch`. -It won't create a commit for you – after running it, you must stage and commit the changes introduced manually. +Это действие модифицирует файлы в вашей рабочей директории. +Выполнение команды практически эквивалентно выполнению команды `patch -p1`, однако, является более параноидальным и принимает меньше нечетких совпадений, чем `patch`. +При этом обрабатываются добавления, удаления и переименования файлов, указанные в формате `git diff`, тогда как `patch` этого не делает. +Наконец, `git apply` использует модель ``применить всё или отменить всё'', где изменения либо применяются полностью, либо не применяются вообще, тогда как `patch` может частично применить патч файлы, приведя вашу рабочую директорию в непонятное состояние. +В целом, `git apply` более консервативен, чем `patch`. +После выполнения команды новый коммит не создаётся и его нужно делать вручную. -You can also use git apply to see if a patch applies cleanly before you try actually applying it – you can run `git apply --check` with the patch: +Командой `git apply` можно проверить корректность применения патча до его фактического применения, используя `git apply --check`: [source,console] ----- @@ -62,20 +62,20 @@ error: patch failed: ticgit.gemspec:1 error: ticgit.gemspec: patch does not apply ----- -If there is no output, then the patch should apply cleanly. -This command also exits with a non-zero status if the check fails, so you can use it in scripts if you want. +Если ошибок не выведено, то патч может быть применен без проблем. +Так же, в случае ошибки эта команда возвращает отличное от 0 значение, что позволяет использовать её в скриптах. [[r_git_am]] -===== Applying a Patch with `am` +===== Применение патча командой `am` (((git commands, am))) -If the contributor is a Git user and was good enough to use the `format-patch` command to generate their patch, then your job is easier because the patch contains author information and a commit message for you. -If you can, encourage your contributors to use `format-patch` instead of `diff` to generate patches for you. -You should only have to use `git apply` for legacy patches and things like that. +Если участник проекта пользователь Git и умеет пользоваться командой `format-patch` для генерации патчей, то вам будет легче, так как в патч включается информация об авторе и сообщение коммита. +Если возможно, требуйте от ваших участников использовать команду `format-patch` вместо `diff` для генерации патчей. +Вам останется использовать `git apply` только для устаревших патчей и подобного им. -To apply a patch generated by `format-patch`, you use `git am`. -Technically, `git am` is built to read an mbox file, which is a simple, plain-text format for storing one or more e-mail messages in one text file. -It looks something like this: +Для применения патча, созданного с помощью `format-patch`, используйте `git am`. +Технически, `git am` реализована для чтения файлов в формате mbox, который предназначен для хранения в одном файле одного или нескольких e-mail собщений в текстовом виде. +Такой файл имеет вид: [source,console] ----- @@ -87,12 +87,12 @@ Subject: [PATCH 1/2] add limit to log function Limit log functionality to the first 20 ----- -This is the beginning of the output of the format-patch command that you saw in the previous section. -This is also a valid mbox e-mail format. -If someone has e-mailed you the patch properly using git send-email, and you download that into an mbox format, then you can point git am to that mbox file, and it will start applying all the patches it sees. -If you run a mail client that can save several e-mails out in mbox format, you can save entire patch series into a file and then use git am to apply them one at a time. +Это начало вывода команды `format-patch`, которая рассматривалась в предыдущем разделе. +Это так же валидный mbox формат. +Если кто-то отправил патч, корректно сформированный командой `git send-email`, и вы сохранили его в mbox формате, то можно указать передать этот файл в качестве аргумента команде `git am`, которая начнёт применять все найденные в файле патчи. +Если вы используете почтовый клиент, который умеет сохранять несколько писем в mbox формате, то можно сохранить сразу серию патчей в один файл, а затем применить их за раз, используя `git am`. -However, if someone uploaded a patch file generated via `format-patch` to a ticketing system or something similar, you can save the file locally and then pass that file saved on your disk to `git am` to apply it: +Так или иначе, если кто-нибудь загрузит созданный с помощью `format-patch` патч файл в систему управления задачами, то вы сможете сохранить его себе и применить локально с помощью `git am`: [source,console] ----- @@ -100,9 +100,9 @@ $ git am 0001-limit-log-function.patch Applying: add limit to log function ----- -You can see that it applied cleanly and automatically created the new commit for you. -The author information is taken from the e-mail's `From` and `Date` headers, and the message of the commit is taken from the `Subject` and body (before the patch) of the e-mail. -For example, if this patch was applied from the mbox example above, the commit generated would look something like this: +Как вы могли заметить, патч применился без конфликтов и был создан новый комит. +Информация об авторе была извлечена из заголовков письма `From` и `Date`, сообщение для коммита -- из заголовка `Subject`, а данные коммита -- из тела письма. +Например, для примененного патча из примера выше коммит будет выглядеть следующим образом: ----- $ git log --pretty=fuller -1 @@ -117,12 +117,12 @@ CommitDate: Thu Apr 9 09:19:06 2009 -0700 Limit log functionality to the first 20 ----- -The `Commit` information indicates the person who applied the patch and the time it was applied. -The `Author` information is the individual who originally created the patch and when it was originally created. +`Commit` информация указывает на того, кто применил патч и когда это было сделано. +`Author` информация указывает на того, кто изначально создал патч и когда это было сделано -But it's possible that the patch won't apply cleanly. -Perhaps your main branch has diverged too far from the branch the patch was built from, or the patch depends on another patch you haven't applied yet. -In that case, the `git am` process will fail and ask you what you want to do: +Однако, возможна ситуация, когда патч не может быть безаконфликтно применен. +Возможно, ваша основная ветка сильно расходится с той веткой, на основании которой был создан патч, или он зависит от другого, ещё не примененного патча. +В таком случае работа `git am` будет прервана, а так же выведена подсказка со списком возможных действий: [source,console] ----- @@ -136,8 +136,8 @@ If you would prefer to skip this patch, instead run "git am --skip". To restore the original branch and stop patching run "git am --abort". ----- -This command puts conflict markers in any files it has issues with, much like a conflicted merge or rebase operation. -You solve this issue much the same way – edit the file to resolve the conflict, stage the new file, and then run `git am --resolved` to continue to the next patch: +Эта команда добавит соответствующие маркеры во все файлы где есть конфликты, аналогично конфликтам слияния или перебазирования. +Для решения такой проблемы используется аналогичный подход -- отредактируйте файлы исправив конфликты, добавьте их в индекс и выполните команду `git am --resolved` для перехода к следующему патчу: [source,console] ----- @@ -147,9 +147,9 @@ $ git am --resolved Applying: seeing if this helps the gem ----- -If you want Git to try a bit more intelligently to resolve the conflict, you can pass a `-3` option to it, which makes Git attempt a three-way merge. -This option isn't on by default because it doesn't work if the commit the patch says it was based on isn't in your repository. -If you do have that commit – if the patch was based on a public commit – then the `-3` option is generally much smarter about applying a conflicting patch: +При желании, вы можете указать опцию `-3`, чтобы Git попробовал провести трёхстороннее слияние. +Эта опция не включена по умолчанию, так как она не будет работать, если коммит, на который ссылается патч, отсутствует в вашем репозитории. +Если у вас есть тот коммит, на который ссылается конфликтующий патч, то использование опции `-3` приводит к более умному применению конфликтующего патча: [source,console] ----- @@ -162,10 +162,10 @@ Falling back to patching base and 3-way merge... No changes -- Patch already applied. ----- -In this case, this patch had already been applied. -Without the `-3` option, it looks like a conflict. +В данном случае патч уже был применен. +Без использования опции `-3` это выглядит как конфликт. -If you're applying a number of patches from an mbox, you can also run the `am` command in interactive mode, which stops at each patch it finds and asks if you want to apply it: +Если вы применяете несколько патчей из файла mbox, то можно запустить `git am` в интерактивном режиме, в котором перед обработкой каждого патча будет задаваться вопрос о дальнейших действиях: [source,console] ----- @@ -177,17 +177,18 @@ seeing if this helps the gem Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all ----- -This is nice if you have a number of patches saved, because you can view the patch first if you don't remember what it is, or not apply the patch if you've already done so. +Это отличная возможность посмотреть содержимое патча перед его применением или пропустить его, если он уже был применен. -When all the patches for your topic are applied and committed into your branch, you can choose whether and how to integrate them into a longer-running branch. +Когда все патчи применены и созданы коммиты в текущей ветке, вы уже можете решить стоит ли и как интегрировать их в более долгоживущую ветку. [[r_checking_out_remotes]] -==== Checking Out Remote Branches +==== Проверка удаленных веток (((branches, remote))) -If your contribution came from a Git user who set up their own repository, pushed a number of changes into it, and then sent you the URL to the repository and the name of the remote branch the changes are in, you can add them as a remote and do merges locally. +Если участник проекта создал свой Git репозиторий, отправил в него свои изменения, а затем прислал вам ссылку и название ветки, куда были отправлены изменения, то вы можете добавить этот репозиторий как удаленный и провести слияние локально. -For instance, if Jessica sends you an e-mail saying that she has a great new feature in the `ruby-client` branch of her repository, you can test it by adding the remote and checking out that branch locally: +К примеру, Джессика отправила вам письмо, в котором сказано, у неё есть новый функционал в ветке `ruby-client` её репозитория. +Вы можете его протестировать, добавив удаленный репозиторий и получив изменения из этой ветки локально: [source,console] ----- @@ -196,18 +197,18 @@ $ git fetch jessica $ git checkout -b rubyclient jessica/ruby-client ----- -If she e-mails you again later with another branch containing another great feature, you can fetch and check out because you already have the remote setup. +Если она снова пришлёт вам письмо с указанием на новый функционал уже в другой ветке, то для его получения достаточно `fetch` и `checkout`, так как удаленный репозиторий уже подключен. -This is most useful if you're working with a person consistently. -If someone only has a single patch to contribute once in a while, then accepting it over e-mail may be less time consuming than requiring everyone to run their own server and having to continually add and remove remotes to get a few patches. -You're also unlikely to want to have hundreds of remotes, each for someone who contributes only a patch or two. -However, scripts and hosted services may make this easier – it depends largely on how you develop and how your contributors develop. +Это очень полезно, когда вы постоянно работаете с этим человеком. +Однако, от тех, кто редко отправляет небольшие патчи, будет проще принимать их по почте, чем требовать от всех поддержания собственных серверов с репозиториями, постоянно добавлять их как удаленные, а затем удалять и всё это ради нескольких патчей. +Так же вы вряд ли захотите иметь сотни удаленных репозиториев, каждый из которых нужен только для одного или нескольких патчей. +К счастью, скрипты и различные сервисы облегчают задачу, но во многом зависят от того как работаете вы и участники вашего проекта. -The other advantage of this approach is that you get the history of the commits as well. -Although you may have legitimate merge issues, you know where in your history their work is based; a proper three-way merge is the default rather than having to supply a `-3` and hope the patch was generated off a public commit to which you have access. +Отличительным преимуществом данного подхода является получение истории коммитов. +Хоть возникновение конфликтов слияния и закономерно, но вы знаете с какого момента это произошло; корректное трёстороннее слияние более предпочтительно, чем указать опцию `-3` и надеяться, что патч основан на коммите, к которому у вас есть доступ. -If you aren't working with a person consistently but still want to pull from them in this way, you can provide the URL of the remote repository to the `git pull` command. -This does a one-time pull and doesn't save the URL as a remote reference: +Если вы с кем-то не работаете постоянно, но всё равно хотите использовать удаленный репозиторий, то можно указать ссылку на него в команде `git pull`. +Это приведёт к однократному выполнению, а ссылка не репозиторий сохранена не будет. [source,console] ----- @@ -218,17 +219,17 @@ Merge made by recursive. ----- [[r_what_is_introduced]] -==== Determining What Is Introduced +==== Определение применяемых изменений (((branches, diffing))) -Now you have a topic branch that contains contributed work. -At this point, you can determine what you'd like to do with it. -This section revisits a couple of commands so you can see how you can use them to review exactly what you'll be introducing if you merge this into your main branch. +На текущий момент у вас есть тематическая ветка, содержащая предоставленные изменения. +Сейчас вы можете определиться что с ними делать. +В этом разделе рассматривается набор команд, которые помогут вам увидеть что именно будет интегрировано, если вы решите слить изменения в основную ветку. -It's often helpful to get a review of all the commits that are in this branch but that aren't in your master branch. -You can exclude commits in the master branch by adding the `--not` option before the branch name. -This does the same thing as the `master..contrib` format that we used earlier. -For example, if your contributor sends you two patches and you create a branch called `contrib` and applied those patches there, you can run this: +Обычно, полезно просмотреть все коммиты текущей ветки, которые ещё не включены в основную. +Вы можете исключить коммиты, которые уже есть в вашей основной ветке добавив опцию `--not` перед её названием. +Это аналогично указанию использовавшегося ранее формата `master..contrib`. +Например, если участник проекта отправил вам два патча, а вы создали ветку с названием `contrib` и применили их, то можно выполнить следующую команду: [source,console] ----- @@ -246,27 +247,26 @@ Date: Mon Oct 22 19:38:36 2008 -0700 updated the gemspec to hopefully work better ----- -To see what changes each commit introduces, remember that you can pass the `-p` option to `git log` and it will append the diff introduced to each commit. +Для просмотра изменений, представленных в каждом коммите, можно использовать опцию `-p` команды `git log`, которая выведет разницу по каждому коммиту. -To see a full diff of what would happen if you were to merge this topic branch with another branch, you may have to use a weird trick to get the correct results. -You may think to run this: +Для просмотра полной разницы того, что произойдёт если вы сольёте изменения в другую ветку, вам понадобится использовать возможно странный способ для получения корректных результатов: [source,console] ----- $ git diff master ----- -This command gives you a diff, but it may be misleading. -If your `master` branch has moved forward since you created the topic branch from it, then you'll get seemingly strange results. -This happens because Git directly compares the snapshots of the last commit of the topic branch you're on and the snapshot of the last commit on the `master` branch. -For example, if you've added a line in a file on the `master` branch, a direct comparison of the snapshots will look like the topic branch is going to remove that line. +Эта команда может вводить в заблуждение, но точно покажет разницу. +Если ваша `master` ветка продвинулась вперед с тех пор как вы создали тематическую ветку, то вы получите на первый взгляд странные результаты. +Это происходит потому, что Git непосредственно сравнивает снимки последних коммитов текущей и `master` веток. +Например, если вы добавили строку в файл в ветке `master`, то прямое сравнение снимков будет выглядеть как будто тематическая ветка собирается удалить эту строку. -If `master` is a direct ancestor of your topic branch, this isn't a problem; but if the two histories have diverged, the diff will look like you're adding all the new stuff in your topic branch and removing everything unique to the `master` branch. +Это не проблема, если ветка `master` является непосредственным родителем вашей тематической ветки, но если история обоих веток изменилась, то разница будет выглядеть как добавление всех изменений из тематической ветки и удаление всего нового из `master` ветки. -What you really want to see are the changes added to the topic branch – the work you'll introduce if you merge this branch with master. -You do that by having Git compare the last commit on your topic branch with the first common ancestor it has with the master branch. +Что действительно нужно видеть, так это изменения тематической ветки, которые предстоит слить в `master` ветку. +Это можно сделать, сказав Git сравнивать последний коммит тематической ветки с первым общим родителем для обоих веток. -Technically, you can do that by explicitly figuring out the common ancestor and then running your diff on it: +Технически это делается за счёт явного указания общего коммита и применения разницы к нему: [source,console] ----- @@ -275,105 +275,106 @@ $ git merge-base contrib master $ git diff 36c7db ----- -However, that isn't convenient, so Git provides another shorthand for doing the same thing: the triple-dot syntax. -In the context of the `diff` command, you can put three periods after another branch to do a `diff` between the last commit of the branch you're on and its common ancestor with another branch: +Однако это не удобно, поэтому Git предоставляет более короткий способ: синтаксис троеточия. +При выполнении команды `diff`, следует поставить три точки после имени ветки для получения разницы между ней и текущей веткой, относительно общего родителя с другой веткой: [source,console] ----- $ git diff master...contrib ----- -This command shows you only the work your current topic branch has introduced since its common ancestor with master. -That is a very useful syntax to remember. +Данная команда отобразит проделанную работу только из тематической ветки, относительно общего родителя с веткой `master`. +Полезно запомнить указанный синтаксис. -==== Integrating Contributed Work +==== Интеграция предоставленной работы (((integrating work))) -When all the work in your topic branch is ready to be integrated into a more mainline branch, the question is how to do it. -Furthermore, what overall workflow do you want to use to maintain your project? -You have a number of choices, so we'll cover a few of them. +Когда все изменения в текущей тематической ветке готовы к интеграции с основной веткой, возникает вопрос как это сделать. +Кроме этого, какой рабочий процесс вы хотите использовать при сопровождении вашего проекта? +У вас несколько вариантов, давайте рассмотрим некоторые из них. -===== Merging Workflows +===== Рабочие процессы по слиянию (((workflows, merging))) -One simple workflow merges your work into your `master` branch. -In this scenario, you have a `master` branch that contains basically stable code. -When you have work in a topic branch that you've done or that someone has contributed and you've verified, you merge it into your master branch, delete the topic branch, and then continue the process. -If we have a repository with work in two branches named `ruby_client` and `php_client` that looks like <> and merge `ruby_client` first and then `php_client` next, then your history will end up looking like <>. +В простом рабочем процессе проделанная работа просто сливается в ветку `master`. +При таком сценарии у вас есть ветка `master`, которая содержит стабильный код. +Когда работа в тематической ветке завершена или вы проверили чью-то работу, вы сливаете её в ветку `master` и удаляете, затем процесс повторяется. +Если в репозитории присутствуют две ветки `ruby_client` и `php_client` с проделанной работой, как показано на рисунке <>, и вы сначала сливаете ветку `ruby_client`, а затем `php_client`, то состояние вашего репозитория будет выглядеть как показано на рисунке <>. [[rmerwf_a]] -.History with several topic branches. -image::images/merging-workflows-1.png[History with several topic branches.] +.История с несколькими тематическими ветками. +image::images/merging-workflows-1.png[История с несколькими тематическими ветками.] [[rmerwf_b]] -.After a topic branch merge. -image::images/merging-workflows-2.png[After a topic branch merge.] +.Слияние тематической ветки. +image::images/merging-workflows-2.png[Слияние тематической ветки.] -That is probably the simplest workflow, but it can possibly be problematic if you're dealing with larger or more stable projects where you want to be really careful about what you introduce. +Это, пожалуй, простейший рабочий процесс и его использование проблематично в больших или более стабильных проектах, где вы должны быть более осторожны с предоставленными изменениями. -If you have a more important project, you might want to use a two-phase merge cycle. -In this scenario, you have two long-running branches, `master` and `develop`, in which you determine that `master` is updated only when a very stable release is cut and all new code is integrated into the `develop` branch. -You regularly push both of these branches to the public repository. -Each time you have a new topic branch to merge in (<>), you merge it into `develop` (<>); then, when you tag a release, you fast-forward `master` to wherever the now-stable `develop` branch is (<>). +Если у вас очень важный проект, то возможно вам стоит использовать двухступенчатый цикл слияния. +При таком сценарии у вас имеются две долгоживущие ветки `master` и `develop`, где в `master` сливаются только очень стабильные изменения, а все новые доработки интегрируются в ветку `develop`. +Обе ветки регулярно отправляются в публичный репозиторий. +Каждый раз, когда новая тематческая ветка готова к слиянию (<>), вы сливаете её в `develop` (<>); затем, когда вы выпускаете релиз, ветка `master` смещается на стабильное состояние ветки `develop` (<>). [[rmerwf_c]] -.Before a topic branch merge. -image::images/merging-workflows-3.png[Before a topic branch merge.] +.Перед слиянием тематической ветки. +image::images/merging-workflows-3.png[Перед слиянием тематической ветки.] [[rmerwf_d]] -.After a topic branch merge. -image::images/merging-workflows-4.png[After a topic branch merge.] +.После слияния тематической ветки. +image::images/merging-workflows-4.png[После слияния тематической ветки.] [[rmerwf_e]] -.After a project release. -image::images/merging-workflows-5.png[After a topic branch release.] +.После релиза проекта. +image::images/merging-workflows-5.png[После релиза тематической ветки.] -This way, when people clone your project's repository, they can either check out master to build the latest stable version and keep up to date on that easily, or they can check out develop, which is the more cutting-edge stuff. -You can also continue this concept, having an integrate branch where all the work is merged together. -Then, when the codebase on that branch is stable and passes tests, you merge it into a develop branch; and when that has proven itself stable for a while, you fast-forward your master branch. +Таким образом, люди могут клонировать репозиторий вашего проекта и использовать ветку `master` для сборки последнего стабильного состояния и получения актуальных изменений или использовать ветку `develop`, которая содержит самые последние изменения. +Вы также можете продолжить эту концепцию, имея ветку интеграции, в которой объединяется вся работа. +После того, как кодовая база указанной ветки стабильна и пройдены все тесты, она сливается в ветку `develop`, а после того, как стабильность слитых изменений доказана, вы перемещаете состояние ветки `master` на стабильное. -===== Large-Merging Workflows +===== Рабочий просесс множественных слияний (((workflows, "merging (large)"))) -The Git project has four long-running branches: `master`, `next`, and `pu` (proposed updates) for new work, and `maint` for maintenance backports. -When new work is introduced by contributors, it's collected into topic branches in the maintainer's repository in a manner similar to what we've described (see <>). -At this point, the topics are evaluated to determine whether they're safe and ready for consumption or whether they need more work. -If they're safe, they're merged into `next`, and that branch is pushed up so everyone can try the topics integrated together. +В проекте Git присутствуют четыре долгоживущие ветки: `master`, `next`, `pu` (предложенные обновления) для новой работы и `maint` для поддержания бэкпортов. +Новая проделанная работа предоставляется участниками в тематические ветки основного репозитория по принципу, описанному ранее (смотри <>). +В этот момент производится проверка этих веток на безопасность и готовность или необходимость доработки. +Если это безопасно, изменения сливаются с веткой `next`, для того, чтобы остальные участники проекта могли проверить интегрированные изменения. [[rmerwf_f]] -.Managing a complex series of parallel contributed topic branches. -image::images/large-merges-1.png[Managing a complex series of parallel contributed topic branches.] +.Управление сложным набором паралельно разрабатываемых тематических веток. +image::images/large-merges-1.png[Управление сложным набором паралельно разрабатываемых тематических веток.] -If the topics still need work, they're merged into `pu` instead. -When it's determined that they're totally stable, the topics are re-merged into `master` and are then rebuilt from the topics that were in `next` but didn't yet graduate to `master`. -This means `master` almost always moves forward, `next` is rebased occasionally, and `pu` is rebased even more often: +Если тематические ветки требуют доработки, то они сливаются в ветку `pu`. +Когда тематические ветки признаются полностью стабильными, то снова сливаются в `master` и перестраиваются на основании изменений, находящихся в `next`, но ещё не попавших в `master`. +Это означает, что `master` практически всегда двигается только вперед, `next` время от времени перебазируется, а `pu` перебазируется часто: -.Merging contributed topic branches into long-term integration branches. -image::images/large-merges-2.png[Merging contributed topic branches into long-term integration branches.] +.Слияние тематических веток в долгоживущие ветки интеграции. +image::images/large-merges-2.png[Слияние тематических веток в долгоживущие ветки интеграции.] -When a topic branch has finally been merged into `master`, it's removed from the repository. -The Git project also has a `maint` branch that is forked off from the last release to provide backported patches in case a maintenance release is required. -Thus, when you clone the Git repository, you have four branches that you can check out to evaluate the project in different stages of development, depending on how cutting edge you want to be or how you want to contribute; and the maintainer has a structured workflow to help them vet new contributions. +После того, как тематическая ветка окончательно слита в `master`, она удаляется из репозитория. +Репозиторий так же содержит ветку `maint`, которая ответвляется от последнего релиза для предоставления патчей, если требуется поддержка обратной совместимости. +Таким образом, после клонирования проекта у вас будет четыре ветки, дающие возможность перейти на разные стадии его разработки, в зависимости от того, на сколько передовым вы хотите быть или как вы собираетесь участвовать в проекте. +Вместе с этим, рабочий процесс структурирован, что помогает сопровождающему проекта проверять поступающий код. [[r_rebase_cherry_pick]] ===== Rebasing and Cherry Picking Workflows (((workflows, rebasing and cherry-picking))) -Other maintainers prefer to rebase or cherry-pick contributed work on top of their master branch, rather than merging it in, to keep a mostly linear history. -When you have work in a topic branch and have determined that you want to integrate it, you move to that branch and run the rebase command to rebuild the changes on top of your current master (or `develop`, and so on) branch. -If that works well, you can fast-forward your `master` branch, and you'll end up with a linear project history. +Некоторые сопровождающие предпочитают перебазировать или выборочно применять (cherry-pick) изменения относительно ветки `master` вместо слияния, что позволяет поддерживать историю проекта в линейном виде. +Когда проделанная работа из тематической ветки готова к интеграции, вы переходите на эту ветку и перебазируете её относительно ветки `master` (или `develop` и т.д.). +Если конфликты отсутствуют, то вы можете просто сдвинуть состояние ветки `master`, что обеспечивает линейность истории проекта. (((git commands, cherry-pick))) -The other way to move introduced work from one branch to another is to cherry-pick it. -A cherry-pick in Git is like a rebase for a single commit. -It takes the patch that was introduced in a commit and tries to reapply it on the branch you're currently on. -This is useful if you have a number of commits on a topic branch and you want to integrate only one of them, or if you only have one commit on a topic branch and you'd prefer to cherry-pick it rather than run rebase. -For example, suppose you have a project that looks like this: +Другим способом перемещения предлагаемых изменений в из одной ветки в другую является их выборочное применение (cherry-pick). +Выборочное применение в Git похоже на перебазирование для одного коммита. +В таком случае формируется патч для выбранного коммита и применяется к текущей ветке. +Это полезно, когда в тематической ветке присутствует несколько коммитов, а выхотите применить только один из них, или в тематической ветке только один коммит и выхотите его применить вместо использования перебазирования. +Например, предположим, что ваш проект выглядит следующим образом: -.Example history before a cherry-pick. -image::images/rebasing-1.png[Example history before a cherry-pick.] +.Пример истории до выборочного слияния. +image::images/rebasing-1.png[Пример истории до выборочного слияния.] -If you want to pull commit `e43a6` into your master branch, you can run +Для применения коммита `e43a6` к ветке `master` выполните команду: [source,console] ----- @@ -383,43 +384,44 @@ Finished one cherry-pick. 3 files changed, 17 insertions(+), 3 deletions(-) ----- -This pulls the same change introduced in `e43a6`, but you get a new commit SHA-1 value, because the date applied is different. -Now your history looks like this: +Это действие применит изменения, содержащиеся в коммите `e43a6`, но будет сформирован новый коммит с другим значением SHA-1. +После этого история будет выглядеть так: -.History after cherry-picking a commit on a topic branch. -image::images/rebasing-2.png[History after cherry-picking a commit on a topic branch.] +.История после выборочного применения коммита из тематической ветки. +image::images/rebasing-2.png[История после выборочного применения коммита из тематической ветки.] -Now you can remove your topic branch and drop the commits you didn't want to pull in. +После этого можно удалять тематическую ветку и коммиты, которые применять не нужно. -===== Rerere +===== Возможность ``Rerere'' (((git commands, rerere)))(((rerere))) -If you're doing lots of merging and rebasing, or you're maintaining a long-lived topic branch, Git has a feature called ``rerere'' that can help. +Если вы часто производите перебазирование и слияние или поддерживаете догоживущие тематические ветки, то в Git есть специальная возможность под названием ``rerere'', призванная вам помочь. -Rerere stands for ``reuse recorded resolution'' – it's a way of shortcutting manual conflict resolution. -When rerere is enabled, Git will keep a set of pre- and post-images from successful merges, and if it notices that there's a conflict that looks exactly like one you've already fixed, it'll just use the fix from last time, without bothering you with it. +Её название расшифровывается как ``переиспользование записанного разрешения'', а применяется для ускорения ручного разрешения конфликтов. +Когда эта опция включена, Git будет сохранять набор образов до и после успешного слияния, а так же разрешать конфликты самостоятельно, если аналогичные конфликты уже были разрешены ранее. -This feature comes in two parts: a configuration setting and a command. -The configuration setting is `rerere.enabled`, and it's handy enough to put in your global config: +Эта возможность реализована как команда и как параметр конфигурации. +Параметр конфигурации называется `rerere.enabled`, который можно включить глобально следующим образом: [source,console] ---- $ git config --global rerere.enabled true ---- -Now, whenever you do a merge that resolves conflicts, the resolution will be recorded in the cache in case you need it in the future. +После этого любое разрешение конфликта слияния будет записано на случай повторного использования. -If you need to, you can interact with the rerere cache using the `git rerere` command. -When it's invoked alone, Git checks its database of resolutions and tries to find a match with any current merge conflicts and resolve them (although this is done automatically if `rerere.enabled` is set to `true`). -There are also subcommands to see what will be recorded, to erase specific resolution from the cache, and to clear the entire cache. We will cover rerere in more detail in <>. +Если нужно, вы можете обращаться к кэшу ``rerere'' напрямую, используя команду `git rerere`. +Когда команда вызвана без параметров, Git проверяет базу данных и пытается найти решение для разрешения текущего конфликта слияния (точно так же как и при установленной настройке `rerere.enabled` в значение `true`). +Существует множество дополнительных команд для просмотра, что именно будет записано, удаления отдельных записей из кэша, а так же его полной очистки. +Более детально ``rerere'' будет рассмотрено в <>. [[r_tagging_releases]] -==== Tagging Your Releases +==== Помечайте свои релизы (((tags)))(((tags, signing))) -When you've decided to cut a release, you'll probably want to drop a tag so you can re-create that release at any point going forward. -You can create a new tag as discussed in <>. -If you decide to sign the tag as the maintainer, the tagging may look something like this: +После выпуска релиза, возможно, вы захотите пометить текущее состояние так, чтобы можно было вернуться к нему в любой момент. +Для этого можно добавить тэг, как было описано в <>. +Кроме этого, вы можете добавить цифровую подпись для тэга, выглядеть это будет вот так: [source,console] ----- @@ -429,9 +431,9 @@ user: "Scott Chacon " 1024-bit DSA key, ID F721C45A, created 2009-02-09 ----- -If you do sign your tags, you may have the problem of distributing the public PGP key used to sign your tags. -The maintainer of the Git project has solved this issue by including their public key as a blob in the repository and then adding a tag that points directly to that content. -To do this, you can figure out which key you want by running `gpg --list-keys`: +Если вы используете цифровую подпись при расстановке тэгов, то возникает проблема распространения публичной части PGP ключа, использованного при создании подписи. +Сопровождающий Git проекта может решить эту проблему добавив в репозиторий свой публичный ключ как бинарный объект и установив ссылающийся на него тэг. +Чтобы это сделать, выберите нужный ключ и списка доступных, который можно получить с помощью команды `gpg --list-keys`: [source,console] ----- @@ -443,7 +445,7 @@ uid Scott Chacon sub 2048g/45D02282 2009-02-09 [expires: 2010-02-09] ----- -Then, you can directly import the key into the Git database by exporting it and piping that through `git hash-object`, which writes a new blob with those contents into Git and gives you back the SHA-1 of the blob: +Затем экспортируйте выбранный ключ и поместите его непосредственно в базу данных Git при помощи команды `git hash-object`, которая сосздаст новый объект с содержимым ключа и вернёт SHA-1 этого объекта: [source,console] ----- @@ -451,30 +453,30 @@ $ gpg -a --export F721C45A | git hash-object -w --stdin 659ef797d181633c87ec71ac3f9ba29fe5775b92 ----- -Now that you have the contents of your key in Git, you can create a tag that points directly to it by specifying the new SHA-1 value that the `hash-object` command gave you: +Теперь, когда ваш публчниый ключ находится в репозитории, можно проставить указывающий на него тэг, используя полученное ранее значение SHA-1: [source,console] ----- $ git tag -a maintainer-pgp-pub 659ef797d181633c87ec71ac3f9ba29fe5775b92 ----- -If you run `git push --tags`, the `maintainer-pgp-pub` tag will be shared with everyone. -If anyone wants to verify a tag, they can directly import your PGP key by pulling the blob directly out of the database and importing it into GPG: +Выполнив команду `git push --tags`, `maintainer-pgp-pub` тэг станет общедоступным. +Теперь все, кто захочет проверить вашу подпись, могут ипортировать ваш публиный ключ, предварительно получив его из репозитория: [source,console] ----- $ git show maintainer-pgp-pub | gpg --import ----- -They can use that key to verify all your signed tags. -Also, if you include instructions in the tag message, running `git show ` will let you give the end user more specific instructions about tag verification. +После этого можно проверять цифровую подпись ваших тэгов. +Кроме этого, вы можете включить дополнительные инструкции по проверке вашей подписи в сообщение тэга, которое будет отображаться каждый раз при вызове команды `git show `. [[r_build_number]] -==== Generating a Build Number +==== Генерация номера сборки (((build numbers)))(((git commands, describe))) -Because Git doesn't have monotonically increasing numbers like 'v123' or the equivalent to go with each commit, if you want to have a human-readable name to go with a commit, you can run `git describe` on that commit. -Git gives you the name of the nearest tag with the number of commits on top of that tag and a partial SHA-1 value of the commit you're describing: +Git не использует монотонно возрастающие идентификаторы для коммитов, поэтому если вы хотите получить читаемые имена комитов, то воспользуйтесь командой `git describe` для нужного коммита. +Git вернёт имя ближайшего тэга, количество коммитов после него и частичное значение хэша SHA-1 для указанного коммита: [source,console] ----- @@ -482,21 +484,21 @@ $ git describe master v1.6.2-rc1-20-g8c5b85c ----- -This way, you can export a snapshot or build and name it something understandable to people. -In fact, if you build Git from source code cloned from the Git repository, `git --version` gives you something that looks like this. -If you're describing a commit that you have directly tagged, it gives you the tag name. +Таким образом, вы можете сделать снимок или собрать билд и дать ему понятное для человека название. +К слову, если вы склонируете репозиторий Git и соберете его из исходного кода, то вывод команды `git --version` будет примерно таким же. +Если попытаться получить имя коммита, которому назначен тэг, то результатом будет название самого тэга. -The `git describe` command favors annotated tags (tags created with the `-a` or `-s` flag), so release tags should be created this way if you're using `git describe`, to ensure the commit is named properly when described. -You can also use this string as the target of a checkout or show command, although it relies on the abbreviated SHA-1 value at the end, so it may not be valid forever. -For instance, the Linux kernel recently jumped from 8 to 10 characters to ensure SHA-1 object uniqueness, so older `git describe` output names were invalidated. +Команда `git describe` поддерживает аннотированные тэги (созданные с использованием опций `-a` или `-s`), поэтому следует использовать именно такие тэги для пометки релизов, особенно если вы используете `git describe` для проверки корректности именования коммитов. +Так же это название можно использовать при выполнении команд ``checkout'' и ``show'', однако в конце имени содержится частичный SHA-1 хэш, поэтому название не будет валидным постоянно. +К примеру, ядро Linux недавно перешло к использованию 10 символов в SHA-1 хэшах вместо 8, чтобы обеспечить уникальность каждого объекта, таким образом предыдущие результаты `git describe` стали невалидными. [[r_preparing_release]] -==== Preparing a Release +==== Подготовка релиза (((releasing)))(((git commands, archive))) -Now you want to release a build. -One of the things you'll want to do is create an archive of the latest snapshot of your code for those poor souls who don't use Git. -The command to do this is `git archive`: +Время делать релиз сборки. +Возможно, вы захотите сделать архив последнего состояния вашего кода для тех, кто не использует Git. +Для создания архива выполните команду `git archive`: [source,console] ----- @@ -505,23 +507,24 @@ $ ls *.tar.gz v1.6.2-rc1-20-g8c5b85c.tar.gz ----- -If someone opens that tarball, they get the latest snapshot of your project under a project directory. -You can also create a zip archive in much the same way, but by passing the `--format=zip` option to `git archive`: +Распаковав архив, вы получите последнее состояние кода вашего проекта в директории ``project''. +Точно таким же способом можно создать zip архив, просто добавив опцию `--format=zip` для команды `git archive`: [source,console] ----- $ git archive master --prefix='project/' --format=zip > `git describe master`.zip ----- -You now have a nice tarball and a zip archive of your project release that you can upload to your website or e-mail to people. +Теперь у вас есть два архива с релизным состоянием вашего кода, которые можно загрузить на сайт или отправить по почте. [[r_the_shortlog]] -==== The Shortlog +==== Краткая история (Shortlog) (((git commands, shortlog))) -It's time to e-mail your mailing list of people who want to know what's happening in your project. -A nice way of quickly getting a sort of changelog of what has been added to your project since your last release or e-mail is to use the `git shortlog` command. -It summarizes all the commits in the range you give it; for example, the following gives you a summary of all the commits since your last release, if your last release was named v1.0.1: +Сейчас самое время оповестить людей из списка рассылки, которые хотят знать что происходит с вашим проектом. +С помощью команды `git shortlog` можно быстро получить список изменений, внесенных в проект с момента последнего релиза или предыдущей рассылки. +Она собирает все коммиты в заданном интервале. +Например, следующая команда выведет список коммитов с момента последнего релиза с названием v1.0.1: [source,console] ----- @@ -541,4 +544,4 @@ Tom Preston-Werner (4): Regenerated gemspec for version 1.0.2 ----- -You get a clean summary of all the commits since v1.0.1, grouped by author, that you can e-mail to your list. +И так, у вас есть готовая к отправке сводка коммитов, сгруппированных по авторам.