《GitHub入门与实战》第六章

第六章 尝试Pull Request

  Pull Request 是社会化编程的象征。GitHub 创造的这一功能,可以说给开源开发世界带来了一场革命。不会用这个功能,就等于不会用 GitHub。
  不过,掌握 Pull Request 的难度确实较高,刚刚接触 GitHub 的人在发送 Pull Request 时,往往会遇到找不到对方的项目或者不知道该如何发送等问题。

6.1 Pull Request 的概要

什么是 Pull Request

  Pull Request 是自己修改源代码后,请求对方仓库采纳该修改时采取的一种行为。

Pull Request 在网络上也常常被简称为 PR。

Pull Request 的流程

  • 假设在使用 GitHub 上的一款开源软件

  在使用这款软件的过程中,偶然间发现了 BUG。为了继续使用软件,必须手动修复了这个 BUG。如果我们修改的这段代码能被该软件的开发仓库采纳,今后与我们同样使用这款软件的人就不会再遇到这个 BUG。为此,我们要第一时间发送 Pull Request。
  在 GitHub 上发送 Pull Request 后,接收方的仓库会创建一个附带源代码的 Issue,我们在这个 Issue 中记录详细内容。这就是 Pull Request。
  发送过去的 Pull Request 是否被采纳,要由接收方仓库的管理者进行判断。一般只要代码没有问题,对方都会采纳。如果有问题,我们会收到评论。
  只要 Pull Request 被顺利采纳,我们就会成为这个项目的 Contributor(贡献者),我们编写的这段代码也将被全世界的人使用。这正是社会化编程和开源开发的一大乐趣。

6.2 发送 Pull Request 前的准备

查看要修正的源代码

  请登录为各位准备的网站https://ituring.github.io/first-pr/。该网站的源代码已经在 GitHub 上公开 https://github.com/ituring/first-pr。各位请将自己的感想写入源代码,然后发送 Pull Request。
  这个网站通过 GitHub 的 GitHub Pages 功能发布。GitHub Pages 的网站的源代码位于仓库的 gh-pages 分支。访问仓库页面,就可以看到源代码。

Fork

  请访问仓库页面,点击 Fork 按钮创建自己的仓库。新建的仓库名 为“自己的账户名 /first-pr”。在这里我们命名为 hirocastest。

clone

  clone 仓库所需的访问信息显示在右侧的中央部分,将它复制下来,把这个仓库 clone 到当前的开发环境中。

$ git clone git@github.com:hirocastest/first-pr.git
Cloning into 'first-pr'...
remote: Counting objects: 14, done.
remote: Compressing objects: 100% (12/12), done.
remote: Total 14 (delta 2), reused 0 (delta 0)
Receiving objects: 100% (14/14), 24.05 KiB, done.
Resolving deltas: 100% (2/2), done.
$ cd first-pr

  first-pr 目录下会生成 Git 仓库。这个仓库与 GitHub 账户下的 first-pr 仓库状态相同。现在只要在这个仓库中修改源代码进行 push,GitHub 账户中的仓库就会被修改。

branch
为何要在特性分支中进行作业

  养成创建特性分支后再修改代码的好习惯。在 GitHub 上发送 Pull Request 时,一般都是发送特性分支。这样一来,Pull Request 就拥有了更明确的特性(主题)。让对方了解自己修改代码的意图,有助于提高代码审查的效率。

确认分支

  查看一下 clone 出的仓库的分支。

$ git branch -a
* gh-pages       ←当前分支
  remotes/origin/HEAD -> origin/gh-pages
  remotes/origin/gh-pages

  开头加了“remotes/origin/”的是 GitHub 端仓库的分支。现在手头的开发环境中只有 gh-pages 分支。
  网站中显示的 HTML 位于 /origin/gh-pages 分支。虽然通常情况下最新版代码都位于 master 分支,但由于本次使用了 GitHub Pages,所以最新代码位于 gh-pages 分支。

创建特性分支

  创建一个名为 work 的分支,用来发送 Pull Request。这个 work 分支就是这次的特性分支。现在创建 work 分支并自动切换。

$ git checkout -b work gh-pages
Switched to a new branch 'work'

  确认是否切换到了 work 分支下。

$ git branch -a
  gh-pages
* work  ←当前分支
  remotes/origin/HEAD -> origin/gh-pages
  remotes/origin/gh-pages

  查看文件列表,我们可以看到网站中显示的 index.html 文件。

添加代码

  用编辑器打开 index.html 文件,以 HTML 形式添加感想。请自由添加感想并用 p 标签(Tag)括起,然后关闭编辑器。

<!-- 省略 -->
<p>请写明这是对本书内容的实践或描述对本书的感想并发送Pull Request。</p>
  ↓追加的行
<p class="impression"> 这本书读着很有趣。(@HIROCASTER)</p>
<!-- 省略 -->

提交修改

  用 git diff 命令查看修改是否已经正确进行。

$ git diff
diff --git a/index.html b/index.html
index f2034b3..91b8ecb 100644
--- a/index.html
+++ b/index.html
@@ -39,6 +39,8 @@
     
 <p>请写明这是对本书内容的实践或描述对本书的感想并发送Pull Request。</p>
     
 +<p class="impression"> 这本书读着很有趣。(@HIROCASTER)</p>
 +

  然后用浏览器打开,查看显示是否正确。然后确认添加的代码,提交至本地仓库。

$ git add index.html
$ git commit -m "Add my impression"
[work 243f28d] Add my impression
 1 file changed, 2 insertions(+)

创建远程分支

  要从 GitHub 发送 Pull Request,GitHub 端的仓库中必须有一个包含了修改后代码的分支。我们现在就来创建本地 work 分支的相应远程分支。

$ git push origin work
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 353 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
To git@github.com:hirocastest/first-pr.git
 * [new branch]      work -> work

  查看分支,/origin/work 已被创建。

$ git branch -a
     master
   * work
   remotes/origin/HEAD -> origin/master
   remotes/origin/gh-pages
   remotes/origin/work   ←已被创建

6.3 发送 Pull Request

  登录 GitHub 并切换至 work 分支。点击分支名左侧的绿色按钮,会跳转至查看分支间差别的页面。请在这里通过差别查看刚刚进行的更改是否正确。这里显示的东西就是本次 Pull Request 中包含的提交。
  确认想要发送的 Pull Request 的内容差别无误后,请点击 Create Pull Request。随后显示的表单用于填写请求对方采纳的评论。现在在评论栏中简明扼要地描述本次进行 Pull Request 的理由。
  确认没有问题后,点击 Send pull request 按钮。这样一来,Pull Request 的目标仓库中就会新建 Pull Request 和 Issue,同时该仓库的管理者会接到通知。
  至此,便顺利发送了第一次的 Pull Request。现在发送的源代码还没有被采纳,对方仓库不会有任何变化,所以网页也仍然是原样。
  如果想查看已发送 Pull Request 的状态,可以登录 GitHub,打开自己的控制面板查看 Pull Request 标签页。点击自己发送的 Pull Request 后会进入相应页面,管理者对 Pull Request 的评论会发到这里。这些在 Conversation 标签页中会按照时间顺序排列显示。只要代码没有问题,我们的 Pull Request 就会被采纳。

6.4 让 Pull Request 更加有效的方法

在开发过程中发送 Pull Request 进行讨论

  在软件的设计与实现过程中如果想发起讨论,Pull Request 是个非常好的契机。虽然可以像本次示例一样等代码完成后再发送 Pull Request,但在实际开发过程中,这样做很可能导致一个功能在完成后才收到设计或实现方面的指正,从而使代码需要大幅更改或重新实现。

  在 GitHub 上,我们可以尽早创建 Pull Request,从审查中获得反馈,在设计与实现方面思路一致,借此逐渐提高代码质量。这个方法在团队开发大型项目时尤其有效,已将 GitHub 运用到实际开发中的团队请务必试一试。
  这个方法执行起来很简单。只要在想发起讨论时发送 Pull Request 即可,不必等代码最终完成。即便某个功能尚在开发之中,只要在 Pull Request 中附带一段简单代码让大家有个大体印象,就能获取不少反馈。如果在 Pull Request 中再加入直观易懂的 Tasklist,就能很清楚反映出哪些功能已经实现,将来要做哪些工作。这不但能加快审查者的工作效率,还能作为自己的备忘录使用。
  从反馈中,不但能获得对自己所提议的新功能的支持和相关改善意见,有时还会被人指出自己没注意到的失误,或者准备编写的代码与其他成员重复等。这样一来,最终所完成的代码的质量一定会比原先高出许多。
  向发送过 Pull Request 的分支添加提交时,该提交会自动添加至已发送的 Pull Request 中。
  这一方法要求尽早发送 Pull Request,越早效果越明显。另外还有一件事要记住,就是千万不要在 Pull Request 中添加无关的修改。处理与主题无关的作业请另外创建分支,不然会让原本清晰的讨论变得一团糟。

明确标出“正在开发过程中”

  为防止开发到一半的 Pull Request 被误合并,一般都会在标题前加上 “ [ WIP ] ” 字样。WIP 是 Work In Progress 的简写,表示仍在开发过程中。等所有功能都实现之后,再消去这个前缀。
  这种在代码库中边讨论边开发的开发流程,要比以往在完成之后审查再反馈的流程高效得多。这个方法已经被应用到众多的软件开发现场。通过这一方法,开发者可以体验 GitHub 上独有的速度感。

不进行 Fork 直接从分支发送 Pull Request

  这个方法也值得在 GitHub 上进行开发的团队借鉴。一般说来,在 GitHub 上修改对方的代码时,需要先将仓库 Fork 到本地,然后再修改代码,发送 Pull Request。但是,如果用户对该仓库有编辑权限,则可以直接创建分支,从分支发送 Pull Request。利用这一设计,团队开发时不妨为每一名成员赋予编辑权限,免去 Fork 仓库的麻烦。这样,成员在有需要时就可以创建自己的分支,然后直接向 master 分支等发送 Pull Request。

6.5 仓库的维护

  Fork 或 clone 来的仓库,一旦放置不管就会离最新的源代码越来越远。如果不以最新的源代码为基础进行开发,劳神费力地编写代码也很可能是白费力气。
  通常来说 clone 来的仓库实际上与原仓库并没有任何关系。所以需要将原仓库设置为远程仓库,从该仓库获取(fetch)数据与本地仓库进行合并(merge),让本地仓库的源代码保持最新状态。

仓库的 Fork 与 clone

  将 octocat/Spoon-Knife 作为原仓库,在 GitHub 上进行 Fork,然后 clone。

$ git clone git@github.com:hirocastest/Spoon-Knife.git
Cloning into 'Spoon-Knife'...
remote: Counting objects: 24, done.
remote: Compressing objects: 100% (21/21), done.
remote: Total 24 (delta 7), reused 17 (delta 1)
Receiving objects: 100% (24/24), 74.36 KiB | 68 KiB/s, done.
Resolving deltas: 100% (7/7), done.
$ cd Spoon-Knife

给原仓库设置名称

  我们给原仓库设置 upstream 的名称,将其作为远程仓库。

git remote add upstream git://github.com/octocat/Spoon-Knife.git

今后,这个仓库将以 upstream 作为原仓库的标识符。这个环境下只需要设定一次。

获取最新数据

  下面从远程仓库实际获取(fetch)最新源代码,与自己仓库的分支进行合并。要让仓库维持最新状态,只需要重复这一工作即可。

$ git fetch upstream
From git://github.com/octocat/Spoon-Knife
 * [new branch]      master     -> upstream/master
$ git merge upstream/master
Already up-to-date.

  通过 git fetch 命令获取最新的数据,将 upstream/master 分支与当前分支(master)合并。虽然本次示例没有可以合并的内容,但这一操作确实可以将最新的源代码合并至当前分支。
  这样一来,当前分支(master)就获得了最新的源代码。在创建特性分支,编辑源代码之前,建议先将仓库更新到这一状态。一般情况下 master 分支都会获取最新代码,很少需要 Fork 的开发者亲自进行修正。

6.6 小结

  本文中简单学习了 Pull Request 的发送方法。想必已经发现,发送 Pull Request 时不单要敲一敲代码,还需要进行很多其他工作。
  在实际开发现场,Pull Request 多少都会与传统的习惯或规范有些冲突。但是,诸多团队的实践表明 Pull Request 确实有其显著的效果。作为一名投身于开源开发的程序员,应当尽早适应这一设计。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值