原文: Team Collaboration With GitHub
GitHub已经成为的一切开放源码软件的基石。开发人员喜欢它,基于它进行协作,并不断通过它开发令人惊叹的项目。除了代码托管,GitHub的主要吸引力是使用它作为一个协作开发工具。在本教程中,让我们来看看一些最有用的GitHub的功能,特别是使团队工作更有效率,更高生产力,非常重要的,好玩的那些功能!
有一件事我觉得非常有用的是,可以将GitHub的维基集成到项目的源代码主线上。
本教程假定您已经熟悉Git – 开放源码的分布式版本控制系统,由Linux的创世人Linus Torvalds在2005年创造的。如果您需要修改或查找有关Git,请访问我们以前的截屏教程,和一些文章。此外,你应该已经有一个Github上的帐户,并做了一些基本的功能,如创建一个存储库,并推送到GitHub上。如果没有,可以参照更多以前的教程。
在这个世界上的软件项目,不可避免的是,我们必须和一个团队一起工作来交付软件。在本教程中,我们将探索一些软件开发团队最常用的工具。这些工具包括:
如果你倾向于观看截屏操作视频,可以观看下面的截屏操作视频,而将本教程作为旁注。
有两种常用的方法在GitHub上建立团队合作:
如果您监管几个团队,想为每个团队设置不同的权限级别,或者为不同的代码仓库增加不同的成员组织(Organizations)将是最好的选择。任何GitHub用户帐户已经可以创建免费的开源代码库的组织。要创建一个组织,只需浏览您的组织设置页面:
要访问组织的团队页面,你可以简单地去页面http://github.com/organizations/[组织名称]/teams
来查看,或者访问页面https://github.com/organizations/[组织名称]/teams/new
来创建新的具备3种不同的权限级别的团队成员,如:
Pull Only:提取和合并另一个库或本地副本。只读访问权限。
Push和Pull:(1)以及更新远程代码仓库。读+写访问权限。
Pull, Push和管理:(1), (2),计费,建立团队,以及取消组织帐户。读+写+管理员权限
合作者主要用于读写访问个人账号所拥有的代码仓库。你可以通过https://github.com/[用户名]/[代码仓库名称]/settings/collaboration
来增加合作者(其他github个人账号)。
一旦做到这一点,每个合作者将会看到代码库页面的访问状态的变化。在拥有对代码库的写访问权限后,我们可以做一个git克隆,进行代码变更,用git拉取和归并远程存储库中的任何变化,并最终将本地的变化git推送到远程代码库:
Pull请求是一个非常棒的方式,通过fork一个新的代码库用来独立开发,并将变更贡献回原始代码库。在一天结束的时候,如果我们愿意,我们可以发送一个pull请求给代码库所有者,来合并我们的代码更改。Pull请求本身可以引起合作者之间的评论,包括代码质量,功能,甚至总体战略等。
现在让我们浏览一个pull请求的基本步骤。
GitHub有两种Pull请求方式:
下面的工作流程是在两个用户(原始代码库拥有者,和fork代码库拥有者)之间的fork-pull方式:
进入你想贡献修改的GitHub代码库,单击“Fork”按钮来创建自己的Github帐户上的代码库克隆:
这将在自己的帐户上创建一个该代码库的复制:
选择 SSH URL,那样它会自动使用你自己的SSH密钥,而不用每次在git pull或者push时询问你的用户名和密码。下一步,我们将克隆一份代码库到本地计算机:
$ git clone [ssh-url] [folder-name]
$ cd [folder-name]
一般情况下,每一个新的功能,我们将创建一个新的Git分支。这是一个很好的做法,因为在未来,如果经过一番讨论后我们需要进一步更新分支,Pull请求将被自动更新。让我们创建一个新的分支做一个非常简单的变化修改的readme.md文件:
$ git checkout -b [new-feature]
在为这个新功能增加文件后,我们只需要将修改提交到这个新分支上,然后切换回master分支:
$ git add .
$ git commit -m "information added in readme"
$ git checkout master
在这里,我们需要将新分支推送到远程代码仓库里。首先,我们需要检查这个新功能的分支名称以及其在远程仓库的别名,然后我们用git push [git-remote-alias] [branch-name]
推送这个变更。
$ git branch
* master
readme
$ git remote -v
origin [email protected]:[forked-repo-owner-username]/[repo-name].git (fetch)
origin [email protected]:[forked-repo-owner-username]/[repo-name].git (push)
$ git push origin readme
进入我们fork的代码库的GitHub页面,选择为这个新功能建立的分支,然后点击Pull Request
按钮:
提交Pull请求后,页面将直接跳转到原始库的Pull请求页面,我们将看到我们提交的Pull请求,作为一个新的问题,以及作为一个新的pull请求。
在经过讨论后,fork的代码库的作者可能想为这个新功能增加一些新的改动。在这种场景下,我们需要在本地计算机上checkout这个同样的分支,修改,提交,并推送回GitHub。当我们再次访问原代码库的pull请求页面的时候,会发现上次提交的Pull请求已经自动更新了。
如果你是原始代码库的所有者,你将有两种方式来合并收到的Pull请求。
直接在GitHub上合并:如果我们想直接在GitHub上进行合并,必须确保没有冲突。原始库的所有者可以通过简单地点击Merge Pull Request
按钮来进行合并:
在本地计算机上进行合并:另外一种情况,合并的时候可能会遇到冲突,点击上部的Info
图标,GitHub有非常清晰的指导,怎么从贡献者的分支上下拉代码变更到本地,合并并解决冲突。
在软件开发团队中有很多不同的代码分支模型。这里有两种非常常用的工作流程模型:
至于采用何种分支模型,取决于团队,项目,以及当时的状态。
在GitHub中,缺陷跟踪的中心是问题列表(Issues)。虽然问题列表主要是为了跟踪缺陷,但我们经常会用以下面的方式:
让我们来探讨问题列表的一下特点:
标签:具有不同颜色的类别,用来帮助过滤问题。
里程碑:附加在每一个问题上的日期分类,可用于确定哪些问题需要在下一个版本解决。 此外,由于每个问题都定有里程碑,每当一个问题解决,它会自动更新进度条。
搜索:搜索时能自动列出匹配的问题列表和里程碑。
分配:每个问题都能分配一个人负责进行解决,同时这也能让我们知道目前我们需要工作在什么上面。
自动关闭:包含Fixes/Fixed/Close/Closes/Closed #问题编号
的提交记录,将自动关闭该问题。
$ git add .
$ git commit -m "corrected url. fixes #2"
$ git push origin master
很显然,我们能将任务清单与代码提交紧密地耦合在一起。
提及或者引用:任何人在评论的时候在消息文本中包含#[问题编号]
,将自动生成该问题的链接,使得在讨论的过程中能非常容易地提及相关的问题。
有两个工具-图形和网络,让我们能洞察存储库的变化。Github图 提供了代码库的合作者,以及代码提交的直观展现,而Github网络可视化直观地展现了每一个贡献者和他们在所有分支上的代码提交。这些分析和图形非常强大,尤其是当在团队中工作。
图提供了详细的分析,包括:
记录卡:代码提交通常发生在每一天的什么时候?
GitHub网络(Network)是一个非常强大的工具,让我们能看到每一个贡献者的代码提交,以及这些提交与其他的提交有什么关联。当我们作为一个整体观看这个网络的可视化展现时,我们能看到每一个库,每一个分支,和每一个提交,
GitHub上的问题列表可以定义问题和里程碑,具有一定的项目管理能力。因为其他的某些功能或现有的工作流程,有些团队可能会更倾向于另外的工具。在本节中,我们将看到我们如何连接Github与其他流行的项目管理工具 – Trello和Pivotal Tracker。使用GitHub的服务钩子(hooks,我们可以将代码提交,问题和许多其他活动自动更新到任务中。对于任何软件开发团队,这种自动化的帮助,不仅节省了时间,而且还可以提高更新的。
Trello提供了一直简单而直观的方式管理任务。使用敏捷开发的方式, Trello任务卡能模拟简单,可视化的虚拟任务看版。作为实例, 当GitHub代码库收到一个Pull请求的时候,我们将利用GitHub的钩子(Hooks)服务,自动在Trello里生成一个任务卡。 让我们来看看实现这个功能的具体步骤:
首先注册一个Trello帐号,并建立一个新的Trello看版(Board)。
访问GitHub repository > Settings > Service Hooks > Trello
。
通过Install Note #1
描述的方法获得认证用的令牌(Token)。
通过Install Note #2
给的链接获得json格式的任务列表(list) id。BOARDID是我们访问网站看版的URL中的一部分https://trello.com/board/[BOARD-NAME]/[BOARDID]
。
回到GitHub的钩子服务,输入我们得到的list id
和token
,激活这个hook,可以通过Test Hook
按钮来测试每次收到新的Pull请求时,是否自动更新看版内容。
当下次收到新的Pull请求时,Trello看版就会自动生成一个Pull请求任务卡。
Pivotal Tracker是另外一个轻量级的项目管理工具,通过基于故事(story)的计划,让组员能对任何变化和进度进行回应,非常容易进行协作开发。 基于项目当前的进度,能生成可视化的图表来分析团队的开发速度,迭代burn-up图,以及当前发布的burn-down图。在下面的例子中, 我们通过关联一个GitHub代码提交(commit)到故事(story),自动地交付一个故事。
在Pivotal Tracker上新建一个项目,并生成一个需要交付的故事(story)。
访问Profile > API Token
,复制给定的API令牌(token)。
返回到GitHub页面访问repository > Settings > Service Hooks > Pivotal Tracker
,粘贴刚才复制的token
,激活,并保存设置。 这样我们就能够在提交代码的时候自动交付对应的故事(story)。
当我们最终提交代码修订的时候,按照格式git commit -m "message [delivers #tracker_id]"
将故事的id
添加到提交记录里。
$ git add .
$ git commit -m "Github and Pivotal Tracker hooks implemented [delivers #43903595]"
$ git push
现在,返回到Pivotal Tracker页面,我们将发现这个指定的故事被自动的发布出去了,附着对应的GitHub上代码提交的链接。
通过Trello和Pivotal Tracker实例,非常清楚的一点是我们能紧密地将我们的任务和代码提交绑定在一起。 当作为一个团队进行工作的时候,这将节省大量的时间,并且提高工作记录的精确度。非常好的消息是, 如果你已经使用了其他项目管理工具,例如Asana,Basecamp, 或者其他的,你能够用类似的方式添加hook。如果没有你目前正在使用的项目管理工具的hook, 自力更生自己做一个!
对于团队软件开发来说,持续集成(CI)是一个非常重要的部分。CI确保当开发人员提交代码改动的时候,将触发自动的构建(build),包括测试,用来快速地检测软件集成的错误。这将毫无疑问地减少集成过程中的错误,提高快速开发迭代的效率。在下面的例子里,我们将看到如何与GitHub一起使用Travis CI,自动检测错误,并且在所有测试通过后进行代码合并。
这里我们使用基于node.js服务器,基于[grunt.js][http://gruntjs.com/]作为构建工具的”Hello-World”应用,来设置Travis CI项目。下面是项目中的文件:
hello.js
文件是nodejs项目。我们有目的地漏写了一个分号,为了让这个文件不能通过grunt构建工具的lint(静态代码检测工具):
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World in Node!\n') // 这里没有分号,将不会通过linting
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
package.json
定义依赖的包:
{
"name": "hello-team",
"description": "A demo for github and travis ci for team collaboration",
"author": "name <[email protected]>",
"version": "0.0.1",
"devDependencies": {
"grunt": "~0.3.17"
},
"scripts": {
"test": "grunt travis --verbose"
}
}
为了简化起见,gruntjs构建工具的配置文件仅仅包含一个任务(linting):
module.exports = function(grunt) {
grunt.initConfig({
lint: {
files: ['hello.js']
}
});
grunt.registerTask('default', 'lint');
grunt.registerTask('travis', 'lint');
};
.travis.yml
是Travis的配置文件,确保Travis运行我们的测试:
language: node_js
node_js:
- 0.8
接着,用GitHub帐号登录到Travis,在repository
选项卡打开repository hook
:
如果上述步骤还不能触发构建,我们将不得不手工配置hook
,在Travis的profile栏复制token。
返回到GitHub代码库,使用复制的token设置Travis Hook:
第一次,我们必须手工做一次git push
来触发Travis构建,如果一切ok,我们可以访问http://travis-ci.org/[用户名]/[repo名]
查看构建的结果。
以前没有持续集成的Pull请求流程,步骤大概是(1)提交pull请求(2)合并(3)测试来看是否通过或者失败。带有持续集成hook的Pull请求流程将反转(2)和(3)步骤,Travis CI将向我们汇报每一个Pull请求的持续集成结果,让我们能够知道这个Pull请求是否足够好,并快速作出判断是否合并进主线。下面我们来看这是怎样做到的:
提交一个附带通过构建结果的Pull请求。Travis将做所有的一切,让我们在合并前就能知道这个合并是否足够好。
如果这个Pull请求使得构建失败,Travis同样会警告你:
如果我们点击红色的警告链接,浏览器将跳转到Travis页面,显示这次构建的详细信息。
因为自动的构建和及时地通知,Travis CI对团队来说非常有帮助,它能极大地缩短我们更正错误的周期。如果你使用另外一个非常有名的持续集成工具Jenkins,你能用相似的步骤设置hook服务。
对于每个提交(commit),GitHub有个干净的接口用来进行评论,甚至是对某行代码进行评论。在进行逐行代码评审的时候,针对单行代码提出评论和问题的功能就显得非常重要了。打开提交(commit)界面的顶部的检查框,就能显示行内评论。
下面探讨一些帮助我们进行代码评审,能快速显示不同提交之间差异的URL模式:
对比branch/tags/SHA1:使用URL模式https://github.com/[username]/[repo-name]/compare/[starting-SHA1]...[ending-SHA1]
。 可以用分支或者标签名代替SHA1
。
去除空格进行对比:增加?w=1
到对比的URL尾部。
Diff:增加.diff
到URL的后面能得到git diff
输出的纯文本信息。在写脚本的时候,这个功能非常有用。
Patch:增加.patch
到URL的后面能得到电子邮件补丁提交格式的git diff
输出的信息。
行链接:在查看文件时,点击任何行号,GitHub将会在URL后面增加一个#行号
,并且将该行的背景颜色置成黄色。这能干净利落地标识代码文件的某一行。我们同样能通过增加#开始行号-结束行号
来指定一个范围。这里是行链接和行范围链接的例子。
在这段,我们将探讨两种文档方法:
每个GitHub代码库都可以生成一个维基,这样非常方便地将代码和文档存放在同一个存储库中。要创建维基,访问主标题的维基选项卡,并设置创建页面的信息。其实维基也有自己的版本,并可以将数据复制到本地机器进行更新,甚至是离线访问。
有一件事我觉得非常有用的是可以将GitHub的维基整合到源代码中,这样我就不必维护两个独立的Git项目了。要做到这一点,我将Wiki作为git子模块增加到主分支上。如果您使用的是Travis CI或任何其他CI,必须确保构建工具会忽略wiki的子模块。在Travis的CI文件.travis.yml
中,添加以下内容:
git:
submodules: false
接着增加一个git子模块wiki
到主代码库中:
$ git submodule add [email protected]:[username]/[repo-name].wiki.git
Cloning into 'hello-team.wiki'...
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (6/6), done.
$ git add .
$ git commit -m "added wiki as submodule"
$ git push origin master
现在,维基就作为一个子模块显示在代码库项目中。
Hubot,总之,可以极大地增添了不少的乐趣记录,并通知小组讨论重要的提交。
Hubot是一个简单的聊天机器人,可以检索信息,或提供通知,每当GitHub有代码提交,问题,或活动时。在一个旨在减少,甚至完全消除会议的一个团队中,Hubot拥有所有团队成员的聊天接口,帮助您记录着每一个讨论。这当然促进灵活的工作时序,因为团队没有必要同时出席讨论。警告:Hubot是非常上瘾的!
有了这个,让我们开始在Heroku上设置Hubot,拥有Campfire聊天接口的聊天机器人![Heroku][]和Campfire,都有免费的版本供大家开始尝试。
我们将使用GitHub出品的支持Campfire的Hubot。如果你愿意,也可以使用其他如Skype,IRC,GTalk等聊天适配器。
根据Hubot维基上给的指示,部署Hubot到Heroku上。如果Heroku的应用程序的URL返回了一个Cannot GET /
,别惊慌,因为默认情况下不会得到任何返回。
从Hubot Campfire账号上,邀请你自己的账号,现在,登录你自己的Campfire账号,然后执行Hubot help
,你将得到所有Hubot支持的命令。
尝试几次,例如Hubot ship it
或者Hubot map me CERN
。
作为实例,我们将增加一个github提交脚本,以至于每次有一个新的提交,Hubot将在聊天室通知大家。将文件github-commits.coffee
放置到scripts
目录。
更新package.json
文件,根据每个脚本文件头的指示,加入新的依赖包。
使用下面命令再一次发布代码到Heroku:git push heroku master
浏览GitHub代码库,我们希望代码提交通知能显示在聊天室,在代码库设置下增加一个web hook
,对github-commits
脚本,webhook将是[HUBOT_URL]:[PORT]/hubot/gh-commits?room=[ROOM_ID]
下一次当代码库有新的代码提交,Hubot将在聊天室如此说:
检查其他Github相关的Hubot的脚本,或者如果您想自己写一个脚本,这里有一个很酷的教程!总之,Hubot可以极大地增添很多乐趣在文档记录、通知小组讨论代码库发生的重要提交,问题和活动。试试看吧!
关于和团队一起使用GitHub,最后要说明的是,这里有一些提高生产力的技巧:
提及(Mentions) – 在任何文本区域中,我们可以通过@用户名
提到另外一个GitHub用户,并且该用户将得到通知。
快捷键 – 按SHIFT + ?
可以查看Github上任何页面上的快捷键。
表情符号 – 通过使用表情符号,Github上的文本区域还支持插入的图标。来吧,与队友一起工作时有点情趣!
我们大多数人会认为使用Github只能为软件项目。毕竟,Github产生就是为了社交编程。但是,也有一些很酷的使用Github的库被用于非编码项目,和他们的合作和讨论同样非常棒。因为这些项目是开源的,任何人都可以作出贡献,这是快速修复错误,容易报告错误,与志同道合的人有效的合作。只是为了好玩,这里是其中的一些:
你能想象GitHub开发团队怎么认为这些项目?
“我们挖掘像这样一样使用GitHub的乐趣!”
那些都是在GitHub上积攒的协作化工具。大部分都是作为分析工具,或者用于和团队工作时节省时间的自动化工具。你有更多GitHub团队合作的技巧吗?让我们一起分享!