目前GitHub是规模最大的Git仓库的托管主机,它的中心服务器已容纳了数百万的开发者和项目,相当多的Git仓库都托管在GitHub,许多开源项目都在使用它,实现Git仓库,问题跟踪,代码浏览等功能,虽然GitHub不属于Git项目,但作为一个开发者,你迟早会遇见GitHub。
以下将介绍GitHub的一些细节,比如用户注册,账号挂你,创建和使用Git仓库,项目贡献的常用工作流,贡献接纳,以及GitHub编程接口和一些小技巧。
注意,由于时间的关系,GitHub的Web UI可能会发生变化,如果发生变化,请参考GitHub提供的最新指南。
6.1 账号注册和配置
首先需要注册一个免费账号,打开https://github.com页面,选择一个用户名,以及邮箱地址和密码,点击Sign up for GitHub按钮,
之后用户将看见一个账号升级的价格页面,当然这可获得一个更私密的环境,但目前并不需要,同时GitHub会向用户邮箱,发送一份验证邮件,以确认用户邮箱的有效性。注意,GitHub向免费用户开放了所有功能,但是免费用户只能创建公开项目,即所有人都可查看,如果升级成付费账号,则可创建私有项目。点击页面左上角的章鱼猫(Octocat,GitHub吉祥物),即可进入用户界面
ssh访问
此时用户已可使用http协议,连接Git仓库,并可使用用户名和密码,通过页面验证,如果只克隆一个公开项目,无需申请GitHub账号,有了GitHub账号之后,用户可以创建一个公开项目的副本,用于贡献代码。
如果需要ssh远程登录,则需配置一个公钥,点击页面右上角的账户设置链接,
选中左侧面板的SSH keys项,
点击Add an SSH key按钮,在Title文本框中设定公钥的名字,将用户的公钥文件(~/.ssh/id_rsa.pub)内容,复制到Key文本框中,再点击Add key按钮,则完成公钥生成,注意,在设定ssh公钥名称时,应设定一个有意义的名字,比如My Laptop或Work Account,方便将来取消公钥时,能直接获知公钥的用途。
变更用户信息
选中左侧面板的Profile项,再点击右侧的Upload new picture,可更改用户头像和信息。
GitHub基于邮件,发送贡献者的项目提交,如果用户需要使用多个邮箱地址,可告知GitHub,项目提交应发送到哪个邮箱,选中左侧面板的Emails项,配置不同用途的邮箱地址,
在Add email addresses标题栏中,输入邮箱地址,点击Add,可完成邮箱地址的添加,上图已添加了三个邮箱地址,首个邮箱已通过验证,并设定为主邮箱,这意味着所有的通知和邮件,都将发送到给邮箱,第二个邮箱已通过验证,如果需要设定为主邮箱,需点击右侧按钮,第三个邮箱未通过验证,还无法正常使用,如果GitHub在任意仓库的提交信息中,发现上述三个邮箱名,将会生成一个链接,直接指向用户的主页。
为了获得更好的安全性,用户还需配置双次验证(也是支付宝和微信的付款模式),如果用户密码不幸被盗,双次验证机制可减弱用户账号的未知风险,因此双次验证机制越来越流行,选中左侧面板的Security项,GitHub将询问用户,选择哪两种不同的验证方法,如果其中一种失效,黑客也无法访问用户账号,
点击Set up two-factor authentication按钮,将跳转到一个配置页面,用户可选择,使用手机app生成一个二级密码(带时限的一次性密码),或者在每次用户登录时,由GitHub使用短信,向用户发送一个登录密码。
6.2 项目贡献
完成用户账号的配置后,用户则可开始计划,为已有项目贡献代码。
项目副本
如果用户不拥有原始项目的推送权限,只能创建一个原始项目的副本,以方便贡献代码,而GitHub可为用户,创建一个原始项目的副本,并放置在用户空间,因此用户有权向该副本,推送数据。注意,在GitHub应用中,fork是指创建原始项目的副本,这与其他IT领域的含义稍有差别,在副本模式下,原始项目的维护者则无需烦恼,用户管理的诸多问题,普通用户可创建一个原始项目的副本,并推送自己的工作成果,再请求原始项目的维护者,接纳这些成果。
为了创建原始项目的副本,可点击页面右上角的Fork按钮
几秒之后,用户将跳转到原始项目的副本主页,
GitHub工作流
GitHub设计了一套特别的协作机制,重点在于,贡献者的请求接纳,这套机制不关心项目的规模,只是基于特性分支的运用,比如以下的工作流程,
- 贡献者创建原始项目的副本
- 贡献者基于master分支,创建一个特性分支
- 贡献者向特性分支,提交一些项目改进
- 贡献者将特性分支推送到GitHub
- 在GitHub上,贡献者向原始项目的维护者,发送一个接纳请求
- 贡献者发起后续改进的讨论
- 原始项目的维护者接纳或拒绝贡献者的提交
- 贡献者将原始项目的最新数据,同步到自己的副本
上述工作流类似于集中管理工作流,只是维护者与贡献者之间的通讯,未使用邮件。
创建接纳请求
Tony正在寻找,可运行在Arduino微控制器的代码,这时他在GitHub上,发现了一个类似的项目,https://github.com/schacon/blink,
但是该项目存在一个问题,LED闪烁的速度太快,需将延时从3秒改为1秒,因此Tony准备修改该项目,首先创建原始项目的副本,Tony的用户名为tonychacon,所以项目副本的地址为https://github.com/tonychacon/blink,之后将原始项目克隆到本地,再创建一个特性分支,完成代码修改,并推送到GitHub的项目副本,
$ git clone https://github.com/tonychacon/blink // #1
Cloning into 'blink'...
$ cd blink
$ git checkout -b slow-blink // #2
Switched to a new branch 'slow-blink'
$ sed -i '' 's/1000/3000/' blink.ino (macOS) // #3
# If you're on a Linux system, do this instead:
# $ sed -i 's/1000/3000/' blink.ino // #3
$ git diff --word-diff // #4
diff --git a/blink.ino b/blink.ino
index 15b9911..a6cc5a5 100644
--- a/blink.ino
+++ b/blink.ino
@@ -18,7 +18,7 @@ void setup() {
// the loop routine runs over and over again forever:
void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
[-delay(1000);-]{
+delay(3000);+} // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
[-delay(1000);-]{
+delay(3000);+} // wait for a second
}
$ git commit -a -m 'three seconds is better' // #5
[slow-blink 5ca509d] three seconds is better
1 file changed, 2 insertions(+), 2 deletions(-)
$ git push origin slow-blink // #6
Username for 'https://github.com': tonychacon
Password for 'https://tonychacon@github.com':
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 340 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To https://github.com/tonychacon/blink
* [new branch] slow-blink -> slow-blink
- 将原始项目克隆到本地
- 创建特性分支
- 修改代码
- 测试代码
- 将修改提交到特性分支
- 将特性分支推送到GitHub的项目副本
这时在GitHub的项目副本中,多了一条新分支slow-blink,同时出现了一个绿色的矩形按钮Compare & pull request,点击它,可向原始项目,发出接纳请求,
或者进入Branches页面(https://github.com/<用户名>/<项目名>/branches),点击Create pull request按钮,可生成一次接纳请求,
点击上述两个按钮后,将出现一个对话框,请求用户提供,接纳请求的标题和描述,简洁明了的标题和描述,有利于原始项目的维护者理解贡献者的意图,并快速给出响应,当贡献者点击按钮后,原始项目的维护者将收到一个建议修改的通知,并附带了贡献者的页面链接,值得注意,虽然公开项目通常需要使用接纳请求,但在私有项目的初始阶段,