GitHub多人協作簡明教程


本文面向已經了解/熟悉git基本命令但是並不熟悉如何使用GitHub進行多人協作開發項目的同學。

為了簡單起見,這里假設只有兩個開發人員,HuanianLiDaxiangLi。他們在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, 例如:

1.4 點擊頁面下方的"Create an account"按鈕並按照后續提示完成注冊。


2. 在Linux桌面上創建兩個用戶(huanianli and daxiangli), (這里以huanianli為例)

2.1 創建用戶huanianli

root@idorax:~# useradd -d /home/huanianli -m -s /bin/bash -c "Huanian Li" huanianli

2.2 對用戶huanianli的git進行設置 (這里直接編輯文件~/.gitconfig

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

2.3 在huanianli的HOME目錄下創建一個工作空間workspace

huanianli@ThinkCentre:~$ cd ~
huanianli@ThinkCentre:~$ mkdir workspace
huanianli@ThinkCentre:~$ ls
workspace
huanianli@ThinkCentre:~$ 

3. (Maintainer) HuanianLi在GitHub上創建一個項目kaiba

3.1 登錄HuanianLi的GitHub空間,打開頁面Repositories, e.g.

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

點擊頁面右邊的New按鈕, 進入創建一個新的代碼倉庫的頁面。

點擊"Create repository"完成創建。

3.2 進入HuanianLi的Linux桌面,clone在3.1創建的項目kaiba

huanianli@ThinkCentre:~$ cd workspace
huanianli@ThinkCentre:~/workspace$ git clone https://github.com/HuanianLi/kaiba.git
Cloning into 'kaiba'...
warning: You appear to have cloned an empty repository.
Checking connectivity... done.
huanianli@ThinkCentre:~/workspace$ ls
kaiba
huanianli@ThinkCentre:~/workspace$ cd kaiba
huanianli@ThinkCentre:~/workspace/kaiba$ vi README.md
huanianli@ThinkCentre:~/workspace/kaiba$ cat -n README.md
     1    kaiba: A sandbox project of Kaiba
huanianli@ThinkCentre:~/workspace/kaiba$
huanianli@ThinkCentre:~/workspace/kaiba$ git add README.md
huanianli@ThinkCentre:~/workspace/kaiba$
huanianli@ThinkCentre:~/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
huanianli@ThinkCentre:~/workspace/kaiba$
huanianli@ThinkCentre:~/workspace/kaiba$ git log
commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
huanianli@ThinkCentre:~/workspace/kaiba$
huanianli@ThinkCentre:~/workspace/kaiba$ git branch
* master
huanianli@ThinkCentre:~/workspace/kaiba$ 
huanianli@ThinkCentre:~/workspace/kaiba$ git push -u origin master
Username for 'https://github.com': HuanianLi
Password for 'https://HuanianLi@github.com':
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.
huanianli@ThinkCentre:~/workspace/kaiba$

在上面的操作中,關鍵的步驟是:

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

注意因為是第一次push, ‘-u’ 是必須的。

3.3 一旦完成git push之后,我們就可以瀏覽GitHub上的項目了


4. (Contributor) DaxiangLi登錄他的GitHub,  然后進入(Maintainer) HuanianLi的GitHub空間,fork項目kaiba

4.1 DaxiangLi登錄他的GitHub


 

4.2 進入(Maintainer) HuanianLi的GitHub空間, 點開項目kaiba

注意: 目前的 Fork 為0。

4.3 fork項目kaiba, 直接點Fork按鈕

Fork 結束后, DaxiangLi的GitHub里就有了項目kaiba


5. (ContributorDaxiangLi貢獻代碼給項目kaiba

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

daxiangli@ThinkPad:~/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.

兩個問題:

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

5.2 DaxiangLi新建一個開發分支

daxiangli@ThinkPad:~/workspace/kaiba$ git checkout -b dev
Switched to a new branch 'dev'

其中, git checkout -b dev 等同於

1 git branch   dev
2 git checkout dev

5.3 把HuanianLi的項目添加到DaxiangLi的遠程倉庫

daxiangli@ThinkPad:~/workspace/kaiba$ git remote add upstream https://github.com/HuanianLi/kaiba.git

 5.4 將HuanianLi的分支取下來並更新到本地

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

daxiangli@ThinkPad:~/workspace/kaiba$ git fetch upstream master
From https://github.com/HuanianLi/kaiba
 * branch            master     -> FETCH_HEAD

 5.5 合並HuanianLi的分支到本地(注意:這一步在第一次其實不需要)

daxiangli@ThinkPad:~/workspace/kaiba$ git rebase upstream/master
Current branch dev is up to date.

 5.6 DaxiangLi添加一個文件並提交commit

daxiangli@ThinkPad:~/workspace/kaiba$ git add foo.py
daxiangli@ThinkPad:~/workspace/kaiba$ git commit -m "DaxiangLi: Add foo.py"
daxiangli@ThinkPad:~/workspace/kaiba$ git push -u origin dev 

 5.7 進入DaxiangLi的GitHub, 提交一個PR

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,

點頁面下方的Create pull request按鈕即可。 生成的PR看起來是這樣的:


6. (Maintainer) HuanianLi 查看PR並Merge

6.1 HuanianLi查看PR

HuanianLi可能在PR中加入comment, 要求DaxiangLi做相應的修改。 這里為簡單起見,直接Review通過。

 

6.2 HuanianLi點Merge pull request

 

到此為止,DaxiangLi成功地給HuanianLi貢獻了一次代碼!! 當然,這次貢獻過程異常簡單,因為未涉及到沖突解決。接下來將介紹更復雜的情況,這才是重點:-)

6.3 HuanianLi 查看kaiba並刪除無用的commit

6.3.1 使用git pull更新本地空間

huanianli@ThinkCentre:~/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

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

commit b8a0b63d8b18f8466e79284ed6022340ca5a43a8
Merge: c0bd2ed 640f6f6
Author: Huanian Li <41667254+HuanianLi@users.noreply.github.com>
Date:   Wed Jul 25 18:55:02 2018 +0800

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

 

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

huanianli@ThinkCentre:~/workspace/kaiba$ git rebase -i c0bd2ed35e10180209726199af422a63a007355f
Successfully rebased and updated refs/heads/master.

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

 

6.3.3 使用git push --force強制更新遠端的master分支

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

這下清爽啦!!

 


下面將重點討論這兩種比較復雜的場景:

  • 場景一 : 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一致

daxiangli@ThinkPad:~/workspace$ 
daxiangli@ThinkPad:~/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.
daxiangli@ThinkPad:~/workspace$ cd kaiba
daxiangli@ThinkPad:~/workspace/kaiba$ ls
README.md
daxiangli@ThinkPad:~/workspace/kaiba$
daxiangli@ThinkPad:~/workspace/kaiba$ git remote add upstream https://github.com/HuanianLi/kaiba.git
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git remote update
Fetching origin
Fetching upstream
From https://github.com/HuanianLi/kaiba
 * [new branch]      master     -> upstream/master
daxiangli@ThinkPad:~/workspace/kaiba$ ls
README.md
daxiangli@ThinkPad:~/workspace/kaiba$
daxiangli@ThinkPad:~/workspace/kaiba$ git fetch upstream master
From https://github.com/HuanianLi/kaiba
 * branch            master     -> FETCH_HEAD
daxiangli@ThinkPad:~/workspace/kaiba$
daxiangli@ThinkPad:~/workspace/kaiba$ git rebase upstream/master
First, rewinding head to replay your work on top of it...
Fast-forwarded master to upstream/master.
daxiangli@ThinkPad:~/workspace/kaiba$ ls
foo.py  README.md
daxiangli@ThinkPad:~/workspace/kaiba$
daxiangli@ThinkPad:~/workspace/kaiba$ git log
commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

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

102 - DaxiangLi 切換到dev分支

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

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git branch -a
* dev
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/dev
  remotes/origin/master
  remotes/upstream/master
daxiangli@ThinkPad:~/workspace/kaiba$ 

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

daxiangli@ThinkPad:~/workspace/kaiba$ ls
foo.py  README.md
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ vi foo.py 
daxiangli@ThinkPad:~/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
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/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")
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/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(+)
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git log
commit e1bb21ee432a56fe83d8b3d79048d1623dde0b4d
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: add checking to foo.py

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git show
commit e1bb21ee432a56fe83d8b3d79048d1623dde0b4d
Author: Daxiang Li <bjlhn@126.com>
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
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git push origin dev
Username for 'https://github.com': DaxiangLi
Password for 'https://DaxiangLi@github.com': 
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
daxiangli@ThinkPad:~/workspace/kaiba$ 

現在,從DaxiangLi的GitHub空間里可以看到新增加到dev分支的commit e1bb21e

104 - DaxiangLi為dev分支的commit e1bb21e創建一個PR

 

105 - HuanianLi開始review DaxiangLi的PR

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

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

105.3 - DaxiangLi根據HuanianLi的comments做修改

daxiangli@ThinkPad:~/workspace/kaiba$ vi foo.py
daxiangli@ThinkPad:~/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

daxiangli@ThinkPad:~/workspace/kaiba$
daxiangli@ThinkPad:~/workspace/kaiba$ git add foo.py
daxiangli@ThinkPad:~/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(-)
daxiangli@ThinkPad:~/workspace/kaiba$ git log
commit d266d6b3f4b6569e82dcd479c020a53f2d5ef556
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 12:54:48 2018 +0800

    DaxiangLi: add checking to foo.py (2)

commit e1bb21ee432a56fe83d8b3d79048d1623dde0b4d
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: add checking to foo.py

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git push
Username for 'https://github.com': DaxiangLi
Password for 'https://DaxiangLi@github.com': 
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
daxiangli@ThinkPad:~/workspace/kaiba$ 

105.4 DaxiangLi在PR上做comment, 告訴HuanianLi已經改好了。 (注意: PR上出現了兩個commit)

  • commit 1: e1bb21e
  • commit 2: d266d6b

105.5 HuanianLi 重新檢查DaxiangLi的PR

HuanianLi一看DaxiangLi的PR包含了多個commit, 這哪成啊。。。立即給DaxiangLi寫comment, 要求合並多個commits為一個commit。

105.6 DaxiangLi着手合並多個commits

daxiangli@ThinkPad:~/workspace/kaiba$ git log
commit d266d6b3f4b6569e82dcd479c020a53f2d5ef556
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 12:54:48 2018 +0800

    DaxiangLi: add checking to foo.py (2)

commit e1bb21ee432a56fe83d8b3d79048d1623dde0b4d
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: add checking to foo.py

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/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.
daxiangli@ThinkPad:~/workspace/kaiba$ git log
commit 7bab5c2d12389b6a5bf5cd602dff684ea336a52e
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: add checking to foo.py

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
daxiangli@ThinkPad:~/workspace/kaiba$ git diff
daxiangli@ThinkPad:~/workspace/kaiba$ git show
commit 7bab5c2d12389b6a5bf5cd602dff684ea336a52e
Author: Daxiang Li <bjlhn@126.com>
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
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git push --force
Username for 'https://github.com': DaxiangLi
Password for 'https://DaxiangLi@github.com': 
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)
daxiangli@ThinkPad:~/workspace/kaiba$ 

注意:

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

關於git rebase -i <commit id>的過程,圖解如下:

  • 01 - 開始做rebase

  • 02 - 進入rebase交互界面,注意閱讀各個command的含義

  • 03 - 將commit d266d6b應用squash

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

  • 05 - 切換到commit交互界面

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

 

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

daxiangli@ThinkPad:~/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(-)
daxiangli@ThinkPad:~/workspace/kaiba$ git log
commit 254347cbe57fa043ffcc774e26eabdcd63ea8b30
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
daxiangli@ThinkPad:~/workspace/kaiba$ git push --force
Username for 'https://github.com': DaxiangLi
Password for 'https://DaxiangLi@github.com': 
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)

 

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

 

105.9 HuanianLi 給kaiba.git里添加一個Makefile, 在檢查DaxiangLi的PR最近改動之前

huanianli@ThinkCentre:~/workspace/kaiba$ ls
foo.py  README.md
huanianli@ThinkCentre:~/workspace/kaiba$ git log
commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

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

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
huanianli@ThinkCentre:~/workspace/kaiba$ git branch -a
* master
  remotes/origin/master
huanianli@ThinkCentre:~/workspace/kaiba$ git push 
Username for 'https://github.com': HuanianLi
Password for 'https://HuanianLi@github.com': 
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
huanianli@ThinkCentre:~/workspace/kaiba$ 

這時候, 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。

 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

105.10 HuanianLi再次檢查DaxiangLi的PR, 發現只有一個commit了,而且與他的master分支沒有沖突,決定merge!!

點擊Merge pull request按鈕右邊的向下箭頭,我們可看到有三種Merge方式,這一次,我們將采用Rebase and merge。

 

105.11 HuanianLi采用Rebase and merge選項處理DaxiangLi的PR

Merge 完畢后,在HuanianLi的GitHub空間可以看到

HuanianLi重新clone一下kaiba.git, 通過git檢查Merge:

huanianli@ThinkCentre:~/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.
huanianli@ThinkCentre:~/workspace$ cd kaiba
huanianli@ThinkCentre:~/workspace/kaiba$ 
huanianli@ThinkCentre:~/workspace/kaiba$ git log
commit 27aca2bcc0fcffb26828cac1eebe517439ef49c9
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <huanian.li@gmail.com>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
huanianli@ThinkCentre:~/workspace/kaiba$ 

 

106 - DaxiangLi 需要重新sync一下master (這一過程我們在前面介紹過,按照基本套路執行即可)

daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git branch * dev
  master
daxiangli@ThinkPad:~/workspace/kaiba$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git branch
  dev
* master
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/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)
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/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
daxiangli@ThinkPad:~/workspace/kaiba$

daxiangli@ThinkPad:~/workspace/kaiba$ git log
commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

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

    DaxiangLi: Add checking to foo.py

commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <huanian.li@gmail.com>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git push origin master
Username for 'https://github.com': DaxiangLi
Password for 'https://DaxiangLi@github.com': 
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
daxiangli@ThinkPad:~/workspace/kaiba$

注意: 這里用到的關鍵命令是:

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

 

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

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

    DaxiangLi: Add checking to foo.py

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

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

    DaxiangLi: Add checking to foo.py

commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <huanian.li@gmail.com>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git push origin dev
Username for 'https://github.com': DaxiangLi
Password for 'https://DaxiangLi@github.com': 
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.
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git push origin dev --force
Username for 'https://github.com': DaxiangLi
Password for 'https://DaxiangLi@github.com': 
Total 0 (delta 0), reused 0 (delta 0)
To https://github.com/DaxiangLi/kaiba.git
 + 254347c...27aca2b dev -> dev (forced update)
daxiangli@ThinkPad:~/workspace/kaiba$ 

注意: 這里用到的關鍵命令是:

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

daxiangli@ThinkPad:~$ 
daxiangli@ThinkPad:~$ rm -rf workspace/kaiba
daxiangli@ThinkPad:~$ cd workspace
daxiangli@ThinkPad:~/workspace$ 
daxiangli@ThinkPad:~/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.
daxiangli@ThinkPad:~/workspace$ cd kaiba
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git remote -v
origin    https://github.com/DaxiangLi/kaiba.git (fetch)
origin    https://github.com/DaxiangLi/kaiba.git (push)
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git remote add upstream https://github.com/HuanianLi/kaiba.git
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/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)
daxiangli@ThinkPad:~/workspace/kaiba$

daxiangli@ThinkPad:~/workspace/kaiba$ git branch 
* master
daxiangli@ThinkPad:~/workspace/kaiba$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/dev
  remotes/origin/master
daxiangli@ThinkPad:~/workspace/kaiba$ git checkout dev
Branch dev set up to track remote branch dev from origin.
Switched to a new branch 'dev'
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git branch
* dev
  master
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ vi foo.py
daxiangli@ThinkPad:~/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)
 
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git add foo.py 
daxiangli@ThinkPad:~/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(-)
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git log
commit 099cfc7de963a4cbe8ceb7088a710bdb4815dd9d
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 16:57:09 2018 +0800

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

commit 27aca2bcc0fcffb26828cac1eebe517439ef49c9
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <huanian.li@gmail.com>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git push origin dev
Username for 'https://github.com': DaxiangLi
Password for 'https://DaxiangLi@github.com': 
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
daxiangli@ThinkPad:~/workspace/kaiba$ 

 

202 - DaxiangLi第二次更改foo.py

提交更新到remotes/origin/dev分支后不滿意,於是做第二次修改再提交,這里為了保持只有一個commit, 將會用到

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

全部修改過程如下:

daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git log
commit 099cfc7de963a4cbe8ceb7088a710bdb4815dd9d
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 16:57:09 2018 +0800

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

commit 27aca2bcc0fcffb26828cac1eebe517439ef49c9
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <huanian.li@gmail.com>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git diff
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ vi foo.py 
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git add foo.py
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/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(-)
daxiangli@ThinkPad:~/workspace/kaiba$ git log
commit 3b9d809f249abfd4d5a53d35006d63f341efbacf
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 16:57:09 2018 +0800

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

commit 27aca2bcc0fcffb26828cac1eebe517439ef49c9
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <huanian.li@gmail.com>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git push origin dev --force
Username for 'https://github.com': DaxiangLi
Password for 'https://DaxiangLi@github.com': 
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)
daxiangli@ThinkPad:~/workspace/kaiba$ 

 

203 - DaxiangLi創建一個PR

 

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

huanianli@ThinkCentre:~/workspace/kaiba$ 
huanianli@ThinkCentre:~/workspace/kaiba$ git log
commit 27aca2bcc0fcffb26828cac1eebe517439ef49c9
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <huanian.li@gmail.com>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
huanianli@ThinkCentre:~/workspace/kaiba$ 
huanianli@ThinkCentre:~/workspace/kaiba$ vi foo.py 
huanianli@ThinkCentre:~/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
huanianli@ThinkCentre:~/workspace/kaiba$ 
huanianli@ThinkCentre:~/workspace/kaiba$ 
huanianli@ThinkCentre:~/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(-)
huanianli@ThinkCentre:~/workspace/kaiba$ 
huanianli@ThinkCentre:~/workspace/kaiba$ git log
commit c5221d81c91d45cda15e33c3bf0e82874d7fcc97
Author: Huanian Li <huanian.li@gmail.com>
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 <bjlhn@126.com>
Date:   Thu Jul 26 11:39:22 2018 +0800

    DaxiangLi: Add checking to foo.py

commit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <huanian.li@gmail.com>
Date:   Thu Jul 26 13:54:01 2018 +0800

    HuanianLi: Add Makefile

commit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800

    DaxiangLi: Add foo.py

commit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800

    Initialize the project by adding README.md
huanianli@ThinkCentre:~/workspace/kaiba$ 
huanianli@ThinkCentre:~/workspace/kaiba$ git push origin master
Username for 'https://github.com': HuanianLi
Password for 'https://HuanianLi@github.com': 
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
huanianli@ThinkCentre:~/workspace/kaiba$ 

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

daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/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
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git branch -a * dev
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/dev
  remotes/origin/master
  remotes/upstream/master

daxiangli@ThinkPad:~/workspace/kaiba$ vi foo.py
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/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(-)

daxiangli@ThinkPad:~/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)
 
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/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
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git push --force
Username for 'https://github.com': DaxiangLi
Password for 'https://DaxiangLi@github.com': 
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)
daxiangli@ThinkPad:~/workspace/kaiba$ 
  • 制造的沖突是故意將return (-1)改成return (-11)

  • 接下來我們發現,PR上就會顯示有沖突了!!

 

  •  沖突的細節在於foo.py的第8行

 

好吧,接下來DaxiangLi就需要去解決沖突了!

 

206 - DaxiangLi解決沖突 (P.S. 解決沖突不是很容易,請仔細看)

206.1 創建一個臨時分支dev-scratch為了演示得更清晰,這里故意刪除舊的空間,重新clone一遍,然后從頭開始

daxiangli@ThinkPad:~/workspace/kaiba$ git checkout -b dev-scratch dev
Switched to a new branch 'dev-scratch'

 

206.2 給臨時分支dev-scratch添加upstream的repo

daxiangli@ThinkPad:~/workspace/kaiba$ git remote add upstream https://github.com/HuanianLi/kaiba.git

 

206.3 讓臨時分支dev-scratch與upstream/master同步

daxiangli@ThinkPad:~/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

daxiangli@ThinkPad:~/workspace/kaiba$ git fetch upstream master
From https://github.com/HuanianLi/kaiba
 * branch            master     -> FETCH_HEAD

daxiangli@ThinkPad:~/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.

 

206.4 在臨時分支dev-scratch里合並沖突

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

 

206.5 將本地的臨時分支dev-scratch與本地開發分支dev做比較

daxiangli@ThinkPad:~/workspace/kaiba$ git diff dev..dev-scratch

 

206.6 切換到本地開發分支dev

daxiangli@ThinkPad:~/workspace/kaiba$ git checkout dev
Switched to branch 'dev'
Your branch is up-to-date with 'origin/dev'.

 

206.7 將臨時分支dev-scratch合並到開發分支dev

daxiangli@ThinkPad:~/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(-)

daxiangli@ThinkPad:~/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(-)
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git diff dev..dev-scratch
daxiangli@ThinkPad:~/workspace/kaiba$ 

 

206.8 把本地的開發dev強制推送到遠端的開發dev

daxiangli@ThinkPad:~/workspace/kaiba$ git push origin dev --force
Username for 'https://github.com': DaxiangLi
Password for 'https://DaxiangLi@github.com': 
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)

 

206.9 刪除本地的臨時分支dev-scratch

daxiangli@ThinkPad:~/workspace/kaiba$ git branch dev-scratch -D
Deleted branch dev-scratch (was c9af088).

OKAY, 沖突解決完成! 重新刷新PR, 發現沖突已經不存在啦。。。

 

207 - HuanianLi再次檢查PR,發現沒有沖突,將代碼Rebase and merge

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

  • 使用下面一組命令即可 (其中, [*]為關鍵命令)
 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

 

209 - DaxiangLi重新sync遠端的dev分支 (前面其實已經介紹過)

  • 使用下面的命令即可 (其中, [*]為關鍵命令)
 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

說明: 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被自動關閉

參考資料:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM