GitHub多人协作简明教程

本文面向已经了解/熟悉git基本命令但是并不熟悉如何使用GitHub进行多人协作开发项目的同学。

为了简单起见,这里假设只有两个开发人员,HuanianLi 和 DaxiangLi。他们在GitHub上的地址和角色为:

HuanianLi将创建一个项目kaiba, 然后请DaxiangLi来帮忙做开发。 为了真实地进行场景演绎,我们将首先创建两个GitHub帐号。


1. 在GitHub上创建两个帐号(HuanianLi and DaxiangLi,这里以HuanianLi为例)

1.1 打开GitHub的主页: https://github.com/

1.2 点击右上角的Sign up

1.3 跳转到注册页面后,开始Create your personal account,按照要求输入Username, Email Address, Password, 例如:

GitHub多人协作简明教程

1.4 点击页面下方的"Create an account"按钮并按照后续提示完成注册。


2. 在Linux桌面上创建两个用户(huanianli and daxiangli), (这里以huanianli为例)

2.1 创建用户huanianli

[email protected]:~# useradd -d /home/huanianli -m -s /bin/bash -c "Huanian Li" huanianli

2.2 对用户huanianli的git进行设置 (这里直接编辑文件~/.gitconfig)

GitHub多人协作简明教程

[email protected]:~$ vim ~/.gitconfig
[email protected]:~$ cat -n ~/.gitconfig 
     1    [user]
     2        email = [email protected]
     3        name = Huanian Li
     4    [core]
     5        editor = vim
     6    [push]
     7        default = matching
[email protected]:~$ 
[email protected]:~$ git config -l
[email protected]
user.name=Huanian Li
core.editor=vim
push.default=matching
[email protected]:~$ 

GitHub多人协作简明教程

2.3 在huanianli的HOME目录下创建一个工作空间workspace

[email protected]:~$ cd ~
[email protected]:~$ mkdir workspace
[email protected]:~$ ls
workspace
[email protected]:~$ 

3. (Maintainer) HuanianLi在GitHub上创建一个项目kaiba

3.1 登录HuanianLi的GitHub空间,打开页面Repositories, e.g.

https://github.com/HuanianLi?tab=repositories

点击页面右边的New按钮, 进入创建一个新的代码仓库的页面。

GitHub多人协作简明教程

点击"Create repository"完成创建。

3.2 进入HuanianLi的Linux桌面,clone在3.1创建的项目kaiba

GitHub多人协作简明教程

[email protected]:~$ cd workspace
[email protected]:~/workspace$ git clone https://github.com/HuanianLi/kaiba.git
Cloning into 'kaiba'...
warning: You appear to have cloned an empty repository.
Checking connectivity... done.
[email protected]:~/workspace$ ls
kaiba
[email protected]:~/workspace$ cd kaiba
[email protected]:~/workspace/kaiba$ vi README.md
[email protected]:~/workspace/kaiba$ cat -n README.md
     1    kaiba: A sandbox project of Kaiba
[email protected]:~/workspace/kaiba$
[email protected]:~/workspace/kaiba$ git add README.md
[email protected]:~/workspace/kaiba$
[email protected]:~/workspace/kaiba$ git commit -m "Initialize the project by adding README.md"
[master (root-commit) c0bd2ed] Initialize the project by adding README.md
 1 file changed, 1 insertion(+)
 create mode 100644 README.md
[email protected]:~/workspace/kaiba$
[email protected]:~/workspace/kaiba$ git log
commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$
[email protected]:~/workspace/kaiba$ git branch
* master
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git push -u origin master
Username for 'https://github.com': HuanianLi
Password for 'https://[email protected]':
Counting objects: 3, done.
Writing objects: 100% (3/3), 273 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/HuanianLi/kaiba.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.
[email protected]:~/workspace/kaiba$

GitHub多人协作简明教程

在上面的操作中,关键的步骤是:

  • clone
git clone https://github.com/HuanianLi/kaiba.git
  • push
git push -u origin master

注意: 因为是第一次push, ‘-u’ 是必须的。

3.3 一旦完成git push之后,我们就可以浏览GitHub上的项目了

GitHub多人协作简明教程


4. (Contributor) DaxiangLi登录他的GitHub,  然后进入(Maintainer) HuanianLi的GitHub空间,fork项目kaiba

4.1 DaxiangLi登录他的GitHub

GitHub多人协作简明教程
 

4.2 进入(Maintainer) HuanianLi的GitHub空间, 点开项目kaiba

GitHub多人协作简明教程

注意: 目前的 Fork 为0。

4.3 fork项目kaiba, 直接点Fork按钮

GitHub多人协作简明教程

Fork 结束后, DaxiangLi的GitHub里就有了项目kaiba

GitHub多人协作简明教程


5. (Contributor)DaxiangLi贡献代码给项目kaiba

5.1 DaxiangLi在他的Linux桌面上clone代码

[email protected]:~/workspace$ git clone https://github.com/DaxiangLi/kaiba.git
Cloning into 'kaiba'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
Checking connectivity... done.

GitHub多人协作简明教程

两个问题:

  • DaxiangLi 能直接clone HuanianLi的GitHub里的代码吗?  A: 能。
  • DaxiangLi 能直接clone HuanianLi的GitHub里的代码,然后做修改后push回去吗? A: 不能。

5.2 DaxiangLi新建一个开发分支

[email protected]:~/workspace/kaiba$ git checkout -b dev
Switched to a new branch 'dev'

GitHub多人协作简明教程

其中, git checkout -b dev 等同于

1 git branch   dev
2 git checkout dev

5.3 把HuanianLi的项目添加到DaxiangLi的远程仓库

[email protected]:~/workspace/kaiba$ git remote add upstream https://github.com/HuanianLi/kaiba.git

GitHub多人协作简明教程

 5.4 将HuanianLi的分支取下来并更新到本地

[email protected]:~/workspace/kaiba$ git remote update
Fetching origin
Fetching upstream
From https://github.com/HuanianLi/kaiba
 * [new branch]      master     -> upstream/master

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ git fetch upstream master
From https://github.com/HuanianLi/kaiba
 * branch            master     -> FETCH_HEAD

GitHub多人协作简明教程

 5.5 合并HuanianLi的分支到本地(注意:这一步在第一次其实不需要)

[email protected]:~/workspace/kaiba$ git rebase upstream/master
Current branch dev is up to date.

GitHub多人协作简明教程

 5.6 DaxiangLi添加一个文件并提交commit

[email protected]:~/workspace/kaiba$ git add foo.py
[email protected]:~/workspace/kaiba$ git commit -m "DaxiangLi: Add foo.py"
[email protected]:~/workspace/kaiba$ git push -u origin dev 

GitHub多人协作简明教程

 5.7 进入DaxiangLi的GitHub, 提交一个PR

GitHub多人协作简明教程

Q: 什么是PR? (参考资料来源点这里

A: PR是Pull Request的缩写,是开发者使用GitHub进行协作的利器。简单来说,Pull Request是一种机制,让开发者告诉项目成员一个功能已经完成。一旦feature分支开发完毕,开发者使用GitHub账号提交一个Pull Request。它告诉所有参与者,他们需要审查代码,并将代码并入master分支。Pull Request不只是一个通知,还是一个专注于某个提议功能的讨论版面。Pull Request 需要两个不同的分支或是两个不同的仓库, 其工作原理大概是:

  1. 开发者在他们的本地仓库中为某个功能创建一个专门的分支;
  2. 开发者将分支推送到公共的GitHub仓库;
  3. 开发者用GitHub发起一个Pull Request;
  4. 其余的团队成员审查代码,讨论并且做出修改;
  5. 项目维护者将这个功能并入官方的仓库,然后关闭这个Pull Request。

 现在点击Compare & pull request按钮,就创建一个PR,

GitHub多人协作简明教程

点页面下方的Create pull request按钮即可。 生成的PR看起来是这样的:

GitHub多人协作简明教程


6. (Maintainer) HuanianLi 查看PR并Merge

6.1 HuanianLi查看PR

HuanianLi可能在PR中加入comment, 要求DaxiangLi做相应的修改。 这里为简单起见,直接Review通过。

GitHub多人协作简明教程

 

6.2 HuanianLi点Merge pull request

GitHub多人协作简明教程

 

到此为止,DaxiangLi成功地给HuanianLi贡献了一次代码!! 当然,这次贡献过程异常简单,因为未涉及到冲突解决。接下来将介绍更复杂的情况,这才是重点:-)

6.3 HuanianLi 查看kaiba并删除无用的commit

6.3.1 使用git pull更新本地空间

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ git pull
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), done.
From https://github.com/HuanianLi/kaiba
   c0bd2ed..b8a0b63  master     -> origin/master
Updating c0bd2ed..b8a0b63
Fast-forward
 foo.py | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 foo.py

GitHub多人协作简明教程

GitHub多人协作简明教程

注意: 在顶端的commit不是我们想要的,需要把它移除掉。

GitHub多人协作简明教程

commit b8a0b63d8b18f8466e79284ed6022340ca5a43a8
Merge: c0bd2ed 640f6f6
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 18:55:02 2018 +0800

    Merge pull request #1 from DaxiangLi/dev
    
    DaxiangLi: Add foo.py

GitHub多人协作简明教程

 

6.3.2 使用git rebase -i移除不需要的commit

[email protected]:~/workspace/kaiba$ git rebase -i c0bd2ed35e10180209726199af422a63a007355f
Successfully rebased and updated refs/heads/master.

在弹出的交互界面中不做任何修改,直接保存退出即可。

GitHub多人协作简明教程

 

6.3.3 使用git push --force强制更新远端的master分支

[email protected]:~/workspace/kaiba$ git push --force
Username for 'https://github.com': HuanianLi
Password for 'https://[email protected]': 
Total 0 (delta 0), reused 0 (delta 0)
To https://github.com/HuanianLi/kaiba.git
 + b8a0b63...640f6f6 master -> master (forced update)

GitHub多人协作简明教程

这下清爽啦!!

 


下面将重点讨论这两种比较复杂的场景:

  • 场景一 : PR Review过程中upstream有更新, 但没有冲突需要解决。例如: DaxiangLi继续修改foo.py, 提交一个PR, 在Review的过程中, HuanianLi增加了一个Makefile并提交了代码。
  • 场景二 : PR Review过程中upstream有更新, 而且需要解决冲突。例如: DaxiangLi继续修改foo.py, 提交一个PR, 在Review的过程中, HuanianLi也修改了foo.py并提交了代码。

这两种场景是常有的事情,因为PR提交后,在review的过程中可能改动多次。那么,在改动的过程中,别的合作伙伴给upstream里贡献了代码并导致commit增加是常有的事情。而且,别的合作伙伴很可能跟你改动了同一个文件,那么你就需要做冲突解决。


场景一: PR Review过程中upstream有更新, 但没有冲突需要解决

101 - 在开发之前,DaxiangLi先同步upstream,保证remotes/origin/master与remotes/upstream/master一致

GitHub多人协作简明教程

[email protected]:~/workspace$ 
[email protected]:~/workspace$ git clone https://github.com/DaxiangLi/kaiba.git
Cloning into 'kaiba'...
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 0), reused 6 (delta 0), pack-reused 0
Unpacking objects: 100% (6/6), done.
Checking connectivity... done.
[email protected]:~/workspace$ cd kaiba
[email protected]:~/workspace/kaiba$ ls
README.md
[email protected]:~/workspace/kaiba$
[email protected]:~/workspace/kaiba$ git remote add upstream https://github.com/HuanianLi/kaiba.git
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git remote update
Fetching origin
Fetching upstream
From https://github.com/HuanianLi/kaiba
 * [new branch]      master     -> upstream/master
[email protected]:~/workspace/kaiba$ ls
README.md
[email protected]:~/workspace/kaiba$
[email protected]:~/workspace/kaiba$ git fetch upstream master
From https://github.com/HuanianLi/kaiba
 * branch            master     -> FETCH_HEAD
[email protected]:~/workspace/kaiba$
[email protected]:~/workspace/kaiba$ git rebase upstream/master
First, rewinding head to replay your work on top of it...
Fast-forwarded master to upstream/master.
[email protected]:~/workspace/kaiba$ ls
foo.py  README.md
[email protected]:~/workspace/kaiba$
[email protected]:~/workspace/kaiba$ git log
commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/dev
  remotes/origin/master
  remotes/upstream/master
[email protected]:~/workspace/kaiba$
[email protected]:~/workspace/kaiba$ git push origin master
Username for 'https://github.com': DaxiangLi
Password for 'https://[email protected]': 
Total 0 (delta 0), reused 0 (delta 0)
To https://github.com/DaxiangLi/kaiba.git
   c0bd2ed..640f6f6  master -> master
[email protected]:~/workspace/kaiba$

GitHub多人协作简明教程

102 - DaxiangLi 切换到dev分支

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/dev
  remotes/origin/master
  remotes/upstream/master
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git checkout dev
Branch dev set up to track remote branch dev from origin.
Switched to a new branch 'dev'
[email protected]:~/workspace/kaiba$ git log
commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git branch -a
* dev
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/dev
  remotes/origin/master
  remotes/upstream/master
[email protected]:~/workspace/kaiba$ 

GitHub多人协作简明教程

103 - DaxiangLi修改foo.py并commit,然后push到remotes/origin/dev

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ ls
foo.py  README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ vi foo.py 
[email protected]:~/workspace/kaiba$ git diff
diff --git a/foo.py b/foo.py
index 55568dd..4ca134c 100644
--- a/foo.py
+++ b/foo.py
@@ -3,6 +3,10 @@
 import sys
 
 def main(argc, argv):
+    if argc != 2:
+        sys.stderr.write("Usage: %s <num>\n" % argv[0])
+        return 1
+
     i = 0
     while i < int(argv[1]):
         print "%02d: Hello World." % i
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git status
On branch dev
Your branch is up-to-date with 'origin/dev'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   foo.py

no changes added to commit (use "git add" and/or "git commit -a")
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git commit -a -m "DaxiangLi: add checking to foo.py"
[dev e1bb21e] DaxiangLi: add checking to foo.py
 1 file changed, 4 insertions(+)
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git log
commit e1bb21ee432a56fe83d8b3d79048d1623dde0b4d
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: add checking to foo.py

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git show
commit e1bb21ee432a56fe83d8b3d79048d1623dde0b4d
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: add checking to foo.py

diff --git a/foo.py b/foo.py
index 55568dd..4ca134c 100644
--- a/foo.py
+++ b/foo.py
@@ -3,6 +3,10 @@
 import sys
 
 def main(argc, argv):
+    if argc != 2:
+        sys.stderr.write("Usage: %s <num>\n" % argv[0])
+        return 1
+
     i = 0
     while i < int(argv[1]):
         print "%02d: Hello World." % i
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git push origin dev
Username for 'https://github.com': DaxiangLi
Password for 'https://[email protected]': 
Counting objects: 3, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 388 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/DaxiangLi/kaiba.git
   640f6f6..e1bb21e  dev -> dev
[email protected]:~/workspace/kaiba$ 

GitHub多人协作简明教程

现在,从DaxiangLi的GitHub空间里可以看到新增加到dev分支的commit e1bb21e。

GitHub多人协作简明教程

104 - DaxiangLi为dev分支的commit e1bb21e创建一个PR

GitHub多人协作简明教程

105 - HuanianLi开始review DaxiangLi的PR

105.1 在HuanianLi的GitHub空间里看到的PR

GitHub多人协作简明教程

105.2 HuanianLi 给PR#2做review, 要求Daxiang Li做修改,于是Daxiang Li看到的PR是

GitHub多人协作简明教程

105.3 - DaxiangLi根据HuanianLi的comments做修改

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ vi foo.py
[email protected]:~/workspace/kaiba$ git diff
diff --git a/foo.py b/foo.py
index 4ca134c..84b0787 100644
--- a/foo.py
+++ b/foo.py
@@ -5,14 +5,14 @@ import sys
 def main(argc, argv):
     if argc != 2:
         sys.stderr.write("Usage: %s <num>\n" % argv[0])
-        return 1
+        return (-1)
 
     i = 0
     while i < int(argv[1]):
         print "%02d: Hello World." % i
         i += 1
 
-    return 0
+    return (0)
 
 if __name__ == '__main__':
     argv = sys.argv

[email protected]:~/workspace/kaiba$
[email protected]:~/workspace/kaiba$ git add foo.py
[email protected]:~/workspace/kaiba$ git commit -m "DaxiangLi: add checking to foo.py (2)"
[dev d266d6b] DaxiangLi: add checking to foo.py (2)
 1 file changed, 2 insertions(+), 2 deletions(-)
[email protected]:~/workspace/kaiba$ git log
commit d266d6b3f4b6569e82dcd479c020a53f2d5ef556
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 12:54:48 2018 +0800

    DaxiangLi: add checking to foo.py (2)

commit e1bb21ee432a56fe83d8b3d79048d1623dde0b4d
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: add checking to foo.py

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git push
Username for 'https://github.com': DaxiangLi
Password for 'https://[email protected]': 
Counting objects: 3, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 331 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/DaxiangLi/kaiba.git
   e1bb21e..d266d6b  dev -> dev
[email protected]:~/workspace/kaiba$ 

GitHub多人协作简明教程

105.4 DaxiangLi在PR上做comment, 告诉HuanianLi已经改好了。 (注意: PR上出现了两个commit)

  • commit 1: e1bb21e
  • commit 2: d266d6b

GitHub多人协作简明教程

105.5 HuanianLi 重新检查DaxiangLi的PR

HuanianLi一看DaxiangLi的PR包含了多个commit, 这哪成啊。。。立即给DaxiangLi写comment, 要求合并多个commits为一个commit。

GitHub多人协作简明教程

105.6 DaxiangLi着手合并多个commits

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ git log
commit d266d6b3f4b6569e82dcd479c020a53f2d5ef556
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 12:54:48 2018 +0800

    DaxiangLi: add checking to foo.py (2)

commit e1bb21ee432a56fe83d8b3d79048d1623dde0b4d
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: add checking to foo.py

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git rebase -i 640f6f6                                                 
[detached HEAD 7bab5c2] DaxiangLi: add checking to foo.py
 Date: Thu Jul 26 11:39:22 2018 +0800
 1 file changed, 5 insertions(+), 1 deletion(-)
Successfully rebased and updated refs/heads/dev.
[email protected]:~/workspace/kaiba$ git log
commit 7bab5c2d12389b6a5bf5cd602dff684ea336a52e
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: add checking to foo.py

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ git diff
[email protected]:~/workspace/kaiba$ git show
commit 7bab5c2d12389b6a5bf5cd602dff684ea336a52e
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: add checking to foo.py

diff --git a/foo.py b/foo.py
index 55568dd..84b0787 100644
--- a/foo.py
+++ b/foo.py
@@ -3,12 +3,16 @@
 import sys
 
 def main(argc, argv):
+    if argc != 2:
+        sys.stderr.write("Usage: %s <num>\n" % argv[0])
+        return (-1)
+
     i = 0
     while i < int(argv[1]):
         print "%02d: Hello World." % i
         i += 1
 
-    return 0
+    return (0)
 
 if __name__ == '__main__':
     argv = sys.argv
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git push --force
Username for 'https://github.com': DaxiangLi
Password for 'https://[email protected]': 
Counting objects: 3, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 404 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/DaxiangLi/kaiba.git
 + d266d6b...7bab5c2 dev -> dev (forced update)
[email protected]:~/workspace/kaiba$ 

GitHub多人协作简明教程

注意:

  1. 做git push的时候必须使用 'git push --force'
  2. 做git rebase -i <commit id>的时候, <commit id>是上一次官方merge的commit id.

关于git rebase -i <commit id>的过程,图解如下:

  • 01 - 开始做rebase

GitHub多人协作简明教程

  • 02 - 进入rebase交互界面,注意阅读各个command的含义

GitHub多人协作简明教程

  • 03 - 将commit d266d6b应用squash

GitHub多人协作简明教程

  • 04 - 在vim里按:wq (保存退出)

GitHub多人协作简明教程

  • 05 - 切换到commit交互界面

GitHub多人协作简明教程

  • 06 : 删除L6-9, 然后保存退出vim

GitHub多人协作简明教程

 

105.7 DaxiangLi更改一下commit的comment, 重新push

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ git commit --amend 
[dev 254347c] DaxiangLi: Add checking to foo.py
 Date: Thu Jul 26 11:39:22 2018 +0800
 1 file changed, 5 insertions(+), 1 deletion(-)
[email protected]:~/workspace/kaiba$ git log
commit 254347cbe57fa043ffcc774e26eabdcd63ea8b30
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ git push --force
Username for 'https://github.com': DaxiangLi
Password for 'https://[email protected]': 
Counting objects: 3, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 405 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/DaxiangLi/kaiba.git
 + db73315...254347c dev -> dev (forced update)

GitHub多人协作简明教程

 

105.8 DaxiangLi重新在PR上加comment, 请HuanianLi再次review (注意: PR上现在只有一个commit了)

GitHub多人协作简明教程

 

105.9 HuanianLi 给kaiba.git里添加一个Makefile, 在检查DaxiangLi的PR最近改动之前

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ ls
foo.py  README.md
[email protected]:~/workspace/kaiba$ git log
commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ vi Makefile
[email protected]:~/workspace/kaiba$ make 
cp foo.py foo && chmod +x foo
[email protected]:~/workspace/kaiba$ ls
foo  foo.py  Makefile  README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git add Makefile 
[email protected]:~/workspace/kaiba$ git commit -m "HuanianLi: Add Makefile"
[master 3609dff] HuanianLi: Add Makefile
 1 file changed, 9 insertions(+)
 create mode 100644 Makefile
[email protected]:~/workspace/kaiba$ git log
commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <[email protected]>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ git branch -a
* master
  remotes/origin/master
[email protected]:~/workspace/kaiba$ git push 
Username for 'https://github.com': HuanianLi
Password for 'https://[email protected]': 
Counting objects: 3, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 382 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/HuanianLi/kaiba.git
   640f6f6..3609dff  master -> master
[email protected]:~/workspace/kaiba$ 

GitHub多人协作简明教程

这时候, HuanianLi的master里包含了3个commits, 而DaxiangLi的master里包含了2个commits, dev分支里包含了3个commits。 那么,如果DaxiangLi的dev分支里的top commit (254347c) 被合并到HuanianLi的master分支的时候,这一commit可能成为top commit, 也就是第4个commit,当然也可能成为第3个commit。

GitHub多人协作简明教程

 1 --- HuanianLi's master branch ---
 2 commit 3609dff HuanianLi: Add Makefile
 3 commit 640f6f6 DaxiangLi: Add foo.py
 4 commit c0bd2ed Initialize the project by adding README.md
 5 
 6 --- DaxiangLi's master branch ---
 7 commit 640f6f6 DaxiangLi: Add foo.py
 8 commit c0bd2ed Initialize the project by adding README.md
 9 
10 --- DaxiangLi's dev    branch ---
11 commit 254347c DaxiangLi: Add checking to foo.py
12 commit 640f6f6 DaxiangLi: Add foo.py
13 commit c0bd2ed Initialize the project by adding README.md
14 
15 #
16 # After commit 7bab5c2 from DaxiangLi's dev    branch
17 # is merged into            HuanianLi's master branch
18 #
19 --- HuanianLi's master branch looks like ---
20 commit 254347c DaxiangLi: Add checking to foo.py
21 commit 3609dff HuanianLi: Add Makefile
22 commit 640f6f6 DaxiangLi: Add foo.py
23 commit c0bd2ed Initialize the project by adding README.md
24 
25 # OR
26 commit 3609dff HuanianLi: Add Makefile
27 commit 254347c DaxiangLi: Add checking to foo.py
28 commit 640f6f6 DaxiangLi: Add foo.py
29 commit c0bd2ed Initialize the project by adding README.md

GitHub多人协作简明教程

105.10 HuanianLi再次检查DaxiangLi的PR, 发现只有一个commit了,而且与他的master分支没有冲突,决定merge!!

GitHub多人协作简明教程

点击Merge pull request按钮右边的向下箭头,我们可看到有三种Merge方式,这一次,我们将采用Rebase and merge。

GitHub多人协作简明教程

 

105.11 HuanianLi采用Rebase and merge选项处理DaxiangLi的PR

GitHub多人协作简明教程

Merge 完毕后,在HuanianLi的GitHub空间可以看到

GitHub多人协作简明教程

HuanianLi重新clone一下kaiba.git, 通过git检查Merge:

GitHub多人协作简明教程

[email protected]:~/workspace$ git clone https://github.com/HuanianLi/kaiba.git
Cloning into 'kaiba'...
remote: Counting objects: 12, done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 12 (delta 2), reused 9 (delta 1), pack-reused 0
Unpacking objects: 100% (12/12), done.
Checking connectivity... done.
[email protected]:~/workspace$ cd kaiba
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git log
commit 27aca2bcc0fcffb26828cac1eebe517439ef49c9
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <[email protected]>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ 

GitHub多人协作简明教程

 

106 - DaxiangLi 需要重新sync一下master (这一过程我们在前面介绍过,按照基本套路执行即可)

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git branch 
* dev
  master
[email protected]:~/workspace/kaiba$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git branch
  dev
* master
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git remote -v
origin    https://github.com/DaxiangLi/kaiba.git (fetch)
origin    https://github.com/DaxiangLi/kaiba.git (push)
upstream    https://github.com/HuanianLi/kaiba.git (fetch)
upstream    https://github.com/HuanianLi/kaiba.git (push)
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git remote update
Fetching origin
Fetching upstream
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 6 (delta 2), reused 3 (delta 1), pack-reused 0
Unpacking objects: 100% (6/6), done.
From https://github.com/HuanianLi/kaiba
   640f6f6..27aca2b  master     -> upstream/master
[email protected]:~/workspace/kaiba$

[email protected]:~/workspace/kaiba$ git log
commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git fetch upstream master
From https://github.com/HuanianLi/kaiba
 * branch            master     -> FETCH_HEAD
[email protected]:~/workspace/kaiba$
[email protected]:~/workspace/kaiba$ git rebase upstream/master
First, rewinding head to replay your work on top of it...
Fast-forwarded master to upstream/master.
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git log
commit 27aca2bcc0fcffb26828cac1eebe517439ef49c9
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <[email protected]>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git push origin master
Username for 'https://github.com': DaxiangLi
Password for 'https://[email protected]': 
Counting objects: 6, done.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 747 bytes | 0 bytes/s, done.
Total 6 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 1 local object.
To https://github.com/DaxiangLi/kaiba.git
   640f6f6..27aca2b  master -> master
[email protected]:~/workspace/kaiba$

GitHub多人协作简明教程

注意: 这里用到的关键命令是:

GitHub多人协作简明教程

1 $  git checkout master
2 $[ git remote add upstream https://github.com/HuanianLi/kaiba.git ]
3 $  git remote -v
4 $  git remote update
5 $  git fetch upstream master
6 $  git rebase upstream/master
7 $  git push origin master

GitHub多人协作简明教程

 

107 - DaxiangLi将dev分支也sync一下(跟origin master同步即可),以便下一次做开发

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git branch
  dev
* master
[email protected]:~/workspace/kaiba$ git checkout dev
Switched to branch 'dev'
Your branch is up-to-date with 'origin/dev'.
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git branch
* dev
  master
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git log
commit 254347cbe57fa043ffcc774e26eabdcd63ea8b30
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git fetch origin master
From https://github.com/DaxiangLi/kaiba
 * branch            master     -> FETCH_HEAD
[email protected]:~/workspace/kaiba$ git rebase origin/master
First, rewinding head to replay your work on top of it...
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git log
commit 27aca2bcc0fcffb26828cac1eebe517439ef49c9
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <[email protected]>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git push origin dev
Username for 'https://github.com': DaxiangLi
Password for 'https://[email protected]': 
To https://github.com/DaxiangLi/kaiba.git
 ! [rejected]        dev -> dev (non-fast-forward)
error: failed to push some refs to 'https://github.com/DaxiangLi/kaiba.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git push origin dev --force
Username for 'https://github.com': DaxiangLi
Password for 'https://[email protected]': 
Total 0 (delta 0), reused 0 (delta 0)
To https://github.com/DaxiangLi/kaiba.git
 + 254347c...27aca2b dev -> dev (forced update)
[email protected]:~/workspace/kaiba$ 

GitHub多人协作简明教程

注意: 这里用到的关键命令是:

1 $ git checkout dev
2 $ git fetch origin master
3 $ git rebase origin/master
4 $ git push origin dev --force

到这里,场景一我们就介绍完毕了, 接下来介绍场景二


场景二: PR Review过程中upstream有更新, 而且需要解决冲突

201 - DaxiangLi第一次更改foo.py

GitHub多人协作简明教程

[email protected]:~$ 
[email protected]:~$ rm -rf workspace/kaiba
[email protected]:~$ cd workspace
[email protected]:~/workspace$ 
[email protected]:~/workspace$ git clone https://github.com/DaxiangLi/kaiba.git
Cloning into 'kaiba'...
remote: Counting objects: 12, done.
remote: Compressing objects: 100% (8/8), done.
remote: Total 12 (delta 2), reused 12 (delta 2), pack-reused 0
Unpacking objects: 100% (12/12), done.
Checking connectivity... done.
[email protected]:~/workspace$ cd kaiba
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git remote -v
origin    https://github.com/DaxiangLi/kaiba.git (fetch)
origin    https://github.com/DaxiangLi/kaiba.git (push)
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git remote add upstream https://github.com/HuanianLi/kaiba.git
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git remote -v
origin    https://github.com/DaxiangLi/kaiba.git (fetch)
origin    https://github.com/DaxiangLi/kaiba.git (push)
upstream    https://github.com/HuanianLi/kaiba.git (fetch)
upstream    https://github.com/HuanianLi/kaiba.git (push)
[email protected]:~/workspace/kaiba$

[email protected]:~/workspace/kaiba$ git branch 
* master
[email protected]:~/workspace/kaiba$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/dev
  remotes/origin/master
[email protected]:~/workspace/kaiba$ git checkout dev
Branch dev set up to track remote branch dev from origin.
Switched to a new branch 'dev'
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git branch
* dev
  master
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ vi foo.py
[email protected]:~/workspace/kaiba$ git diff foo.py
diff --git a/foo.py b/foo.py
index 84b0787..44635b7 100644
--- a/foo.py
+++ b/foo.py
@@ -7,10 +7,8 @@ def main(argc, argv):
         sys.stderr.write("Usage: %s <num>\n" % argv[0])
         return (-1)
 
-    i = 0
-    while i < int(argv[1]):
+    for i in range(int(argv[1])):
         print "%02d: Hello World." % i
-        i += 1
 
     return (0)
 
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git add foo.py 
[email protected]:~/workspace/kaiba$ git commit -m "DaxiangLi: Update foo.py to use for instead of while"
[dev 099cfc7] DaxiangLi: Update foo.py to use for instead of while
 1 file changed, 1 insertion(+), 3 deletions(-)
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git log
commit 099cfc7de963a4cbe8ceb7088a710bdb4815dd9d
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 16:57:09 2018 +0800

    DaxiangLi: Update foo.py to use for instead of while

commit 27aca2bcc0fcffb26828cac1eebe517439ef49c9
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <[email protected]>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git push origin dev
Username for 'https://github.com': DaxiangLi
Password for 'https://[email protected]': 
Counting objects: 3, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 340 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To https://github.com/DaxiangLi/kaiba.git
   27aca2b..099cfc7  dev -> dev
[email protected]:~/workspace/kaiba$ 

GitHub多人协作简明教程

 

202 - DaxiangLi第二次更改foo.py

提交更新到remotes/origin/dev分支后不满意,于是做第二次修改再提交,这里为了保持只有一个commit, 将会用到

$ git commit -a -m "comments" --amend

全部修改过程如下:

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git log
commit 099cfc7de963a4cbe8ceb7088a710bdb4815dd9d
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 16:57:09 2018 +0800

    DaxiangLi: Update foo.py to use for instead of while

commit 27aca2bcc0fcffb26828cac1eebe517439ef49c9
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <[email protected]>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git diff
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ vi foo.py 
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git add foo.py
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git commit -m "DaxiangLi: Update foo.py to use 'for' instead of 'while'" --amend
[dev 3b9d809] DaxiangLi: Update foo.py to use 'for' instead of 'while'
 Date: Thu Jul 26 16:57:09 2018 +0800
 1 file changed, 2 insertions(+), 4 deletions(-)
[email protected]:~/workspace/kaiba$ git log
commit 3b9d809f249abfd4d5a53d35006d63f341efbacf
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 16:57:09 2018 +0800

    DaxiangLi: Update foo.py to use 'for' instead of 'while'

commit 27aca2bcc0fcffb26828cac1eebe517439ef49c9
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <[email protected]>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git push origin dev --force
Username for 'https://github.com': DaxiangLi
Password for 'https://[email protected]': 
Counting objects: 3, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 357 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To https://github.com/DaxiangLi/kaiba.git
 + 099cfc7...3b9d809 dev -> dev (forced update)
[email protected]:~/workspace/kaiba$ 

GitHub多人协作简明教程

 

203 - DaxiangLi创建一个PR

GitHub多人协作简明教程

 

204 - HuanianLi更新foo.py并提交到upstream/master分支

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git log
commit 27aca2bcc0fcffb26828cac1eebe517439ef49c9
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <[email protected]>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ vi foo.py 
[email protected]:~/workspace/kaiba$ git diff foo.py
diff --git a/foo.py b/foo.py
index 84b0787..a9aa6fe 100644
--- a/foo.py
+++ b/foo.py
@@ -5,14 +5,14 @@ import sys
 def main(argc, argv):
     if argc != 2:
         sys.stderr.write("Usage: %s <num>\n" % argv[0])
-        return (-1)
+        return -1
 
     i = 0
     while i < int(argv[1]):
         print "%02d: Hello World." % i
         i += 1
 
-    return (0)
+    return 0
 
 if __name__ == '__main__':
     argv = sys.argv
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git commit -a -m "HuanianLi: Update foo.py to use return N instead of return (N)"
[master c5221d8] HuanianLi: Update foo.py to use return N instead of return (N)
 1 file changed, 2 insertions(+), 2 deletions(-)
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git log
commit c5221d81c91d45cda15e33c3bf0e82874d7fcc97
Author: Huanian Li <[email protected]>
Date:   Thu Jul 26 17:29:22 2018 +0800

    HuanianLi: Update foo.py to use return N instead of return (N)

commit 27aca2bcc0fcffb26828cac1eebe517439ef49c9
Author: Daxiang Li <[email protected]>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <[email protected]>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <[email protected]>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <[email protected]>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git push origin master
Username for 'https://github.com': HuanianLi
Password for 'https://[email protected]': 
Counting objects: 3, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 325 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To https://github.com/HuanianLi/kaiba.git
   27aca2b..c5221d8  master -> master
[email protected]:~/workspace/kaiba$ 

GitHub多人协作简明教程

205 - DaxiangLi再次更新foo.py,故意制造一个冲突

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git remote update
Fetching origin
Fetching upstream
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 3 (delta 2), reused 3 (delta 2), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/HuanianLi/kaiba
 * [new branch]      master     -> upstream/master
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git branch -a
* dev
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/dev
  remotes/origin/master
  remotes/upstream/master

[email protected]:~/workspace/kaiba$ vi foo.py
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git commit -a --amend 
[dev 924729d] DaxiangLi: Update foo.py to use 'for' instead of 'while'
 Date: Thu Jul 26 16:57:09 2018 +0800
 1 file changed, 3 insertions(+), 5 deletions(-)

[email protected]:~/workspace/kaiba$ git diff remotes/origin/master..
diff --git a/foo.py b/foo.py
index 84b0787..b1070a5 100644
--- a/foo.py
+++ b/foo.py
@@ -5,12 +5,10 @@ import sys
 def main(argc, argv):
     if argc != 2:
         sys.stderr.write("Usage: %s <num>\n" % argv[0])
-        return (-1)
+        return (-11)
 
-    i = 0
-    while i < int(argv[1]):
-        print "%02d: Hello World." % i
-        i += 1
+    for i in range(int(argv[1])):
+        print "%02d: Hello World." % (i + 1)
 
     return (0)
 
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git diff remotes/upstream/master..
diff --git a/foo.py b/foo.py
index a9aa6fe..b1070a5 100644
--- a/foo.py
+++ b/foo.py
@@ -5,14 +5,12 @@ import sys
 def main(argc, argv):
     if argc != 2:
         sys.stderr.write("Usage: %s <num>\n" % argv[0])
-        return -1
+        return (-11)
 
-    i = 0
-    while i < int(argv[1]):
-        print "%02d: Hello World." % i
-        i += 1
+    for i in range(int(argv[1])):
+        print "%02d: Hello World." % (i + 1)
 
-    return 0
+    return (0)
 
 if __name__ == '__main__':
     argv = sys.argv
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git push --force
Username for 'https://github.com': DaxiangLi
Password for 'https://[email protected]': 
Counting objects: 3, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 362 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To https://github.com/DaxiangLi/kaiba.git
 + 671404d...924729d dev -> dev (forced update)
[email protected]:~/workspace/kaiba$ 

GitHub多人协作简明教程

  • 制造的冲突是故意将return (-1)改成return (-11)

GitHub多人协作简明教程

  • 接下来我们发现,PR上就会显示有冲突了!!

 GitHub多人协作简明教程

  •  冲突的细节在于foo.py的第8行

GitHub多人协作简明教程

 

好吧,接下来DaxiangLi就需要去解决冲突了!

 

206 - DaxiangLi解决冲突 (P.S. 解决冲突不是很容易,请仔细看)

206.1 创建一个临时分支dev-scratch (为了演示得更清晰,这里故意删除旧的空间,重新clone一遍,然后从头开始)

[email protected]:~/workspace/kaiba$ git checkout -b dev-scratch dev
Switched to a new branch 'dev-scratch'

GitHub多人协作简明教程

 

206.2 给临时分支dev-scratch添加upstream的repo

[email protected]:~/workspace/kaiba$ git remote add upstream https://github.com/HuanianLi/kaiba.git

GitHub多人协作简明教程

 

206.3 让临时分支dev-scratch与upstream/master同步

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ git remote update
Fetching origin
Fetching upstream
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 2), reused 2 (delta 1), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/HuanianLi/kaiba
 * [new branch]      master     -> upstream/master

GitHub多人协作简明教程

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ git fetch upstream master
From https://github.com/HuanianLi/kaiba
 * branch            master     -> FETCH_HEAD

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ git merge upstream/master
Auto-merging foo.py
CONFLICT (content): Merge conflict in foo.py
Automatic merge failed; fix conflicts and then commit the result.

GitHub多人协作简明教程

 

206.4 在临时分支dev-scratch里合并冲突

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ git add foo.py
[email protected]:~/workspace/kaiba$ git commit -m "DaxiangLi: Merge confilict in foo.py"
[dev-scratch c9af088] DaxiangLi: Merge confilict in foo.py

GitHub多人协作简明教程

 

206.5 将本地的临时分支dev-scratch与本地开发分支dev做比较

[email protected]:~/workspace/kaiba$ git diff dev..dev-scratch

GitHub多人协作简明教程

 

206.6 切换到本地开发分支dev

[email protected]:~/workspace/kaiba$ git checkout dev
Switched to branch 'dev'
Your branch is up-to-date with 'origin/dev'.

GitHub多人协作简明教程

 

206.7 将临时分支dev-scratch合并到开发分支dev

[email protected]:~/workspace/kaiba$ git merge --squash dev-scratch
Updating 924729d..c9af088
Fast-forward
Squash commit -- not updating HEAD
 foo.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

GitHub多人协作简明教程

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ git commit -a --amend 
[dev 5055a77] DaxiangLi: Update foo.py to use 'for' instead of 'while'
 Date: Thu Jul 26 16:57:09 2018 +0800
 1 file changed, 4 insertions(+), 6 deletions(-)
[email protected]:~/workspace/kaiba$ 
[email protected]:~/workspace/kaiba$ git diff dev..dev-scratch
[email protected]:~/workspace/kaiba$ 

GitHub多人协作简明教程

GitHub多人协作简明教程

 

206.8 把本地的开发dev强制推送到远端的开发dev

GitHub多人协作简明教程

[email protected]:~/workspace/kaiba$ git push origin dev --force
Username for 'https://github.com': DaxiangLi
Password for 'https://[email protected]': 
Counting objects: 3, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 373 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To https://github.com/DaxiangLi/kaiba.git
 + 924729d...5055a77 dev -> dev (forced update)

GitHub多人协作简明教程

GitHub多人协作简明教程

 

206.9 删除本地的临时分支dev-scratch

[email protected]:~/workspace/kaiba$ git branch dev-scratch -D
Deleted branch dev-scratch (was c9af088).

GitHub多人协作简明教程

OKAY, 冲突解决完成! 重新刷新PR, 发现冲突已经不存在啦。。。

GitHub多人协作简明教程

 

207 - HuanianLi再次检查PR,发现没有冲突,将代码Rebase and merge

208 - DaxiangLi重新sync远端的master分支

  • 使用下面一组命令即可 (其中, [*]为关键命令)

GitHub多人协作简明教程

 1 [ ] $ git branch
 2 [*] $ git checkout master
 3 [ ] $ git branch
 4 [ ] $ git log
 5 [*] $ git remote add upstream https://github.com/HuanianLi/kaiba.git
 6 [ ] $ git remote -v
 7 [ ] $ git remote update
 8 [*] $ git fetch  upstream master
 9 [*] $ git rebase upstream/master
10 [ ] $ git log
11 [ ] $ git diff remotes/origin/master..
12 [*] $ git push origin master

GitHub多人协作简明教程

 

209 - DaxiangLi重新sync远端的dev分支 (前面其实已经介绍过)

  • 使用下面的命令即可 (其中, [*]为关键命令)

GitHub多人协作简明教程

 1 [*] $ git clone https://github.com/DaxiangLi/kaiba.git
 2 [*] $ git checkout dev
 3 [ ] $ git remote -v
 4 [*] $ git remote add upstream https://github.com/HuanianLi/kaiba.git
 5 [ ] $ git remote -v
 6 [ ] $ git log
 7 [ ] $ git remote update
 8 [*] $ git fetch  upstream master
 9 [*] $ git rebase upstream/master
10 [ ] $ git log --graph
11 [*] $ git push origin dev --force

GitHub多人协作简明教程

说明: git remote update可以不做,直接使用git fetch upstream master也okay.


总结:

  1. 从upstream fork出代码空间后,总是创建一个dev分支并保存到远端比较好,这样master分支用来与upstream保持同步,dev分支用来做开发
  2. 提交PR的时候请在dev分支中总是保存一个用来被合作伙伴review的commit,如不小心提交了多个commit, 需要进行合并,合并的方法是使用git rebase -i
  3. 保持PR中只有一个commit的秘诀是使用git commit -a --amend,然后使用git push origin dev --force
  4. 养成总是让origin/master与upstream同步的好习惯
  5. 不用总是让origin/dev与upstream保持同步,如果PR中显示有冲突就解决冲突,没有就不用管,即使origin/dev与upstream不同步 (P.S. git没有recommit功能,所以你无法总是把你的commit放置到top位置)
  6. 当一个PR被合并后,不妨也让origin/dev分支与upstream同步,同步的秘诀还是git push origin dev --force
  7. 可以认为origin/dev分支是一个沙箱,可以用来随便玩, 玩坏了大不了删除远端的origin/dev分支再重新创建一个;但是请认真对待origin/master
  8. 尽可能地使用git rebase upstream/master, 不使用git merge upstream/master, 在做同步的时候
  9. 解决冲突请创建一个本地临时分支dev-scratch, 然后将临时分支合并到本地开发分支dev,合并的秘诀是使用 git merge --squash dev-scratch
  10. 不需要的临时分支dev-scratch用git branch dev-scratch -D删除,养成不留垃圾分支的好习惯
  11. 不小心关掉一个PR可以Re-open, 但是尽量不要在review的过程中删除被review的commit,那样会导致PR被自动关闭

参考资料: