From 0085f227b5d8eec9e9a468898178feedca4052e5 Mon Sep 17 00:00:00 2001 From: secondwtq Date: Sun, 21 Jun 2015 02:46:18 +0800 Subject: [PATCH 1/6] Translate 05-distributed-git maintaining --- .../sections/maintaining.asc | 387 +++++++++--------- status.json | 2 +- 2 files changed, 194 insertions(+), 195 deletions(-) diff --git a/book/05-distributed-git/sections/maintaining.asc b/book/05-distributed-git/sections/maintaining.asc index 2f521758..01fd6ebf 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`,这样如果你暂时停止其中的工作,以后回来时也不会忘记。 +项目的维护者一般还会为这些分支附带命名空间,比如 `sc/ruby_client`(其中 `sc` 是贡献该项工作的人名称的简写)。 +正如你所想到的,可以以如下的方式基于 master 分支建立主题分支: [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. +现在你已经准备好将别人贡献的工作加入到这个主题分支,并考虑是否将其合并到长期分支中去了。 [[_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` 命令采用了一种“全部应用,否则就全部撤销(apply all or abort all)”的模型,即补丁只有全部内容都被应用和完全不被应用两个状态,而 `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. +如果没有产生输出,说明该补丁可以整洁地应用。 +如果检查失败了,该命令还会以一个非零的状态退出,所以需要时你也可以在脚本中使用它。 [[_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 文件而构建的,mbox 是一种用来在单个文本文件中存储一个或多个电子邮件消息的简单纯文本格式。 +其大致格式如下所示: [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 格式的文件,你甚至能够将一系列补丁打包为单个 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` 生成的补丁文件上传到类似 Request Ticket 的任务处理系统,你可以先将其下载到本地,之后运行 `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` 和邮件正文中补丁之前的内容。 +比如,根据上面那个 mbox 示例所生成的提交是这样的: ----- $ 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: +如果你希望 Git 能够尝试以更加智能的方式解决冲突,你可以对其传递 `-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 文件用用多个补丁,也可以在交互模式下运行 `am` 命令,这样在每个补丁之前,它会停住询问你是否要应用: [source,console] ----- @@ -177,17 +177,17 @@ 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. +当与主题相关的所有补丁都被应用并提交到分支中之后,你就可以选择是否以及如何将其整合到更长期的分支中去了。 [[_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. +如果你的贡献者建立了自己的版本库,并且向其中推送了若干修改,之后将版本库的 URL 和包含更改的远程分支发送给你,那么你可以将其添加为一个远程分支,并且在本地进行合并。 -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: +比如 Jessica 向你发送了一封电子邮件,内容是在她的版本库中的 `ruby-client` 分支中有一个很不错的新功能,为了测试该功能,你可以将其添加为一个远程分支,并在本地检出: [source,console] ----- @@ -196,18 +196,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. +如果她再次发邮件说另一个分支中包含另一个优秀功能,因为之前已经设置好远程分支了,你就可以直接进行抓取及检出操作。 -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. +这种方式的另一种优点是你同时可以得到提交历史。 +虽然代码合并中可能会出现问题,但是你能获知他人的工作基于你的历史中的具体哪一个位置;所以Git 会默认进行三方合并,不需要提供 `-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: +对于非持续性的合作,如果你依然想要以这种方式拉取数据的话,你可以对远程分支的 URL 调用 `git pull` 命令。 +这会执行一个一次性的抓取,而不会将 URL 存为远程引用: [source,console] ----- @@ -218,17 +218,17 @@ Merge made by recursive. ----- [[_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: +一般来说,你应该对该分支中所有 master 分支尚未包含的提交进行检查。 +通过在分支名称前加入 `--not` 选项,你可以排除 master 分支中的提交。 +这和我们之前使用的 `master..contrib` 格式是一样的。 +假设贡献者向你发送了两个补丁,为此你创建了一个名叫 `contrib` 的分支并在其上应用补丁,你可以运行: [source,console] ----- @@ -246,27 +246,27 @@ 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. +如果要查看每次提交所引入的具体修改,你应该记得可以给 `git log` 命令传递 `-p` 选项,这样它会在每次提交后面附加对应的 diff。 -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: +而要查看将该主题分支与另一个分支合并的完整 diff,你可能需要使用一个有些奇怪的技巧来得到正确的结果。 +你可能会想到这种方式: [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. +这个命令会输出一个 diff,但它可能并不是我们想要的。 +如果在你创建主题分支之后,`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` 分支是主题分支的直接祖先,其实是没有任何问题的;但是一旦两个分支的历史产生了分叉,上述比对产生的 diff 看上去就像是将主题分支中所有的新东西加入,并且将 `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 对主题分支上最新的提交与该分支与 master 分支的首个公共祖先进行比较。 -Technically, you can do that by explicitly figuring out the common ancestor and then running your diff on it: +从技术的角度讲,你可以以以手工的方式找出公共祖先,并对其显式运行 diff 命令: [source,console] ----- @@ -275,105 +275,104 @@ $ 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` 分支,那么提交历史就会变成 <> 的样子。 [[merwf_a]] -.History with several topic branches. -image::images/merging-workflows-1.png[History with several topic branches.] +.包含若干主题分支的提交历史 +image::images/merging-workflows-1.png[包含若干主题分支的提交历史] [[merwf_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` 分支(<>)。 [[merwf_c]] -.Before a topic branch merge. -image::images/merging-workflows-3.png[Before a topic branch merge.] +.合并主题分支前 +image::images/merging-workflows-3.png[合并主题分支前] [[merwf_d]] -.After a topic branch merge. -image::images/merging-workflows-4.png[After a topic branch merge.] +.合并主题分支后 +image::images/merging-workflows-4.png[合并主题分支后] [[merwf_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`(proposed updates)和用于维护和 backport 的 `maint`分支。 +贡献者的新工作会以类似之前所介绍的方式收入主题分支中(见 <>)。 +之后对主题分支进行测试评估,检查其是否已经能够合并,或者仍需要更多工作。 +稳定安全的主题分支会被合并入 `next` 分支,之后推送该分支使得所有人都可以尝试集成到一起的主题。 [[merwf_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` 分支。 +这意味着 `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` 分支后,便会被从版本库中删除掉。 +Git 项目还有一个从上一次发布中 fork 出来的 `maint` 分支来提供 backport 过来的补丁以供发布维护更新。 +因此,当你克隆 Git 的版本库之后,就会有四个可签出的分支,分别代表了开发的不同阶段,签出哪个分支,取决于你需要多新的版本,或者你想要如何进行贡献;对于维护者来说,这套结构化的工作流能帮助它们审查新的贡献。 [[_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. +为了保持线性的提交历史,有些维护者比较喜欢在 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: +另一种将引入的工作转移到其他分支的方法是挑拣。 +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 +382,43 @@ 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 (((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. +Rerere 是“重用记录的解决方案”的意思——它是手动冲突解决的一种快捷方式。 +当启用 rerere 时,Git 将会维护一些成功合并之前和之后的镜像,当 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>>. +如果你需要和 rerere 的缓存交互,你可以使用 `git rerere` 命令。 +当单独调用它时,Git 会检查解决方案数据库,尝试寻找符合当前合并冲突的匹配并解决冲突(尽管当 `rerere.enabled` 被设置为 `true` 时会自动进行)。 +它也有若干子命令,可用来查看记录项,删除特定解决方案和清除缓存全部内容等。我们将在 <<_rerere>> 中详细探讨。 [[_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 <<_git_basics_chapter>>. -If you decide to sign the tag as the maintainer, the tagging may look something like this: +当你决定进行一次发布时,你可能想要留下一个标签,这样在之后的任何一个提交点都可以重新创建该发布。 +你在 <<_git_basics_chapter>> 已经了解了创建新标签的过程。 +作为一个维护者,如果你决定要为标签签名的话,打标签的过程应该是这样子的: [source,console] ----- @@ -429,9 +428,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 项目的维护者已经解决了这一问题:在版本库中以 blob 的形式包含他们的公钥,并添加一个直接指向该内容的标签。 +要完成这一任务,首先你可以通过运行 `gpg --list-keys` 找出你所想要的 key: [source,console] ----- @@ -443,7 +442,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: +之后你可以通过导出 key 并通过管道传递给 `git hash-object` 来直接将 key 导入到 Git 的数据库中,`git hash-object` 命令会向 Git 中写入一个包含其内容的新 blob,并向你返回其 SHA-1 值: [source,console] ----- @@ -451,30 +450,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: +既然 Git 中已经包含你的 key 的内容了,你就可以通过指定 `hash-object` 命令给出的 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` 标签将会被共享给所有人。 +需要校验标签的人可以通过从数据库中直接拉取 blob 并导入到 GPG 中来导入 PGP key: [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. +人们可以使用这个 key 来校验所有由你签名的标签。 +另外,如果你在标签信息中包含了一些操作说明,用户可以通过运行 `git show ` 来获取更多关于标签校验的说明。 [[_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 中不存在随每次提交递增的“v123”之类的数字序列,如果你想要为提交附上一个可读的名称,可以对其运行 `git describe` 命令。 +Git 将会给出一个字符串,它由最近的标签名、自该标签之后的提交数目和你所描述的提交的部分 SHA-1 值构成: [source,console] ----- @@ -482,21 +481,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 自己的版本库克隆下来并编译的,那么 `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 内核为了保证 SHA-1 值对象的唯一性,将其位数由 8 位扩展到了 10 位,导致以前的 `git describe` 输出全部失效。 [[_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 +504,23 @@ $ 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`: +将这个压缩包解压,可以得到你的项目文件夹的最新快照。 +你也可以以类似的方式创建一个 zip 压缩包,此时你应该向 `git archive` 命令传递 `--format=zip` 选项: [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. +现在你有了本次发布的一个 tar 包和一个 zip 包,可以将其上传到网站或以电子邮件的形式发送给人们。 [[_the_shortlog]] -==== The 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` 命令可以快速生成一份包含从上次发布之后项目新增内容的修改日志(changelog)类文档。 +它会对你给定范围内的所有提交进行总结;比如,你的上一次发布名称是 v1.0.1,那么下面的命令可以给出上次发布以来所有提交的总结: [source,console] ----- @@ -541,4 +540,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. +这份整洁的总结包括了自 v1.0.1 以来的所有提交,并且已经按照作者分好组,你可以通过电子邮件直接将其发送到列表中。 diff --git a/status.json b/status.json index 65ad9e9d..f8827553 100644 --- a/status.json +++ b/status.json @@ -48,7 +48,7 @@ "1-distributed-git.asc": 0, "sections/contributing.asc": 0, "sections/distributed-workflows.asc": 0, - "sections/maintaining.asc": 0 + "sections/maintaining.asc": 100 }, "06-github": { "1-github.asc": 0, From 19a2e3470f7b781a415ec41c5fbe0213c6ef7696 Mon Sep 17 00:00:00 2001 From: secondwtq Date: Sun, 21 Jun 2015 14:23:21 +0800 Subject: [PATCH 2/6] Improved translation of 05-distributed-git maintaining --- .../sections/maintaining.asc | 115 +++++++++--------- 1 file changed, 58 insertions(+), 57 deletions(-) diff --git a/book/05-distributed-git/sections/maintaining.asc b/book/05-distributed-git/sections/maintaining.asc index 01fd6ebf..3e3f4330 100644 --- a/book/05-distributed-git/sections/maintaining.asc +++ b/book/05-distributed-git/sections/maintaining.asc @@ -1,16 +1,16 @@ === 维护项目 (((maintaining a project))) -除了如何有效地进行贡献之外,你可能也需要了解如何维护项目。 -这包含接受并处理别人使用 `format-patch` 生成并通过电子邮件发送过来的补丁,或对项目添加的远程版本库分支中的更改进行集成。 -但是无论是自己管理版本库,或者提供验证、审核补丁的帮助,你都需要了解如何以一种对于其他贡献者来说最清晰,且对自己来说长期可持续的方式来接受工作。 +除了如何有效地参与一个项目的贡献之外,你可能也需要了解如何维护项目。 +这包含接受并应用别人使用 `format-patch` 生成并通过电子邮件发送过来的补丁,或对项目添加的远程版本库分支中的更改进行整合。 +但是无论是自己管理版本库,或者想要提供验证、审核补丁的帮助,你都需要了解如何以一种对于其他贡献者来说最清晰,且对自己来说长期可持续的方式来接受工作。 ==== 在主题分支中工作 (((branches, topic))) -如果你想向项目中集成一些新东西,最好先在为此专门设立的一个临时分支——即主题分支中进行尝试。 +如果你想向项目中整合一些新东西,最好先在为此专门设立的一个临时分支——即主题分支中进行尝试。 这样便于单独调整补丁,如果遇到无法正常工作的情况,可以先不用管,等到有时间的时候再来处理。 -基于你所尝试的主题为这个分支起一个简单并且具有描述性的名字,比如 `ruby_client`,这样如果你暂时停止其中的工作,以后回来时也不会忘记。 +如果你创建的分支名字就是简单地基于你所要尝试的工作主题,比如 `ruby_client` 或者具有类似描述性的其他名字,这样如果你必须暂时抛弃它,以后回来时也不会忘记。 项目的维护者一般还会为这些分支附带命名空间,比如 `sc/ruby_client`(其中 `sc` 是贡献该项工作的人名称的简写)。 正如你所想到的,可以以如下的方式基于 master 分支建立主题分支: @@ -19,7 +19,7 @@ $ git branch sc/ruby_client master ----- -或者如果你想立刻切换到新分支上的话,可以使用 `checkout -b` 选项: +或者如果你同时想立刻切换到新分支上的话,可以使用 `checkout -b` 选项: [source,console] ----- @@ -32,10 +32,10 @@ $ git checkout -b sc/ruby_client master ==== 应用来自邮件的补丁 (((email, applying patches from))) -如果你通过电子邮件收到了一个需要集成进入工程的补丁,你需要将其应用到主题分支中进行评估。 +如果你通过电子邮件收到了一个需要整合进入工程的补丁,你需要将其应用到主题分支中进行评估。 有两种应用该种补丁的方法:使用 `git apply`,或者使用 `git am`。 -===== 使用 apply 命令应用补丁 +===== 使用 `apply` 命令应用补丁 (((git commands, apply))) 如果你收到了一个使用 `git diff` 或 Unix `diff` 命令(不推荐使用这种方式,具体见下一节)创建的补丁,可以使用 `git apply` 命令来应用。 @@ -47,11 +47,11 @@ $ git apply /tmp/patch-ruby-client.patch ----- 这会修改工作目录中的文件。 -它与运行 `patch -p1` 命令应用补丁几乎是等效的,但是这种方式更加严格,相对于 patch 来说,它能够接受的模糊匹配更少。 +它与运行 `patch -p1` 命令来应用补丁几乎是等效的,但是这种方式更加严格,相对于 patch 来说,它能够接受的模糊匹配更少。 它也能够处理 `git diff` 格式文件所描述的文件添加、删除和重命名操作,而 `patch` 则不会。 -最后,`git apply` 命令采用了一种“全部应用,否则就全部撤销(apply all or abort all)”的模型,即补丁只有全部内容都被应用和完全不被应用两个状态,而 `patch` 可能会导致补丁的部分应用,从而使工作目录的状态变得非常奇怪。 +最后,`git apply` 命令采用了一种“全部应用,否则就全部撤销(apply all or abort all)”的模型,即补丁只有全部内容都被应用和完全不被应用两个状态,而 `patch` 可能会导致补丁文件的部分应用,最后使你的工作目录保持在一个比较奇怪的状态。 总体来看,`git apply` 命令要比 `patch` 谨慎得多。 -并且,它不会进行提交——在运行之后,你需要手动暂存并提交补丁所引入的更改。 +并且,它不会为你创建提交——在运行之后,你需要手动暂存并提交补丁所引入的更改。 在实际应用补丁前,你还可以使用 git apply 来检查补丁是否可以整洁地应用——即对补丁运行 `git apply --check` 命令: @@ -70,7 +70,7 @@ error: ticgit.gemspec: patch does not apply (((git commands, am))) 如果补丁的贡献者也是一个 Git 用户,并且其水平足以使用 `format-patch` 命令来生成补丁,那么因为补丁中包含了作者信息和提交消息,你应用补丁的工作会变得更加轻松。 -请鼓励贡献者使用 `format-patch` 而不是 `diff` 来为你生成补丁。 +如果可能的话,请鼓励贡献者使用 `format-patch` 而不是 `diff` 来为你生成补丁。 而只有对老式的补丁,你才必须使用 `git apply` 命令。 要应用一个由 `format-patch` 命令生成的补丁,你应该使用 `git am` 命令。 @@ -90,9 +90,9 @@ Limit log functionality to the first 20 这其实就是你前面看到的 format-patch 命令的输出的开始几行。 而同时它也是有效的 mbox 电子邮件格式。 如果有人使用 git send-email 命令将补丁以电子邮件的形式发送给你,你便可以将它下载为 mbox 格式的文件,之后将 git am 命令指向该文件,它会应用其中包含的所有补丁。 -如果你所使用的邮件客户端能够同时将多封邮件保存为 mbox 格式的文件,你甚至能够将一系列补丁打包为单个 mbox 文件,并利用 `git am` 命令你个将它们一次性全部应用。 +如果你所使用的邮件客户端能够同时将多封邮件保存为 mbox 格式的文件,你甚至能够将一系列补丁打包为单个 mbox 文件,并利用 `git am` 命令将它们一次性全部应用。 -另外,如果贡献者将 `format-patch` 生成的补丁文件上传到类似 Request Ticket 的任务处理系统,你可以先将其下载到本地,之后运行 `git am` 来应用: +另外,如果贡献者将 `format-patch` 生成的补丁文件上传到类似 Request Ticket 的任务处理系统,你可以先将其保存到本地,之后运行 `git am` 来应用: [source,console] ----- @@ -117,8 +117,8 @@ CommitDate: Thu Apr 9 09:19:06 2009 -0700 Limit log functionality to the first 20 ----- -其中 `Commit` 信息表示的是应用补丁的人和时间。 -`Author` 信息则表示补丁的原作者和创建时间。 +其中 `Commit` 信息表示的是应用补丁的人和应用补丁的时间。 +`Author` 信息则表示补丁的原作者和原本的创建时间。 但是,有时候补丁可能无法整洁地应用。 这也许是因为你的主分支和创建补丁的分支相差较多,也有可能是因为这个补丁依赖于其他你尚未应用的补丁。 @@ -165,7 +165,7 @@ No changes -- Patch already applied. 比如上面这种情况,我在之前已经应用过同样的补丁。 如果没有 `-3` 选项的话,看起来就像是存在一个冲突。 -如果你正在利用一个 mbox 文件用用多个补丁,也可以在交互模式下运行 `am` 命令,这样在每个补丁之前,它会停住询问你是否要应用: +如果你正在利用一个 mbox 文件应用多个补丁,也可以在交互模式下运行 `am` 命令,这样在每个补丁之前,它会停住询问你是否要应用: [source,console] ----- @@ -199,15 +199,15 @@ $ git checkout -b rubyclient jessica/ruby-client 如果她再次发邮件说另一个分支中包含另一个优秀功能,因为之前已经设置好远程分支了,你就可以直接进行抓取及检出操作。 这对于与他人长期合作工作来说很有用。 -而对于提交补丁较少的贡献者,相对于每个人维护自己的服务器,频繁增删远程分支的做法,使用电子邮件来接收就会省时许多。 -况且你也不会想要加入数百个只提供一两个补丁的远程分支。 +而对于提交补丁频率较小的贡献者,相对于每个人维护自己的服务器,不断增删远程的做法,使用电子邮件来接收可能会比较省时。 +况且你也不会想要加入数百个只提供一两个补丁的远程。 然而,脚本和托管服务在一定程度上可以简化这些工作——这很大依赖于你和你的贡献者开发的方式。 这种方式的另一种优点是你同时可以得到提交历史。 虽然代码合并中可能会出现问题,但是你能获知他人的工作基于你的历史中的具体哪一个位置;所以Git 会默认进行三方合并,不需要提供 `-3` 选项,你也不需要担心补丁是基于某个你无法访问的提交生成的。 -对于非持续性的合作,如果你依然想要以这种方式拉取数据的话,你可以对远程分支的 URL 调用 `git pull` 命令。 -这会执行一个一次性的抓取,而不会将 URL 存为远程引用: +对于非持续性的合作,如果你依然想要以这种方式拉取数据的话,你可以对远程版本库的 URL 调用 `git pull` 命令。 +这会执行一个一次性的抓取,而不会将该 URL 存为远程引用: [source,console] ----- @@ -261,12 +261,12 @@ $ git diff master 这是因为 Git 会直接将该主题分支与 `master` 分支的最新提交快照进行比较。 比如说你在 `master` 分支中向某个文件添加了一行内容,那么直接比对最新快照的结果看上去就像是你在主题分支中将这一行删除了。 -如果 `master` 分支是主题分支的直接祖先,其实是没有任何问题的;但是一旦两个分支的历史产生了分叉,上述比对产生的 diff 看上去就像是将主题分支中所有的新东西加入,并且将 `master` 分支所独有的东西删除。 +如果 `master` 分支是你的主题分支的直接祖先,其实是没有任何问题的;但是一旦两个分支的历史产生了分叉,上述比对产生的 diff 看上去就像是将主题分支中所有的新东西加入,并且将 `master` 分支所独有的东西删除。 而你真正想要检查的东西,实际上仅仅是特性分支所添加的更改——也就是该分支与 master 分支合并所要引入的工作。 要达到此目的,你需要让 Git 对主题分支上最新的提交与该分支与 master 分支的首个公共祖先进行比较。 -从技术的角度讲,你可以以以手工的方式找出公共祖先,并对其显式运行 diff 命令: +从技术的角度讲,你可以以手工的方式找出公共祖先,并对其显式运行 diff 命令: [source,console] ----- @@ -286,12 +286,12 @@ $ git diff master...contrib 该命令仅会显示自当前主题分支与 master 分支的共同祖先起,该分支中的工作。 这个语法很有用,应该牢记。 -==== 将贡献的工作集成进来 +==== 将贡献的工作整合进来 (((integrating work))) -当主题分支中所有的工作都已经准备好集成进入更靠近主线的分支时,接下来的问题就是如何进行集成了。 +当主题分支中所有的工作都已经准备好整合进入更靠近主线的分支时,接下来的问题就是如何进行整合了。 此外,还有一个问题是,你想使用怎样的总体工作流来维护你的项目? -可能的选择有很多,我们只会介绍其中的一部分。 +你可能的选择有很多,我们会介绍其中的一部分。 ===== 合并工作流 @@ -299,7 +299,7 @@ $ git diff master...contrib 一种非常简单的工作流会直接将工作合并进入 `master` 分支。 在这种情况下,`master` 分支包含的代码是基本稳定的。 当你完成某个主题分支的工作,或审核通过了其他人所贡献的工作时,你会将其合并进入 master 分支,之后将主题分支删除,如此反复。 -如果我们的版本库包含类似 <> 的两个名称分别为 `ruby_client` 和 `php_client` 的分支,并且我们先合并 `ruby_client` 分支,之后合并 `php_client` 分支,那么提交历史就会变成 <> 的样子。 +如果我们的版本库包含类似 <> 的两个名称分别为 `ruby_client` 和 `php_client` 的分支,并且我们先合并 `ruby_client` 分支,之后合并 `php_client` 分支,那么提交历史最后会变成 <> 的样子。 [[merwf_a]] .包含若干主题分支的提交历史 @@ -312,8 +312,9 @@ image::images/merging-workflows-2.png[合并主题分支之后] 这也许是最简单的工作流了,但是当项目更大,或更稳定,你对自己所引入的工作更加在意时,它可能会带来问题。 如果你的项目更加重要,你可能会使用两阶段合并循环。 -在这种情况下,你会维护两个长期分支,分别是 `master` 和 `develop`,`master` 分支只会在一个非常稳定的版本发布时才会更新,而所有的新代码会首先集成进入 `develop` 分支。 -每次需要合并新的主题分支时(<>),都应该合并进入 `develop` 分支(<>);当打标签发布的时候,你会将 `master` 分支快进到已经稳定的 `develop` 分支(<>)。 +在这种情况下,你会维护两个长期分支,分别是 `master` 和 `develop`,`master` 分支只会在一个非常稳定的版本发布时才会更新,而所有的新代码会首先整合进入 `develop` 分支。 +你定期将这两个分支推送到公共版本库中。 +每次需要合并新的主题分支时(<>),你都应该合并进入 `develop` 分支(<>);当打标签发布的时候,你会将 `master` 分支快进到已经稳定的 `develop` 分支(<>)。 [[merwf_c]] .合并主题分支前 @@ -328,7 +329,7 @@ image::images/merging-workflows-4.png[合并主题分支后] image::images/merging-workflows-5.png[一次发布之后] 这样当人们克隆你项目的版本库后,既可以检出 master 分支以构建最新的稳定版本并保持更新,也可以检出包含更多新东西的 develop 分支。 -你也可以扩展这个概念,维护一个所有工作被合并到一起的集成分支。 +你也可以扩展这个概念,维护一个所有工作被合并到一起的整合分支。 当该分支的代码稳定并通过测试之后,将其合并进入 develop 分支;经过一段时间,确认其稳定之后,将其以快进的形式并入 master 分支。 ===== 大项目合并工作流 @@ -337,7 +338,7 @@ image::images/merging-workflows-5.png[一次发布之后] Git 项目包含四个长期分支:`master`,`next`,用于新工作的 `pu`(proposed updates)和用于维护和 backport 的 `maint`分支。 贡献者的新工作会以类似之前所介绍的方式收入主题分支中(见 <>)。 之后对主题分支进行测试评估,检查其是否已经能够合并,或者仍需要更多工作。 -稳定安全的主题分支会被合并入 `next` 分支,之后推送该分支使得所有人都可以尝试集成到一起的主题。 +安全的主题分支会被合并入 `next` 分支,之后该分支会被推送使得所有人都可以尝试整合到一起的主题。 [[merwf_f]] .管理复杂的一系列并行接收贡献的主题分支 @@ -347,30 +348,30 @@ image::images/large-merges-1.png[管理复杂的一系列并行接收贡献的 当它们完全稳定之后,会被再次并入 `master` 分支。 这意味着 `master` 分支始终在进行快进,`next` 分支偶尔会被变基,而 `pu` 分支变基比较频繁: -.将贡献过来的主题分支并入长期集成分支 -image::images/large-merges-2.png[将贡献过来的主题分支并入长期集成分支] +.将贡献过来的主题分支并入长期整合分支 +image::images/large-merges-2.png[将贡献过来的主题分支并入长期整合分支] 当主题分支最终被并入 `master` 分支后,便会被从版本库中删除掉。 -Git 项目还有一个从上一次发布中 fork 出来的 `maint` 分支来提供 backport 过来的补丁以供发布维护更新。 -因此,当你克隆 Git 的版本库之后,就会有四个可签出的分支,分别代表了开发的不同阶段,签出哪个分支,取决于你需要多新的版本,或者你想要如何进行贡献;对于维护者来说,这套结构化的工作流能帮助它们审查新的贡献。 +Git 项目还有一个从上一次发布中派生出来的 `maint` 分支来提供 backport 过来的补丁以供发布维护更新。 +因此,当你克隆 Git 的版本库之后,就会有四个可签出的分支,可分别评估该项目开发的不同阶段,签出哪个分支,取决于你需要多新的版本,或者你想要如何进行贡献;对于维护者来说,这套结构化的工作流能帮助它们审查新的贡献。 [[_rebase_cherry_pick]] -===== 变基与挑拣工作流 +===== 变基与拣选工作流 (((workflows, rebasing and cherry-picking))) -为了保持线性的提交历史,有些维护者比较喜欢在 master 分支上对贡献过来的工作进行变基和挑拣,而不是直接将其合并。 -当你完成某个特性分支中的工作,并且决定要将其集成的时候,你可以在该分支中运行变基命令,在当前 master 分支(或者是 `develop` 等分支)的基础上重新构造修改。 +为了保持线性的提交历史,有些维护者更喜欢在 master 分支上对贡献过来的工作进行变基和拣选,而不是直接将其合并。 +当你完成了某个主题分支中的工作,并且决定要将其整合的时候,你可以在该分支中运行变基命令,在当前 master 分支(或者是 `develop` 等分支)的基础上重新构造修改。 如果结果理想的话,你可以快进 `master` 分支,最后得到一个线性的项目提交历史。 (((git commands, cherry-pick))) -另一种将引入的工作转移到其他分支的方法是挑拣。 -Git 中的挑拣类似于对特定的某次提交的变基。 -它会提起该提交的补丁,之后尝试将其重新应用到当前分支上。 +另一种将引入的工作转移到其他分支的方法是拣选。 +Git 中的拣选类似于对特定的某次提交的变基。 +它会提取该提交的补丁,之后尝试将其重新应用到当前分支上。 这种方式在你只想引入主题分支中的某个提交,或者主题分支中只有一个提交,而你不想运行变基时很有用。 假如你的工程提交历史类似: -.挑拣之前的示例历史 -image::images/rebasing-1.png[挑拣之前的示例历史] +.拣选之前的示例历史 +image::images/rebasing-1.png[拣选之前的示例历史] 如果你希望将提交 `e43a6` 拉取到 master 分支,你可以运行: @@ -382,20 +383,20 @@ Finished one cherry-pick. 3 files changed, 17 insertions(+), 3 deletions(-) ----- -这样会拉取和 `e43a6` 相同的更改,但是得到的提交 SHA-1 值是不同的,因为应用的日期不同。 +这样会拉取和 `e43a6` 相同的更改,但是你会得到一个新的提交 SHA-1 值,因为应用的日期不同。 现在你的历史会变成这样: -.挑拣主题分支中的一个提交后的历史 -image::images/rebasing-2.png[挑拣主题分支中的一个提交后的历史] +.拣选主题分支中的一个提交后的历史 +image::images/rebasing-2.png[拣选主题分支中的一个提交后的历史] -现在你可以删除这个主题分支,丢弃不想引入的提交。 +现在你可以删除这个主题分支,并丢弃不想拉入的提交。 ===== Rerere (((git commands, rerere)))(((rerere))) 如果你在进行大量的合并或变基,或维护一个长期的主题分支,Git 提供的一个叫做“rerere”的功能会有一些帮助。 -Rerere 是“重用记录的解决方案”的意思——它是手动冲突解决的一种快捷方式。 +Rerere 是“重用记录下的解决方案(reuse recorded resolution)”的意思——它是手动冲突解决的一种快捷方式。 当启用 rerere 时,Git 将会维护一些成功合并之前和之后的镜像,当 Git 发现和之前已经修复过的类似的冲突时,便会使用之前的修复方案,而不需要你的干预。 这个功能包含两个部分:一个配置选项和一个命令。 @@ -417,7 +418,7 @@ $ git config --global rerere.enabled true (((tags)))(((tags, signing))) 当你决定进行一次发布时,你可能想要留下一个标签,这样在之后的任何一个提交点都可以重新创建该发布。 -你在 <<_git_basics_chapter>> 已经了解了创建新标签的过程。 +你在 <<_git_basics_chapter>> 中已经了解了创建新标签的过程。 作为一个维护者,如果你决定要为标签签名的话,打标签的过程应该是这样子的: [source,console] @@ -429,7 +430,7 @@ user: "Scott Chacon " ----- 如果你为标签签名了,你可能会遇到分发用来签名的 PGP 公钥的问题。 -Git 项目的维护者已经解决了这一问题:在版本库中以 blob 的形式包含他们的公钥,并添加一个直接指向该内容的标签。 +Git 项目的维护者已经解决了这一问题:在版本库中以 blob 对象的形式包含他们的公钥,并添加一个直接指向该内容的标签。 要完成这一任务,首先你可以通过运行 `gpg --list-keys` 找出你所想要的 key: [source,console] @@ -442,7 +443,7 @@ uid Scott Chacon sub 2048g/45D02282 2009-02-09 [expires: 2010-02-09] ----- -之后你可以通过导出 key 并通过管道传递给 `git hash-object` 来直接将 key 导入到 Git 的数据库中,`git hash-object` 命令会向 Git 中写入一个包含其内容的新 blob,并向你返回其 SHA-1 值: +之后你可以通过导出 key 并通过管道传递给 `git hash-object` 来直接将 key 导入到 Git 的数据库中,`git hash-object` 命令会向 Git 中写入一个包含其内容的新 blob 对象,并向你返回该 blob 对象的 SHA-1 值: [source,console] ----- @@ -450,7 +451,7 @@ $ gpg -a --export F721C45A | git hash-object -w --stdin 659ef797d181633c87ec71ac3f9ba29fe5775b92 ----- -既然 Git 中已经包含你的 key 的内容了,你就可以通过指定 `hash-object` 命令给出的 SHA-1 值来创建一个直接指向它的标签: +既然 Git 中已经包含你的 key 的内容了,你就可以通过指定 `hash-object` 命令给出的新 SHA-1 值来创建一个直接指向它的标签: [source,console] ----- @@ -458,7 +459,7 @@ $ git tag -a maintainer-pgp-pub 659ef797d181633c87ec71ac3f9ba29fe5775b92 ----- 如果你运行 `git push --tags` 命令,那么 `maintainer-pgp-pub` 标签将会被共享给所有人。 -需要校验标签的人可以通过从数据库中直接拉取 blob 并导入到 GPG 中来导入 PGP key: +需要校验标签的人可以通过从数据库中直接拉取 blob 对象并导入到 GPG 中来导入 PGP key: [source,console] ----- @@ -482,7 +483,7 @@ v1.6.2-rc1-20-g8c5b85c ----- 这样你在导出一个快照或构建时,可以给出一个便于人们理解的命名。 -实际上,如果你的 Git 是从 Git 自己的版本库克隆下来并编译的,那么 `git --version` 命令给出的结果是与此类似的。 +实际上,如果你的 Git 是从 Git 自己的版本库克隆下来并构建的,那么 `git --version` 命令给出的结果是与此类似的。 如果你所描述的提交自身就有一个标签,那么它将只会输出标签名,没有后面两项信息。 注意 `git describe` 命令只适用于有注解的标签(即使用 `-a` 或 `-s` 选项创建的标签),所以如果你在使用 `git describe` 命令的话,为了确保能为标签生成合适的名称,打发布标签时都应该采用加注解的方式。 @@ -504,8 +505,8 @@ $ ls *.tar.gz v1.6.2-rc1-20-g8c5b85c.tar.gz ----- -将这个压缩包解压,可以得到你的项目文件夹的最新快照。 -你也可以以类似的方式创建一个 zip 压缩包,此时你应该向 `git archive` 命令传递 `--format=zip` 选项: +如果有人将这个压缩包解压,他就可以得到你的项目文件夹的最新快照。 +你也可以以类似的方式创建一个 zip 压缩包,但此时你应该向 `git archive` 命令传递 `--format=zip` 选项: [source,console] ----- @@ -518,7 +519,7 @@ $ git archive master --prefix='project/' --format=zip > `git describe master`.zi ==== 制作提交简报 (((git commands, shortlog))) -现在是时候通知邮件列表里那些好奇项目进度的人了。 +现在是时候通知邮件列表里那些好奇你的项目发生了什么的人了。 使用 `git shortlog` 命令可以快速生成一份包含从上次发布之后项目新增内容的修改日志(changelog)类文档。 它会对你给定范围内的所有提交进行总结;比如,你的上一次发布名称是 v1.0.1,那么下面的命令可以给出上次发布以来所有提交的总结: From 3a74e29a648ef7f1290eac01f1227de2655f2bc5 Mon Sep 17 00:00:00 2001 From: secondwtq Date: Mon, 3 Aug 2015 23:34:06 +0800 Subject: [PATCH 3/6] Reviewed by @IceNature . --- .../sections/maintaining.asc | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/book/05-distributed-git/sections/maintaining.asc b/book/05-distributed-git/sections/maintaining.asc index 3e3f4330..94a591b5 100644 --- a/book/05-distributed-git/sections/maintaining.asc +++ b/book/05-distributed-git/sections/maintaining.asc @@ -3,14 +3,14 @@ (((maintaining a project))) 除了如何有效地参与一个项目的贡献之外,你可能也需要了解如何维护项目。 这包含接受并应用别人使用 `format-patch` 生成并通过电子邮件发送过来的补丁,或对项目添加的远程版本库分支中的更改进行整合。 -但是无论是自己管理版本库,或者想要提供验证、审核补丁的帮助,你都需要了解如何以一种对于其他贡献者来说最清晰,且对自己来说长期可持续的方式来接受工作。 +但是无论是自己管理版本库,还是想要提供验证、审核补丁的帮助,你都需要了解如何以一种对于其他贡献者来说最清晰,且对自己来说长期可持续的方式来接受工作。 ==== 在主题分支中工作 (((branches, topic))) 如果你想向项目中整合一些新东西,最好先在为此专门设立的一个临时分支——即主题分支中进行尝试。 这样便于单独调整补丁,如果遇到无法正常工作的情况,可以先不用管,等到有时间的时候再来处理。 -如果你创建的分支名字就是简单地基于你所要尝试的工作主题,比如 `ruby_client` 或者具有类似描述性的其他名字,这样如果你必须暂时抛弃它,以后回来时也不会忘记。 +如果你基于你所尝试的工作主题为分支创建一个简单的名字,比如 `ruby_client` 或者具有类似描述性的其他名字,这样即使你必须暂时抛弃它,以后回来时也不会忘记。 项目的维护者一般还会为这些分支附带命名空间,比如 `sc/ruby_client`(其中 `sc` 是贡献该项工作的人名称的简写)。 正如你所想到的,可以以如下的方式基于 master 分支建立主题分支: @@ -49,7 +49,7 @@ $ git apply /tmp/patch-ruby-client.patch 这会修改工作目录中的文件。 它与运行 `patch -p1` 命令来应用补丁几乎是等效的,但是这种方式更加严格,相对于 patch 来说,它能够接受的模糊匹配更少。 它也能够处理 `git diff` 格式文件所描述的文件添加、删除和重命名操作,而 `patch` 则不会。 -最后,`git apply` 命令采用了一种“全部应用,否则就全部撤销(apply all or abort all)”的模型,即补丁只有全部内容都被应用和完全不被应用两个状态,而 `patch` 可能会导致补丁文件的部分应用,最后使你的工作目录保持在一个比较奇怪的状态。 +最后,`git apply` 命令采用了一种“全部应用,否则就全部撤销(apply all or abort all)”的模型,即补丁只有全部内容都被应用和完全不被应用两个状态,而 `patch` 可能会导致补丁文件被部分应用,最后使你的工作目录保持在一个比较奇怪的状态。 总体来看,`git apply` 命令要比 `patch` 谨慎得多。 并且,它不会为你创建提交——在运行之后,你需要手动暂存并提交补丁所引入的更改。 @@ -62,14 +62,14 @@ error: patch failed: ticgit.gemspec:1 error: ticgit.gemspec: patch does not apply ----- -如果没有产生输出,说明该补丁可以整洁地应用。 +如果没有产生输出,则该补丁可以整洁地应用。 如果检查失败了,该命令还会以一个非零的状态退出,所以需要时你也可以在脚本中使用它。 [[_git_am]] ===== 使用 `am` 命令应用补丁 (((git commands, am))) -如果补丁的贡献者也是一个 Git 用户,并且其水平足以使用 `format-patch` 命令来生成补丁,那么因为补丁中包含了作者信息和提交消息,你应用补丁的工作会变得更加轻松。 +如果补丁的贡献者也是一个 Git 用户,并且其有轻松使用 `format-patch` 命令生成补丁的水平,那么因为补丁中包含了作者信息和提交消息,你应用补丁的工作会变得更加轻松。 如果可能的话,请鼓励贡献者使用 `format-patch` 而不是 `diff` 来为你生成补丁。 而只有对老式的补丁,你才必须使用 `git apply` 命令。 @@ -100,9 +100,9 @@ $ git am 0001-limit-log-function.patch Applying: add limit to log function ----- -你会看到补丁被优雅整洁地应用,新的提交也会被帮你创建好。 +你会看到补丁被优雅整洁地应用,新的提交也会被创建好。 其中的作者信息来自于电子邮件头部的 `From` 和 `Date` 字段,提交消息则取自 `Subject` 和邮件正文中补丁之前的内容。 -比如,根据上面那个 mbox 示例所生成的提交是这样的: +比如,应用上面那个 mbox 示例后生成的提交是这样的: ----- $ git log --pretty=fuller -1 @@ -136,7 +136,7 @@ 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". ----- -该命令将会在所有出现问题的文件内加入冲突标记,就像发生冲突的合并或变基操作一样。 +该命令将会在所有出现问题的文件内加入冲突标记,就和发生冲突的合并或变基操作一样。 而你解决问题的手段很大程度上也是一样的——即手动编辑那些文件来解决冲突,暂存新的文件,之后运行 `git am --resolved` 继续应用下一个补丁: [source,console] @@ -149,7 +149,7 @@ Applying: seeing if this helps the gem 如果你希望 Git 能够尝试以更加智能的方式解决冲突,你可以对其传递 `-3` 选项来使 Git 尝试进行三方合并。 该选项默认并没有打开,因为如果用于创建补丁的提交并不在你的版本库内的话,这样做是没有用处的。 -而如果你确实有那个提交的话——比如补丁是基于某个公共提交的——那么 `-3` 选项对于应用有冲突的补丁一般是更加明智的选择。 +而如果你确实有那个提交的话——比如补丁是基于某个公共提交的——那么通常 `-3` 选项对于应用有冲突的补丁是更加明智的选择。 [source,console] ----- @@ -163,7 +163,7 @@ No changes -- Patch already applied. ----- 比如上面这种情况,我在之前已经应用过同样的补丁。 -如果没有 `-3` 选项的话,看起来就像是存在一个冲突。 +如果没有 `-3` 选项的话,这看起来就像是存在一个冲突。 如果你正在利用一个 mbox 文件应用多个补丁,也可以在交互模式下运行 `am` 命令,这样在每个补丁之前,它会停住询问你是否要应用: @@ -203,8 +203,8 @@ $ git checkout -b rubyclient jessica/ruby-client 况且你也不会想要加入数百个只提供一两个补丁的远程。 然而,脚本和托管服务在一定程度上可以简化这些工作——这很大依赖于你和你的贡献者开发的方式。 -这种方式的另一种优点是你同时可以得到提交历史。 -虽然代码合并中可能会出现问题,但是你能获知他人的工作基于你的历史中的具体哪一个位置;所以Git 会默认进行三方合并,不需要提供 `-3` 选项,你也不需要担心补丁是基于某个你无法访问的提交生成的。 +这种方式的另一种优点是你可以同时得到提交历史。 +虽然代码合并中可能会出现问题,但是你能获知他人的工作是基于你的历史中的具体哪一个位置;所以Git 会默认进行三方合并,不需要提供 `-3` 选项,你也不需要担心补丁是基于某个你无法访问的提交生成的。 对于非持续性的合作,如果你依然想要以这种方式拉取数据的话,你可以对远程版本库的 URL 调用 `git pull` 命令。 这会执行一个一次性的抓取,而不会将该 URL 存为远程引用: @@ -221,7 +221,7 @@ Merge made by recursive. ==== 确定引入了哪些东西 (((branches, diffing))) -你已经有了一个包含其他人所贡献工作的主题分支。 +你已经有了一个包含其他人贡献的工作的主题分支。 现在你可以决定如何处理它们了。 本节回顾了若干命令,以便于你检查若将其合并进入主要分支所引入的更改。 @@ -276,7 +276,7 @@ $ git diff 36c7db ----- 然而,这种做法比较麻烦,所以 Git 提供了一种比较便捷的方式:三点语法。 -对于 `diff` 命令来说,你可以通过把 `...` 置于另一个分支名后,来对该分支的最新提交与两个分支的共同祖先进行比较: +对于 `diff` 命令来说,你可以通过把 `...` 置于另一个分支名后来对该分支的最新提交与两个分支的共同祖先进行比较: [source,console] ----- @@ -311,7 +311,7 @@ image::images/merging-workflows-2.png[合并主题分支之后] 这也许是最简单的工作流了,但是当项目更大,或更稳定,你对自己所引入的工作更加在意时,它可能会带来问题。 -如果你的项目更加重要,你可能会使用两阶段合并循环。 +如果你的项目非常重要,你可能会使用两阶段合并循环。 在这种情况下,你会维护两个长期分支,分别是 `master` 和 `develop`,`master` 分支只会在一个非常稳定的版本发布时才会更新,而所有的新代码会首先整合进入 `develop` 分支。 你定期将这两个分支推送到公共版本库中。 每次需要合并新的主题分支时(<>),你都应该合并进入 `develop` 分支(<>);当打标签发布的时候,你会将 `master` 分支快进到已经稳定的 `develop` 分支(<>)。 @@ -329,7 +329,7 @@ image::images/merging-workflows-4.png[合并主题分支后] image::images/merging-workflows-5.png[一次发布之后] 这样当人们克隆你项目的版本库后,既可以检出 master 分支以构建最新的稳定版本并保持更新,也可以检出包含更多新东西的 develop 分支。 -你也可以扩展这个概念,维护一个所有工作被合并到一起的整合分支。 +你也可以扩展这个概念,维护一个将所有工作合并到一起的整合分支。 当该分支的代码稳定并通过测试之后,将其合并进入 develop 分支;经过一段时间,确认其稳定之后,将其以快进的形式并入 master 分支。 ===== 大项目合并工作流 @@ -344,16 +344,16 @@ Git 项目包含四个长期分支:`master`,`next`,用于新工作的 `pu` .管理复杂的一系列并行接收贡献的主题分支 image::images/large-merges-1.png[管理复杂的一系列并行接收贡献的主题分支] -如果主题分支需要更多工作,则会被并入 `pu` 分支。 +如果主题分支需要更多工作,它则会被并入 `pu` 分支。 当它们完全稳定之后,会被再次并入 `master` 分支。 -这意味着 `master` 分支始终在进行快进,`next` 分支偶尔会被变基,而 `pu` 分支变基比较频繁: +这意味着 `master` 分支始终在进行快进,`next` 分支偶尔会被变基,而 `pu` 分支的变基比较频繁: .将贡献过来的主题分支并入长期整合分支 image::images/large-merges-2.png[将贡献过来的主题分支并入长期整合分支] 当主题分支最终被并入 `master` 分支后,便会被从版本库中删除掉。 Git 项目还有一个从上一次发布中派生出来的 `maint` 分支来提供 backport 过来的补丁以供发布维护更新。 -因此,当你克隆 Git 的版本库之后,就会有四个可签出的分支,可分别评估该项目开发的不同阶段,签出哪个分支,取决于你需要多新的版本,或者你想要如何进行贡献;对于维护者来说,这套结构化的工作流能帮助它们审查新的贡献。 +因此,当你克隆 Git 的版本库之后,就会有四个可分别评估该项目开发的不同阶段的可签出的分支,签出哪个分支,取决于你需要多新的版本,或者你想要如何进行贡献;对于维护者来说,这套结构化的工作流能帮助它们审查新的贡献。 [[_rebase_cherry_pick]] ===== 变基与拣选工作流 @@ -383,7 +383,7 @@ Finished one cherry-pick. 3 files changed, 17 insertions(+), 3 deletions(-) ----- -这样会拉取和 `e43a6` 相同的更改,但是你会得到一个新的提交 SHA-1 值,因为应用的日期不同。 +这样会拉取和 `e43a6` 相同的更改,但是因为应用的日期不同,你会得到一个新的提交 SHA-1 值。 现在你的历史会变成这样: .拣选主题分支中的一个提交后的历史 @@ -451,7 +451,7 @@ $ gpg -a --export F721C45A | git hash-object -w --stdin 659ef797d181633c87ec71ac3f9ba29fe5775b92 ----- -既然 Git 中已经包含你的 key 的内容了,你就可以通过指定 `hash-object` 命令给出的新 SHA-1 值来创建一个直接指向它的标签: +既然 Git 中已经包含你的 key 的内容了,你就可以通过指定由 `hash-object` 命令给出的新 SHA-1 值来创建一个直接指向它的标签: [source,console] ----- @@ -541,4 +541,4 @@ Tom Preston-Werner (4): Regenerated gemspec for version 1.0.2 ----- -这份整洁的总结包括了自 v1.0.1 以来的所有提交,并且已经按照作者分好组,你可以通过电子邮件直接将其发送到列表中。 +这份整洁的总结包括了自 v1.0.1 以来的所有提交,并且已经按照作者分好组,你可以通过电子邮件将其直接发送到列表中。 From 6ad4d1dd68da4a04ca996841440dc87d4e80bc7c Mon Sep 17 00:00:00 2001 From: secondwtq Date: Mon, 3 Aug 2015 23:50:08 +0800 Subject: [PATCH 4/6] Fixed translation of "topic branch" according to TRANSLATION_NOTES. --- .../sections/maintaining.asc | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/book/05-distributed-git/sections/maintaining.asc b/book/05-distributed-git/sections/maintaining.asc index 94a591b5..437b805d 100644 --- a/book/05-distributed-git/sections/maintaining.asc +++ b/book/05-distributed-git/sections/maintaining.asc @@ -5,14 +5,14 @@ 这包含接受并应用别人使用 `format-patch` 生成并通过电子邮件发送过来的补丁,或对项目添加的远程版本库分支中的更改进行整合。 但是无论是自己管理版本库,还是想要提供验证、审核补丁的帮助,你都需要了解如何以一种对于其他贡献者来说最清晰,且对自己来说长期可持续的方式来接受工作。 -==== 在主题分支中工作 +==== 在特性分支中工作 (((branches, topic))) -如果你想向项目中整合一些新东西,最好先在为此专门设立的一个临时分支——即主题分支中进行尝试。 +如果你想向项目中整合一些新东西,最好先在为此专门设立的一个临时分支——即特性分支中进行尝试。 这样便于单独调整补丁,如果遇到无法正常工作的情况,可以先不用管,等到有时间的时候再来处理。 -如果你基于你所尝试的工作主题为分支创建一个简单的名字,比如 `ruby_client` 或者具有类似描述性的其他名字,这样即使你必须暂时抛弃它,以后回来时也不会忘记。 +如果你基于你所尝试进行工作的特性为分支创建一个简单的名字,比如 `ruby_client` 或者具有类似描述性的其他名字,这样即使你必须暂时抛弃它,以后回来时也不会忘记。 项目的维护者一般还会为这些分支附带命名空间,比如 `sc/ruby_client`(其中 `sc` 是贡献该项工作的人名称的简写)。 -正如你所想到的,可以以如下的方式基于 master 分支建立主题分支: +正如你所想到的,可以以如下的方式基于 master 分支建立特性分支: [source,console] ----- @@ -26,13 +26,13 @@ $ git branch sc/ruby_client master $ git checkout -b sc/ruby_client master ----- -现在你已经准备好将别人贡献的工作加入到这个主题分支,并考虑是否将其合并到长期分支中去了。 +现在你已经准备好将别人贡献的工作加入到这个特性分支,并考虑是否将其合并到长期分支中去了。 [[_patches_from_email]] ==== 应用来自邮件的补丁 (((email, applying patches from))) -如果你通过电子邮件收到了一个需要整合进入工程的补丁,你需要将其应用到主题分支中进行评估。 +如果你通过电子邮件收到了一个需要整合进入工程的补丁,你需要将其应用到特性分支中进行评估。 有两种应用该种补丁的方法:使用 `git apply`,或者使用 `git am`。 ===== 使用 `apply` 命令应用补丁 @@ -179,7 +179,7 @@ Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all 这在你保存的补丁较多时很好用,因为你可以在应用之前查看忘掉内容的补丁,并且跳过已经应用过的补丁。 -当与主题相关的所有补丁都被应用并提交到分支中之后,你就可以选择是否以及如何将其整合到更长期的分支中去了。 +当与你的特性相关的所有补丁都被应用并提交到分支中之后,你就可以选择是否以及如何将其整合到更长期的分支中去了。 [[_checking_out_remotes]] ==== 检出远程分支 @@ -221,7 +221,7 @@ Merge made by recursive. ==== 确定引入了哪些东西 (((branches, diffing))) -你已经有了一个包含其他人贡献的工作的主题分支。 +你已经有了一个包含其他人贡献的工作的特性分支。 现在你可以决定如何处理它们了。 本节回顾了若干命令,以便于你检查若将其合并进入主要分支所引入的更改。 @@ -248,7 +248,7 @@ Date: Mon Oct 22 19:38:36 2008 -0700 如果要查看每次提交所引入的具体修改,你应该记得可以给 `git log` 命令传递 `-p` 选项,这样它会在每次提交后面附加对应的 diff。 -而要查看将该主题分支与另一个分支合并的完整 diff,你可能需要使用一个有些奇怪的技巧来得到正确的结果。 +而要查看将该特性分支与另一个分支合并的完整 diff,你可能需要使用一个有些奇怪的技巧来得到正确的结果。 你可能会想到这种方式: [source,console] @@ -257,14 +257,14 @@ $ git diff master ----- 这个命令会输出一个 diff,但它可能并不是我们想要的。 -如果在你创建主题分支之后,`master` 分支向前移动了,你获得的结果就会显得有些不对。 -这是因为 Git 会直接将该主题分支与 `master` 分支的最新提交快照进行比较。 -比如说你在 `master` 分支中向某个文件添加了一行内容,那么直接比对最新快照的结果看上去就像是你在主题分支中将这一行删除了。 +如果在你创建特性分支之后,`master` 分支向前移动了,你获得的结果就会显得有些不对。 +这是因为 Git 会直接将该特性分支与 `master` 分支的最新提交快照进行比较。 +比如说你在 `master` 分支中向某个文件添加了一行内容,那么直接比对最新快照的结果看上去就像是你在特性分支中将这一行删除了。 -如果 `master` 分支是你的主题分支的直接祖先,其实是没有任何问题的;但是一旦两个分支的历史产生了分叉,上述比对产生的 diff 看上去就像是将主题分支中所有的新东西加入,并且将 `master` 分支所独有的东西删除。 +如果 `master` 分支是你的特性分支的直接祖先,其实是没有任何问题的;但是一旦两个分支的历史产生了分叉,上述比对产生的 diff 看上去就像是将特性分支中所有的新东西加入,并且将 `master` 分支所独有的东西删除。 而你真正想要检查的东西,实际上仅仅是特性分支所添加的更改——也就是该分支与 master 分支合并所要引入的工作。 -要达到此目的,你需要让 Git 对主题分支上最新的提交与该分支与 master 分支的首个公共祖先进行比较。 +要达到此目的,你需要让 Git 对特性分支上最新的提交与该分支与 master 分支的首个公共祖先进行比较。 从技术的角度讲,你可以以手工的方式找出公共祖先,并对其显式运行 diff 命令: @@ -283,13 +283,13 @@ $ git diff 36c7db $ git diff master...contrib ----- -该命令仅会显示自当前主题分支与 master 分支的共同祖先起,该分支中的工作。 +该命令仅会显示自当前特性分支与 master 分支的共同祖先起,该分支中的工作。 这个语法很有用,应该牢记。 ==== 将贡献的工作整合进来 (((integrating work))) -当主题分支中所有的工作都已经准备好整合进入更靠近主线的分支时,接下来的问题就是如何进行整合了。 +当特性分支中所有的工作都已经准备好整合进入更靠近主线的分支时,接下来的问题就是如何进行整合了。 此外,还有一个问题是,你想使用怎样的总体工作流来维护你的项目? 你可能的选择有很多,我们会介绍其中的一部分。 @@ -298,31 +298,31 @@ $ git diff master...contrib (((workflows, merging))) 一种非常简单的工作流会直接将工作合并进入 `master` 分支。 在这种情况下,`master` 分支包含的代码是基本稳定的。 -当你完成某个主题分支的工作,或审核通过了其他人所贡献的工作时,你会将其合并进入 master 分支,之后将主题分支删除,如此反复。 +当你完成某个特性分支的工作,或审核通过了其他人所贡献的工作时,你会将其合并进入 master 分支,之后将特性分支删除,如此反复。 如果我们的版本库包含类似 <> 的两个名称分别为 `ruby_client` 和 `php_client` 的分支,并且我们先合并 `ruby_client` 分支,之后合并 `php_client` 分支,那么提交历史最后会变成 <> 的样子。 [[merwf_a]] -.包含若干主题分支的提交历史 -image::images/merging-workflows-1.png[包含若干主题分支的提交历史] +.包含若干特性分支的提交历史 +image::images/merging-workflows-1.png[包含若干特性分支的提交历史] [[merwf_b]] -.合并主题分支之后 -image::images/merging-workflows-2.png[合并主题分支之后] +.合并特性分支之后 +image::images/merging-workflows-2.png[合并特性分支之后] 这也许是最简单的工作流了,但是当项目更大,或更稳定,你对自己所引入的工作更加在意时,它可能会带来问题。 如果你的项目非常重要,你可能会使用两阶段合并循环。 在这种情况下,你会维护两个长期分支,分别是 `master` 和 `develop`,`master` 分支只会在一个非常稳定的版本发布时才会更新,而所有的新代码会首先整合进入 `develop` 分支。 你定期将这两个分支推送到公共版本库中。 -每次需要合并新的主题分支时(<>),你都应该合并进入 `develop` 分支(<>);当打标签发布的时候,你会将 `master` 分支快进到已经稳定的 `develop` 分支(<>)。 +每次需要合并新的特性分支时(<>),你都应该合并进入 `develop` 分支(<>);当打标签发布的时候,你会将 `master` 分支快进到已经稳定的 `develop` 分支(<>)。 [[merwf_c]] -.合并主题分支前 -image::images/merging-workflows-3.png[合并主题分支前] +.合并特性分支前 +image::images/merging-workflows-3.png[合并特性分支前] [[merwf_d]] -.合并主题分支后 -image::images/merging-workflows-4.png[合并主题分支后] +.合并特性分支后 +image::images/merging-workflows-4.png[合并特性分支后] [[merwf_e]] .一次发布之后 @@ -336,22 +336,22 @@ image::images/merging-workflows-5.png[一次发布之后] (((workflows, "merging (large)"))) Git 项目包含四个长期分支:`master`,`next`,用于新工作的 `pu`(proposed updates)和用于维护和 backport 的 `maint`分支。 -贡献者的新工作会以类似之前所介绍的方式收入主题分支中(见 <>)。 -之后对主题分支进行测试评估,检查其是否已经能够合并,或者仍需要更多工作。 -安全的主题分支会被合并入 `next` 分支,之后该分支会被推送使得所有人都可以尝试整合到一起的主题。 +贡献者的新工作会以类似之前所介绍的方式收入特性分支中(见 <>)。 +之后对特性分支进行测试评估,检查其是否已经能够合并,或者仍需要更多工作。 +安全的特性分支会被合并入 `next` 分支,之后该分支会被推送使得所有人都可以尝试整合到一起的特性。 [[merwf_f]] -.管理复杂的一系列并行接收贡献的主题分支 -image::images/large-merges-1.png[管理复杂的一系列并行接收贡献的主题分支] +.管理复杂的一系列并行接收贡献的特性分支 +image::images/large-merges-1.png[管理复杂的一系列并行接收贡献的特性分支] -如果主题分支需要更多工作,它则会被并入 `pu` 分支。 +如果特性分支需要更多工作,它则会被并入 `pu` 分支。 当它们完全稳定之后,会被再次并入 `master` 分支。 这意味着 `master` 分支始终在进行快进,`next` 分支偶尔会被变基,而 `pu` 分支的变基比较频繁: -.将贡献过来的主题分支并入长期整合分支 -image::images/large-merges-2.png[将贡献过来的主题分支并入长期整合分支] +.将贡献过来的特性分支并入长期整合分支 +image::images/large-merges-2.png[将贡献过来的特性分支并入长期整合分支] -当主题分支最终被并入 `master` 分支后,便会被从版本库中删除掉。 +当特性分支最终被并入 `master` 分支后,便会被从版本库中删除掉。 Git 项目还有一个从上一次发布中派生出来的 `maint` 分支来提供 backport 过来的补丁以供发布维护更新。 因此,当你克隆 Git 的版本库之后,就会有四个可分别评估该项目开发的不同阶段的可签出的分支,签出哪个分支,取决于你需要多新的版本,或者你想要如何进行贡献;对于维护者来说,这套结构化的工作流能帮助它们审查新的贡献。 @@ -360,14 +360,14 @@ Git 项目还有一个从上一次发布中派生出来的 `maint` 分支来提 (((workflows, rebasing and cherry-picking))) 为了保持线性的提交历史,有些维护者更喜欢在 master 分支上对贡献过来的工作进行变基和拣选,而不是直接将其合并。 -当你完成了某个主题分支中的工作,并且决定要将其整合的时候,你可以在该分支中运行变基命令,在当前 master 分支(或者是 `develop` 等分支)的基础上重新构造修改。 +当你完成了某个特性分支中的工作,并且决定要将其整合的时候,你可以在该分支中运行变基命令,在当前 master 分支(或者是 `develop` 等分支)的基础上重新构造修改。 如果结果理想的话,你可以快进 `master` 分支,最后得到一个线性的项目提交历史。 (((git commands, cherry-pick))) 另一种将引入的工作转移到其他分支的方法是拣选。 Git 中的拣选类似于对特定的某次提交的变基。 它会提取该提交的补丁,之后尝试将其重新应用到当前分支上。 -这种方式在你只想引入主题分支中的某个提交,或者主题分支中只有一个提交,而你不想运行变基时很有用。 +这种方式在你只想引入特性分支中的某个提交,或者特性分支中只有一个提交,而你不想运行变基时很有用。 假如你的工程提交历史类似: .拣选之前的示例历史 @@ -386,15 +386,15 @@ Finished one cherry-pick. 这样会拉取和 `e43a6` 相同的更改,但是因为应用的日期不同,你会得到一个新的提交 SHA-1 值。 现在你的历史会变成这样: -.拣选主题分支中的一个提交后的历史 -image::images/rebasing-2.png[拣选主题分支中的一个提交后的历史] +.拣选特性分支中的一个提交后的历史 +image::images/rebasing-2.png[拣选特性分支中的一个提交后的历史] -现在你可以删除这个主题分支,并丢弃不想拉入的提交。 +现在你可以删除这个特性分支,并丢弃不想拉入的提交。 ===== Rerere (((git commands, rerere)))(((rerere))) -如果你在进行大量的合并或变基,或维护一个长期的主题分支,Git 提供的一个叫做“rerere”的功能会有一些帮助。 +如果你在进行大量的合并或变基,或维护一个长期的特性分支,Git 提供的一个叫做“rerere”的功能会有一些帮助。 Rerere 是“重用记录下的解决方案(reuse recorded resolution)”的意思——它是手动冲突解决的一种快捷方式。 当启用 rerere 时,Git 将会维护一些成功合并之前和之后的镜像,当 Git 发现和之前已经修复过的类似的冲突时,便会使用之前的修复方案,而不需要你的干预。 From 2e34d407af7e6acc49f8dcb39ab7191075651fbd Mon Sep 17 00:00:00 2001 From: secondwtq Date: Fri, 7 Aug 2015 23:19:40 +0800 Subject: [PATCH 5/6] Reviewed by @morefreeze. --- book/05-distributed-git/sections/maintaining.asc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/book/05-distributed-git/sections/maintaining.asc b/book/05-distributed-git/sections/maintaining.asc index 437b805d..e044e789 100644 --- a/book/05-distributed-git/sections/maintaining.asc +++ b/book/05-distributed-git/sections/maintaining.asc @@ -53,7 +53,7 @@ $ git apply /tmp/patch-ruby-client.patch 总体来看,`git apply` 命令要比 `patch` 谨慎得多。 并且,它不会为你创建提交——在运行之后,你需要手动暂存并提交补丁所引入的更改。 -在实际应用补丁前,你还可以使用 git apply 来检查补丁是否可以整洁地应用——即对补丁运行 `git apply --check` 命令: +在实际应用补丁前,你还可以使用 git apply 来检查补丁是否可以顺畅地应用——即对补丁运行 `git apply --check` 命令: [source,console] ----- @@ -62,7 +62,7 @@ error: patch failed: ticgit.gemspec:1 error: ticgit.gemspec: patch does not apply ----- -如果没有产生输出,则该补丁可以整洁地应用。 +如果没有产生输出,则该补丁可以顺畅地应用。 如果检查失败了,该命令还会以一个非零的状态退出,所以需要时你也可以在脚本中使用它。 [[_git_am]] @@ -100,7 +100,7 @@ $ git am 0001-limit-log-function.patch Applying: add limit to log function ----- -你会看到补丁被优雅整洁地应用,新的提交也会被创建好。 +你会看到补丁被顺畅地应用,新的提交也会被创建好。 其中的作者信息来自于电子邮件头部的 `From` 和 `Date` 字段,提交消息则取自 `Subject` 和邮件正文中补丁之前的内容。 比如,应用上面那个 mbox 示例后生成的提交是这样的: @@ -120,7 +120,7 @@ CommitDate: Thu Apr 9 09:19:06 2009 -0700 其中 `Commit` 信息表示的是应用补丁的人和应用补丁的时间。 `Author` 信息则表示补丁的原作者和原本的创建时间。 -但是,有时候补丁可能无法整洁地应用。 +但是,有时候补丁可能无法顺畅地应用。 这也许是因为你的主分支和创建补丁的分支相差较多,也有可能是因为这个补丁依赖于其他你尚未应用的补丁。 这种情况下,`git am` 进程将会报错并且询问你要做什么: From c56b6b8b22b471a3a3194d37c7914efb95fe62cf Mon Sep 17 00:00:00 2001 From: secondwtq Date: Tue, 11 Aug 2015 15:34:26 +0800 Subject: [PATCH 6/6] Reviewed by @archersmind. --- .../sections/maintaining.asc | 88 +++++++++---------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/book/05-distributed-git/sections/maintaining.asc b/book/05-distributed-git/sections/maintaining.asc index e044e789..e886b7ab 100644 --- a/book/05-distributed-git/sections/maintaining.asc +++ b/book/05-distributed-git/sections/maintaining.asc @@ -3,16 +3,16 @@ (((maintaining a project))) 除了如何有效地参与一个项目的贡献之外,你可能也需要了解如何维护项目。 这包含接受并应用别人使用 `format-patch` 生成并通过电子邮件发送过来的补丁,或对项目添加的远程版本库分支中的更改进行整合。 -但是无论是自己管理版本库,还是想要提供验证、审核补丁的帮助,你都需要了解如何以一种对于其他贡献者来说最清晰,且对自己来说长期可持续的方式来接受工作。 +但无论是管理版本库,还是帮忙验证、审核收到的补丁,都需要同其他贡献者约定某种长期可持续的工作方式。 ==== 在特性分支中工作 (((branches, topic))) -如果你想向项目中整合一些新东西,最好先在为此专门设立的一个临时分支——即特性分支中进行尝试。 +如果你想向项目中整合一些新东西,最好将这些尝试局限在特性分支——一种通常用来尝试新东西的临时分支中。 这样便于单独调整补丁,如果遇到无法正常工作的情况,可以先不用管,等到有时间的时候再来处理。 如果你基于你所尝试进行工作的特性为分支创建一个简单的名字,比如 `ruby_client` 或者具有类似描述性的其他名字,这样即使你必须暂时抛弃它,以后回来时也不会忘记。 项目的维护者一般还会为这些分支附带命名空间,比如 `sc/ruby_client`(其中 `sc` 是贡献该项工作的人名称的简写)。 -正如你所想到的,可以以如下的方式基于 master 分支建立特性分支: +你应该记得,可以使用如下方式基于 master 分支建立特性分支: [source,console] ----- @@ -53,7 +53,7 @@ $ git apply /tmp/patch-ruby-client.patch 总体来看,`git apply` 命令要比 `patch` 谨慎得多。 并且,它不会为你创建提交——在运行之后,你需要手动暂存并提交补丁所引入的更改。 -在实际应用补丁前,你还可以使用 git apply 来检查补丁是否可以顺畅地应用——即对补丁运行 `git apply --check` 命令: +在实际应用补丁前,你还可以使用 git apply 来检查补丁是否可以顺利应用——即对补丁运行 `git apply --check` 命令: [source,console] ----- @@ -62,14 +62,14 @@ error: patch failed: ticgit.gemspec:1 error: ticgit.gemspec: patch does not apply ----- -如果没有产生输出,则该补丁可以顺畅地应用。 +如果没有产生输出,则该补丁可以顺利应用。 如果检查失败了,该命令还会以一个非零的状态退出,所以需要时你也可以在脚本中使用它。 [[_git_am]] ===== 使用 `am` 命令应用补丁 (((git commands, am))) -如果补丁的贡献者也是一个 Git 用户,并且其有轻松使用 `format-patch` 命令生成补丁的水平,那么因为补丁中包含了作者信息和提交消息,你应用补丁的工作会变得更加轻松。 +如果补丁的贡献者也是一个 Git 用户,并且其能熟练使用 `format-patch` 命令来生成补丁,这样的话你的工作会变得更加轻松,因为这种补丁中包含了作者信息和提交信息供你参考。 如果可能的话,请鼓励贡献者使用 `format-patch` 而不是 `diff` 来为你生成补丁。 而只有对老式的补丁,你才必须使用 `git apply` 命令。 @@ -87,12 +87,12 @@ Subject: [PATCH 1/2] add limit to log function Limit log functionality to the first 20 ----- -这其实就是你前面看到的 format-patch 命令的输出的开始几行。 +这其实就是你前面看到的 format-patch 命令输出的开始几行。 而同时它也是有效的 mbox 电子邮件格式。 如果有人使用 git send-email 命令将补丁以电子邮件的形式发送给你,你便可以将它下载为 mbox 格式的文件,之后将 git am 命令指向该文件,它会应用其中包含的所有补丁。 如果你所使用的邮件客户端能够同时将多封邮件保存为 mbox 格式的文件,你甚至能够将一系列补丁打包为单个 mbox 文件,并利用 `git am` 命令将它们一次性全部应用。 -另外,如果贡献者将 `format-patch` 生成的补丁文件上传到类似 Request Ticket 的任务处理系统,你可以先将其保存到本地,之后运行 `git am` 来应用: +然而,如果贡献者将 `format-patch` 生成的补丁文件上传到类似 Request Ticket 的任务处理系统,你可以先将其保存到本地,之后通过 `git am` 来应用补丁: [source,console] ----- @@ -100,7 +100,7 @@ $ git am 0001-limit-log-function.patch Applying: add limit to log function ----- -你会看到补丁被顺畅地应用,新的提交也会被创建好。 +你会看到补丁被顺利地应用,并且为你自动创建了一个新的提交。 其中的作者信息来自于电子邮件头部的 `From` 和 `Date` 字段,提交消息则取自 `Subject` 和邮件正文中补丁之前的内容。 比如,应用上面那个 mbox 示例后生成的提交是这样的: @@ -120,7 +120,7 @@ CommitDate: Thu Apr 9 09:19:06 2009 -0700 其中 `Commit` 信息表示的是应用补丁的人和应用补丁的时间。 `Author` 信息则表示补丁的原作者和原本的创建时间。 -但是,有时候补丁可能无法顺畅地应用。 +但是,有时候无法顺利地应用补丁。 这也许是因为你的主分支和创建补丁的分支相差较多,也有可能是因为这个补丁依赖于其他你尚未应用的补丁。 这种情况下,`git am` 进程将会报错并且询问你要做什么: @@ -165,7 +165,7 @@ No changes -- Patch already applied. 比如上面这种情况,我在之前已经应用过同样的补丁。 如果没有 `-3` 选项的话,这看起来就像是存在一个冲突。 -如果你正在利用一个 mbox 文件应用多个补丁,也可以在交互模式下运行 `am` 命令,这样在每个补丁之前,它会停住询问你是否要应用: +如果你正在利用一个 mbox 文件应用多个补丁,也可以在交互模式下运行 `am` 命令,这样在每个补丁之前,它会停住询问你是否要应用该补丁: [source,console] ----- @@ -199,9 +199,9 @@ $ git checkout -b rubyclient jessica/ruby-client 如果她再次发邮件说另一个分支中包含另一个优秀功能,因为之前已经设置好远程分支了,你就可以直接进行抓取及检出操作。 这对于与他人长期合作工作来说很有用。 -而对于提交补丁频率较小的贡献者,相对于每个人维护自己的服务器,不断增删远程的做法,使用电子邮件来接收可能会比较省时。 -况且你也不会想要加入数百个只提供一两个补丁的远程。 -然而,脚本和托管服务在一定程度上可以简化这些工作——这很大依赖于你和你的贡献者开发的方式。 +而对于提交补丁频率较小的贡献者,相对于每个人维护自己的服务器,不断增删远程分支的做法,使用电子邮件来接收可能会比较省时。 +况且你也不会想要加入数百个只提供一两个补丁的远程分支。 +然而,脚本和托管服务在一定程度上可以简化这些工作——这很大程度上依赖于你和你的贡献者开发的方式。 这种方式的另一种优点是你可以同时得到提交历史。 虽然代码合并中可能会出现问题,但是你能获知他人的工作是基于你的历史中的具体哪一个位置;所以Git 会默认进行三方合并,不需要提供 `-3` 选项,你也不需要担心补丁是基于某个你无法访问的提交生成的。 @@ -221,9 +221,9 @@ Merge made by recursive. ==== 确定引入了哪些东西 (((branches, diffing))) -你已经有了一个包含其他人贡献的工作的特性分支。 +你已经有了一个包含其他人贡献的特性分支。 现在你可以决定如何处理它们了。 -本节回顾了若干命令,以便于你检查若将其合并进入主要分支所引入的更改。 +本节回顾了若干命令,以便于你检查若将其合并入主分支所引入的更改。 一般来说,你应该对该分支中所有 master 分支尚未包含的提交进行检查。 通过在分支名称前加入 `--not` 选项,你可以排除 master 分支中的提交。 @@ -246,7 +246,7 @@ Date: Mon Oct 22 19:38:36 2008 -0700 updated the gemspec to hopefully work better ----- -如果要查看每次提交所引入的具体修改,你应该记得可以给 `git log` 命令传递 `-p` 选项,这样它会在每次提交后面附加对应的 diff。 +如果要查看每次提交所引入的具体修改,你应该记得可以给 `git log` 命令传递 `-p` 选项,这样它会在每次提交后面附加对应的差异(diff)。 而要查看将该特性分支与另一个分支合并的完整 diff,你可能需要使用一个有些奇怪的技巧来得到正确的结果。 你可能会想到这种方式: @@ -291,7 +291,7 @@ $ git diff master...contrib (((integrating work))) 当特性分支中所有的工作都已经准备好整合进入更靠近主线的分支时,接下来的问题就是如何进行整合了。 此外,还有一个问题是,你想使用怎样的总体工作流来维护你的项目? -你可能的选择有很多,我们会介绍其中的一部分。 +你的选择有很多,我们会介绍其中的一部分。 ===== 合并工作流 @@ -302,12 +302,12 @@ $ git diff master...contrib 如果我们的版本库包含类似 <> 的两个名称分别为 `ruby_client` 和 `php_client` 的分支,并且我们先合并 `ruby_client` 分支,之后合并 `php_client` 分支,那么提交历史最后会变成 <> 的样子。 [[merwf_a]] -.包含若干特性分支的提交历史 -image::images/merging-workflows-1.png[包含若干特性分支的提交历史] +.包含若干特性分支的提交历史。 +image::images/merging-workflows-1.png[包含若干特性分支的提交历史。] [[merwf_b]] -.合并特性分支之后 -image::images/merging-workflows-2.png[合并特性分支之后] +.合并特性分支之后。 +image::images/merging-workflows-2.png[合并特性分支之后。] 这也许是最简单的工作流了,但是当项目更大,或更稳定,你对自己所引入的工作更加在意时,它可能会带来问题。 @@ -317,16 +317,16 @@ image::images/merging-workflows-2.png[合并特性分支之后] 每次需要合并新的特性分支时(<>),你都应该合并进入 `develop` 分支(<>);当打标签发布的时候,你会将 `master` 分支快进到已经稳定的 `develop` 分支(<>)。 [[merwf_c]] -.合并特性分支前 -image::images/merging-workflows-3.png[合并特性分支前] +.合并特性分支前。 +image::images/merging-workflows-3.png[合并特性分支前。] [[merwf_d]] -.合并特性分支后 -image::images/merging-workflows-4.png[合并特性分支后] +.合并特性分支后。 +image::images/merging-workflows-4.png[合并特性分支后。] [[merwf_e]] -.一次发布之后 -image::images/merging-workflows-5.png[一次发布之后] +.一次发布之后。 +image::images/merging-workflows-5.png[一次发布之后。] 这样当人们克隆你项目的版本库后,既可以检出 master 分支以构建最新的稳定版本并保持更新,也可以检出包含更多新东西的 develop 分支。 你也可以扩展这个概念,维护一个将所有工作合并到一起的整合分支。 @@ -335,25 +335,25 @@ image::images/merging-workflows-5.png[一次发布之后] ===== 大项目合并工作流 (((workflows, "merging (large)"))) -Git 项目包含四个长期分支:`master`,`next`,用于新工作的 `pu`(proposed updates)和用于维护和 backport 的 `maint`分支。 +Git 项目包含四个长期分支:`master`、`next`,用于新工作的 `pu`(proposed updates)和用于维护和向后移植的 `maint` 分支。 贡献者的新工作会以类似之前所介绍的方式收入特性分支中(见 <>)。 之后对特性分支进行测试评估,检查其是否已经能够合并,或者仍需要更多工作。 安全的特性分支会被合并入 `next` 分支,之后该分支会被推送使得所有人都可以尝试整合到一起的特性。 [[merwf_f]] -.管理复杂的一系列并行接收贡献的特性分支 -image::images/large-merges-1.png[管理复杂的一系列并行接收贡献的特性分支] +.管理复杂的一系列接收贡献的平行特性分支。 +image::images/large-merges-1.png[管理复杂的一系列接收贡献的平行特性分支。] 如果特性分支需要更多工作,它则会被并入 `pu` 分支。 当它们完全稳定之后,会被再次并入 `master` 分支。 这意味着 `master` 分支始终在进行快进,`next` 分支偶尔会被变基,而 `pu` 分支的变基比较频繁: -.将贡献过来的特性分支并入长期整合分支 -image::images/large-merges-2.png[将贡献过来的特性分支并入长期整合分支] +.将贡献的特性分支并入长期整合分支。 +image::images/large-merges-2.png[将贡献的特性分支并入长期整合分支。] 当特性分支最终被并入 `master` 分支后,便会被从版本库中删除掉。 -Git 项目还有一个从上一次发布中派生出来的 `maint` 分支来提供 backport 过来的补丁以供发布维护更新。 -因此,当你克隆 Git 的版本库之后,就会有四个可分别评估该项目开发的不同阶段的可签出的分支,签出哪个分支,取决于你需要多新的版本,或者你想要如何进行贡献;对于维护者来说,这套结构化的工作流能帮助它们审查新的贡献。 +Git 项目还有一个从上一次发布中派生出来的 `maint` 分支来提供向后移植过来的补丁以供发布维护更新。 +因此,当你克隆 Git 的版本库之后,就会有四个可分别评估该项目开发的不同阶段的可检出的分支,签出哪个分支,取决于你需要多新的版本,或者你想要如何进行贡献;对于维护者来说,这套结构化的工作流能帮助它们审查新的贡献。 [[_rebase_cherry_pick]] ===== 变基与拣选工作流 @@ -368,10 +368,10 @@ Git 项目还有一个从上一次发布中派生出来的 `maint` 分支来提 Git 中的拣选类似于对特定的某次提交的变基。 它会提取该提交的补丁,之后尝试将其重新应用到当前分支上。 这种方式在你只想引入特性分支中的某个提交,或者特性分支中只有一个提交,而你不想运行变基时很有用。 -假如你的工程提交历史类似: +举个例子,假设你的工程提交历史类似: -.拣选之前的示例历史 -image::images/rebasing-1.png[拣选之前的示例历史] +.拣选之前的示例历史。 +image::images/rebasing-1.png[拣选之前的示例历史。] 如果你希望将提交 `e43a6` 拉取到 master 分支,你可以运行: @@ -386,8 +386,8 @@ Finished one cherry-pick. 这样会拉取和 `e43a6` 相同的更改,但是因为应用的日期不同,你会得到一个新的提交 SHA-1 值。 现在你的历史会变成这样: -.拣选特性分支中的一个提交后的历史 -image::images/rebasing-2.png[拣选特性分支中的一个提交后的历史] +.拣选特性分支中的一个提交后的历史。 +image::images/rebasing-2.png[拣选特性分支中的一个提交后的历史。] 现在你可以删除这个特性分支,并丢弃不想拉入的提交。 @@ -396,8 +396,8 @@ image::images/rebasing-2.png[拣选特性分支中的一个提交后的历史] (((git commands, rerere)))(((rerere))) 如果你在进行大量的合并或变基,或维护一个长期的特性分支,Git 提供的一个叫做“rerere”的功能会有一些帮助。 -Rerere 是“重用记录下的解决方案(reuse recorded resolution)”的意思——它是手动冲突解决的一种快捷方式。 -当启用 rerere 时,Git 将会维护一些成功合并之前和之后的镜像,当 Git 发现和之前已经修复过的类似的冲突时,便会使用之前的修复方案,而不需要你的干预。 +Rerere 是“重用已记录的冲突解决方案(reuse recorded resolution)”的意思——它是一种简化冲突解决的方法。 +当启用 rerere 时,Git 将会维护一些成功合并之前和之后的镜像,当 Git 发现之前已经修复过类似的冲突时,便会使用之前的修复方案,而不需要你的干预。 这个功能包含两个部分:一个配置选项和一个命令。 其中的配置选项是 `rerere.enabled`,把它放在全局配置中就可以了: @@ -410,7 +410,7 @@ $ git config --global rerere.enabled true 现在每当你进行一次需要解决冲突的合并时,解决方案都会被记录在缓存中,以备之后使用。 如果你需要和 rerere 的缓存交互,你可以使用 `git rerere` 命令。 -当单独调用它时,Git 会检查解决方案数据库,尝试寻找符合当前合并冲突的匹配并解决冲突(尽管当 `rerere.enabled` 被设置为 `true` 时会自动进行)。 +当单独调用它时,Git 会检查解决方案数据库,尝试寻找一个和当前任一冲突相关的匹配项并解决冲突(尽管当 `rerere.enabled` 被设置为 `true` 时会自动进行)。 它也有若干子命令,可用来查看记录项,删除特定解决方案和清除缓存全部内容等。我们将在 <<_rerere>> 中详细探讨。 [[_tagging_releases]] @@ -430,7 +430,7 @@ user: "Scott Chacon " ----- 如果你为标签签名了,你可能会遇到分发用来签名的 PGP 公钥的问题。 -Git 项目的维护者已经解决了这一问题:在版本库中以 blob 对象的形式包含他们的公钥,并添加一个直接指向该内容的标签。 +Git 项目的维护者已经解决了这一问题,其方法是在版本库中以 blob 对象的形式包含他们的公钥,并添加一个直接指向该内容的标签。 要完成这一任务,首先你可以通过运行 `gpg --list-keys` 找出你所想要的 key: [source,console]