Github入门

发布于 2020-11-19  137 次阅读


Github是世界上最大的同性交友网站(?),同时也是最大的Git仓库托管商。我博客页面的最下方有我GitHub个人页面的URL(发出希望得到star的声音)。

使用GitHub团队协作(或者为其他项目做贡献)

Github有一个特有的操作--Fork

当你fork一个项目的时候,GitHub会为你clone一个这个项目的副本,并且该副本处于你的管辖范围内(也就是说你的GitHub profile里面会出现一个这个项目)。

下面通过Pro Git 这本书中的一个例子来了解GitHub的基础工作流程。

GitHub 设计了一个以合并请求为中心的特殊合作流程。 它基于我们在 Git 分支 的 特性分支 中提到的工作流程。 不管你是在一个紧密的团队中使用单独的版本库,或者使用许多的“Fork”来为一个由陌生人组成的国际企业或网络做出贡献,这种合作流程都能应付。

流程通常如下:

  1. 从 master 分支中创建一个新分支
  2. 提交一些修改来改进项目
  3. 将这个分支推送到 GitHub 上
  4. 创建一个合并请求
  5. 讨论,根据实际情况继续修改
  6. 项目的拥有者合并或关闭你的合并请求

这基本和 集成管理者工作流 中的一体化管理流程差不多,但是团队可以使用 GitHub 提供的网页工具替代电子邮件来交流和审查修改。

现在我们来看一个使用这个流程的例子。

创建合并请求

Tony 在找一些能在他的 Arduino 微控制器上运行的代码,他觉得 https://github.com/schacon/blink 中的代码不错。

他想要做出贡献的项目

Figure 90. 他想要做出贡献的项目

但是有个问题,这个代码中的的闪烁频率太高,我们觉得 3 秒一次比 1 秒一次更好一些。 所以让我们来改进这个程序,并将修改后的代码提交给这个项目。

首先,单击“Fork”按钮来获得这个项目的副本。 我们使用的用户名是“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 (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:[email protected]':
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
  1. 将派生出的副本克隆到本地
  2. 创建出名称有意义的分支
  3. 修改代码
  4. 检查改动
  5. 将改动提交到分支中
  6. 将新分支推送到 GitHub 的副本中

现在到 GitHub 上查看之前的项目副本,可以看到 GitHub 提示我们有新的分支,并且显示了一个大大的绿色按钮让我们可以检查我们的改动,并给源项目创建合并请求。

你也可以到“Branches”(分支)页面查看分支并创建合并请求: https://github.com/<用户名>/<项目名>/branches

合并请求按钮

Figure 91. 合并请求按钮

如果你点击了那个绿色按钮,就会看到一个新页面,在这里我们可以对改动填写标题和描述,让项目的拥有者考虑一下我们的改动。通常花点时间来编写个清晰有用的描述是个不错的主意,这能让作者明白为什么这个改动可以给他的项目带来好处,并且让他接受合并请求。

同时我们也能看到比主分支中所“领先”(ahead)的提交(在这个例子中只有一个)以及所有将会被合并的改动与之前代码的对比。

合并请求创建页面

Figure 92. 合并请求创建页面

当你单击了“Create pull request”(创建合并请求)的按钮后,这个项目的拥有者将会收到一条包含关改动和合并请求页面的链接的提醒。

NOTE虽然合并请求通常是在贡献者准备好在公开项目中提交改动的时候提交,但是也常被用在仍处于开发阶段的内部项目中。因为合并请求在提交后 依然可以加入新的改动 ,它也经常被用来建立团队合作的环境,而不只是在最终阶段使用。

利用合并请求

现在,项目的拥有者可以看到你的改动并合并它,拒绝它或是发表评论。在这里我们就当作他喜欢这个点子,但是他想要让灯熄灭的时间比点亮的时间稍长一些。

接下来可能会通过电子邮件进行互动,就像我们在 分布式 Git 中提到的工作流程那样,但是在 GitHub,这些都在线上完成。项目的拥有者可以审查修改,只需要单击某一行,就可以对其发表评论。

合并请求中对某一行的评论

Figure 93. 对合并请求内的特定一行发表评论

当维护者发表评论后,提交合并请求的人,以及所有正在关注(Watching)这个版本库的用户都会收到通知。我们待会儿将会告诉你如何修改这项设置。现在,如果 Tony 有开启电子邮件提醒,他将会收到这样的一封邮件:

电子邮件提醒

Figure 94. 通过电子邮件发送的评论提醒

每个人都能在合并请求中发表评论。在 合并请求讨论页面 里我们可以看到项目拥有者对某行代码发表评论,并在讨论区留下了一个普通评论。你可以看到被评论的代码也会在互动中显示出来。

合并请求讨论页面

Figure 95. 合并请求讨论页面

现在贡献者可以看到如何做才能让他们的改动被接受。幸运的是,这也是一件轻松的事情。如果你使用的是电子邮件进行交流,你需要再次对代码进行修改并重新提交至邮件列表,在 GitHub 上,你只需要再次提交到你的分支中并推送即可。

如果贡献者完成了以上的操作,项目的拥有者会再次收到提醒,当他们查看页面时,将会看到最新的改动。事实上,只要提交中有一行代码改动,GitHub 都会注意到并处理掉旧的变更集。

最终的合并请求

Figure 96. 最终的合并请求

如果你点开合并请求的“Files Changed”(更改的文件)选项卡,你将会看到“整理过的”差异表 —— 也就是这个分支被合并到主分支之后将会产生的所有改动,其实就是 git diff master...<分支名> 命令的执行结果。你可以浏览 确定引入了哪些东西 来了解更多关于差异表的知识。

你还会注意到,GitHub 会检查你的合并请求是否能直接合并,如果可以,将会提供一个按钮来进行合并操作。这个按钮只在你对版本库有写入权限并且可以进行简洁合并时才会显示。你点击后 GitHub 将做出一个“非快进式”(non-fast-forward)合并,即使这个合并 能够 快进式(fast-forward)合并,GitHub 依然会创建一个合并提交。

如果你需要,你还可以将分支拉取并在本地合并。如果你将这个分支合并到 master 分支中并推送到 GitHub,这个合并请求会被自动关闭。

这就是大部分 GitHub 项目使用的工作流程。创建分支,基于分支创建合并请求,进行讨论,根据需要继续在分支上进行修改,最终关闭或合并合并请求。

NOTE不必总是 Fork
有件很重要的事情:你可以在同一个版本库中不同的分支提交合并请求。如果你正在和某人实现某个功能,而且你对项目有写权限,你可以推送分支到版本库,并在 master 分支提交一个合并请求并在此进行代码审查和讨论的操作。不需要进行“Fork”。

与上游保持一致

当你进行拉取请求时,GitHub会进行检查,看你是否能够干净地进行合并。

拉取请求合并失败
若无法干净地合并则会出现这样的提示

这时我们有两种解决方案,第一种是将你的分支rebase到目标分支中去(在《Pro Git》中作者明确说明不推荐);第二种则是将目标分支merge到你的分支中去。

你先把对应的GitHub项目添加为一个新的远程仓库,并将其fetch下来,再进行merge操作,merge时你就可以手动进行合并处理操作。

下面就是用此方法的一个完整的解决过程。

$ git remote add upstream https://github.com/schacon/blink (1)

$ git fetch upstream (2)
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (3/3), done.
Unpacking objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
From https://github.com/schacon/blink
 * [new branch]      master     -> upstream/master

$ git merge upstream/master (3)
Auto-merging blink.ino
CONFLICT (content): Merge conflict in blink.ino
Automatic merge failed; fix conflicts and then commit the result.

$ vim blink.ino (4)
$ git add blink.ino
$ git commit
[slow-blink 3c8d735] Merge remote-tracking branch 'upstream/master' \
    into slower-blink

$ git push origin slow-blink (5)
Counting objects: 6, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 682 bytes | 0 bytes/s, done.
Total 6 (delta 2), reused 0 (delta 0)
To https://github.com/tonychacon/blink
   ef4725c..3c8d735  slower-blink -> slow-blink
  1. 将源版本库添加为一个远端,并命名为“upstream”(上游)
  2. 从远端抓取最新的内容
  3. 将该仓库的主分支的内容合并到你的分支中
  4. 修复产生的冲突
  5. 再推送回同一个分支

你完成了上面的步骤后,拉取请求将会自动更新并重新检查是否能干净的合并。

保持更新你的fork仓库

当你fork一个仓库后,相当于你已经有了一个独立于原仓库的自己的仓库。而当原仓库更新之后,GitHub会提醒你:

This branch is 5 commits behind progit:master.
(本分支落后 progit:master 5 个提交。)

如果你们是在团队协作开发一个软件,那么这个通知就是非常重要的。(当然如果你是在维护某一开源项目的其他衍生版本那大概这就没有太大用处了)。

虽然GitHub会对你进行通知,但是他并不会自动帮你进行更新,你需要手动完成更新:

$ git checkout master (1)
$ git pull https://github.com/progit/progit2.git (2)
$ git push origin master (3)

第一步:如果在别的分支则转到master分支去

第二步:从你fork来源的远程仓库pull

第三步:把更新push到origin(也就是在GitHub上面你fork出来的那个仓库)

这虽然可行,但每次都要输入从哪个 URL 抓取有点麻烦。你可以稍微设置一下来自动完成它:

$ git remote add progit https://github.com/progit/progit2.git (1)
$ git branch --set-upstream-to=progit/master master (2)
$ git config --local remote.pushDefault origin (3)
  1. 添加源仓库并取一个名字,这里叫它 progit
  2. 将 master 分支设置为从 progit 远端抓取
  3. 将默认推送仓库设置为 origin

搞定之后,工作流程为更加简单:

$ git checkout master (1)
$ git pull (2)
$ git push (3)
  1. 如果在另一个分支上,就切换到 master
  2. 从 progit 抓取更改后合并到 master
  3. 将 master 分支推送到 origin

以上就是(鸽了一个月)的GitHub使用小说明。


你好哇!欢迎来到雷公马碎碎念的地方:)