GitHub多人协作简明教程

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

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

  • HuanianLi: https://github.com/huanianli  # Maintainer
  • DaxiangLi: https://github.com/daxiangli  # Contributor

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.com3        name = Huanian Li4    [core]5        editor = vim6    [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.md1    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.md1 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 +0800Initialize 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/kaibac0bd2ed..b8a0b63  master     -> origin/master
Updating c0bd2ed..b8a0b63
Fast-forwardfoo.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 +0800Merge pull request #1 from DaxiangLi/devDaxiangLi: 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 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize the project by adding README.md
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git branch -a
* masterremotes/origin/HEAD -> origin/masterremotes/origin/devremotes/origin/masterremotes/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.gitc0bd2ed..640f6f6  master -> master
daxiangli@ThinkPad:~/workspace/kaiba$

102 - DaxiangLi 切换到dev分支

daxiangli@ThinkPad:~/workspace/kaiba$ git branch -a
* masterremotes/origin/HEAD -> origin/masterremotes/origin/devremotes/origin/masterremotes/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 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize the project by adding README.md
daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git branch -a
* devmasterremotes/origin/HEAD -> origin/masterremotes/origin/devremotes/origin/masterremotes/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 sysdef main(argc, argv):
+    if argc != 2:
+        sys.stderr.write("Usage: %s <num>\n" % argv[0])
+        return 1
+i = 0while 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.pyno 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.py1 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 +0800DaxiangLi: add checking to foo.pycommit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize 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 +0800DaxiangLi: add checking to foo.pydiff --git a/foo.py b/foo.py
index 55568dd..4ca134c 100644
--- a/foo.py
+++ b/foo.py
@@ -3,6 +3,10 @@import sysdef main(argc, argv):
+    if argc != 2:
+        sys.stderr.write("Usage: %s <num>\n" % argv[0])
+        return 1
+i = 0while 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.git640f6f6..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 sysdef main(argc, argv):if argc != 2:sys.stderr.write("Usage: %s <num>\n" % argv[0])
-        return 1
+        return (-1)i = 0while i < int(argv[1]):print "%02d: Hello World." % ii += 1-    return 0
+    return (0)if __name__ == '__main__':argv = sys.argvdaxiangli@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 +0800DaxiangLi: add checking to foo.py (2)commit e1bb21ee432a56fe83d8b3d79048d1623dde0b4d
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 11:39:22 2018 +0800DaxiangLi: add checking to foo.pycommit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize 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.gite1bb21e..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 +0800DaxiangLi: add checking to foo.py (2)commit e1bb21ee432a56fe83d8b3d79048d1623dde0b4d
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 11:39:22 2018 +0800DaxiangLi: add checking to foo.pycommit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize 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.pyDate: Thu Jul 26 11:39:22 2018 +08001 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 +0800DaxiangLi: add checking to foo.pycommit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize 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 +0800DaxiangLi: add checking to foo.pydiff --git a/foo.py b/foo.py
index 55568dd..84b0787 100644
--- a/foo.py
+++ b/foo.py
@@ -3,12 +3,16 @@import sysdef main(argc, argv):
+    if argc != 2:
+        sys.stderr.write("Usage: %s <num>\n" % argv[0])
+        return (-1)
+i = 0while i < int(argv[1]):print "%02d: Hello World." % ii += 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.pyDate: Thu Jul 26 11:39:22 2018 +08001 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 +0800DaxiangLi: Add checking to foo.pycommit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize 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 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize 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 Makefile1 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 +0800HuanianLi: Add Makefilecommit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize the project by adding README.md
huanianli@ThinkCentre:~/workspace/kaiba$ git branch -a
* masterremotes/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.git640f6f6..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 +0800DaxiangLi: Add checking to foo.pycommit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <huanian.li@gmail.com>
Date:   Thu Jul 26 13:54:01 2018 +0800HuanianLi: Add Makefilecommit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize the project by adding README.md
huanianli@ThinkCentre:~/workspace/kaiba$ 

 

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

daxiangli@ThinkPad:~/workspace/kaiba$ 
daxiangli@ThinkPad:~/workspace/kaiba$ git branch 
* devmaster
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 branchdev
* 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/kaiba640f6f6..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 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize 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 +0800DaxiangLi: Add checking to foo.pycommit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <huanian.li@gmail.com>
Date:   Thu Jul 26 13:54:01 2018 +0800HuanianLi: Add Makefilecommit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize 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.git640f6f6..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 branchdev
* 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
* devmaster
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 +0800DaxiangLi: Add checking to foo.pycommit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize 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 +0800DaxiangLi: Add checking to foo.pycommit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <huanian.li@gmail.com>
Date:   Thu Jul 26 13:54:01 2018 +0800HuanianLi: Add Makefilecommit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize 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
* masterremotes/origin/HEAD -> origin/masterremotes/origin/devremotes/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
* devmaster
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 += 1return (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 while1 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 +0800DaxiangLi: Update foo.py to use for instead of whilecommit 27aca2bcc0fcffb26828cac1eebe517439ef49c9
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 11:39:22 2018 +0800DaxiangLi: Add checking to foo.pycommit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <huanian.li@gmail.com>
Date:   Thu Jul 26 13:54:01 2018 +0800HuanianLi: Add Makefilecommit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize 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.git27aca2b..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 +0800DaxiangLi: Update foo.py to use for instead of whilecommit 27aca2bcc0fcffb26828cac1eebe517439ef49c9
Author: Daxiang Li <bjlhn@126.com>
Date:   Thu Jul 26 11:39:22 2018 +0800DaxiangLi: Add checking to foo.pycommit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <huanian.li@gmail.com>
Date:   Thu Jul 26 13:54:01 2018 +0800HuanianLi: Add Makefilecommit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize 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 +08001 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 +0800DaxiangLi: 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 +0800DaxiangLi: Add checking to foo.pycommit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <huanian.li@gmail.com>
Date:   Thu Jul 26 13:54:01 2018 +0800HuanianLi: Add Makefilecommit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize 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 +0800DaxiangLi: Add checking to foo.pycommit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <huanian.li@gmail.com>
Date:   Thu Jul 26 13:54:01 2018 +0800HuanianLi: Add Makefilecommit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize 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 sysdef main(argc, argv):if argc != 2:sys.stderr.write("Usage: %s <num>\n" % argv[0])
-        return (-1)
+        return -1i = 0while i < int(argv[1]):print "%02d: Hello World." % ii += 1-    return (0)
+    return 0if __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 +0800HuanianLi: 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 +0800DaxiangLi: Add checking to foo.pycommit 3609dff98de5a17a09484738328a0e9db1784e0d
Author: Huanian Li <huanian.li@gmail.com>
Date:   Thu Jul 26 13:54:01 2018 +0800HuanianLi: Add Makefilecommit 640f6f63f4634915b4e4ed195e9a48d31cabb893
Author: Daxiang Li <bjlhn@126.com>
Date:   Wed Jul 25 18:15:38 2018 +0800DaxiangLi: Add foo.pycommit c0bd2ed35e10180209726199af422a63a007355f
Author: Huanian Li <huanian.li@gmail.com>
Date:   Wed Jul 25 16:21:43 2018 +0800Initialize 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.git27aca2b..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
* devmasterremotes/origin/HEAD -> origin/masterremotes/origin/devremotes/origin/masterremotes/upstream/masterdaxiangli@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 +08001 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 sysdef 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 sysdef 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 HEADfoo.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 +08001 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被自动关闭

参考资料:

  • Git教程
  • A successful Git branching model
  • 怎样在github上协同开发
  • 使用git和github进行协同开发流程
  • GitHub实现多人协同提交代码并且权限分组管理

转载于:https://www.cnblogs.com/idorax/p/9366035.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/353227.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2020地区mysql表_2020年甘肃省军队文职考试职位表下载:张掖地区招13人

2020年6月15日全军面向社会招考文职人员公告已发布&#xff0c;全国招聘27073人&#xff0c;甘肃省招聘370人&#xff0c;其中张掖地区总共招聘13人。此次考试博士招考岗位报名时间为2020年6月17日至21日&#xff0c;其他招考岗位报名时间为7月1日至10日。考试时间为2020年8月2…

superhot预告片下载_预告片:裸指关节SOA

superhot预告片下载我正在研究这个想法&#xff0c;但我不知道它是否对你们有吸引力。 我想就您是否需要进一步探讨提出您的意见。 这是一笔交易&#xff1a;我遇到了一些团队&#xff0c;这些团队在使用SOA技术时由于其工具的绝对复杂性而陷入泥潭。 我只在Java中看到过这种情…

多少秒算长镜头_下中国象棋,能算多少步才算高手?

下象棋&#xff0c;你能算多少步&#xff1f;这是一个让初学者很困扰&#xff0c;也很感兴趣的话题。 很多象棋爱好者说&#xff1a;我最多看2步&#xff0c;我觉得能看5步以上的&#xff0c;就是超级高手高手高高手了。 但一代象棋宗师、14届全国冠军胡荣华的看法则颇有“玄学…

对基于消息队列的Activiti异步执行器进行基准测试

一点历史 永不停息​​的一件事是&#xff0c;Activiti如何以惊人的规模在一些大型组织中使用。 过去&#xff0c;这导致了各种优化和重构&#xff0c;其中包括异步执行器-替换旧的作业执行器。 对于未启动的用户&#xff1a;这些执行器在流程实例中处理计时器和异步继续。 特别…

2020德勤面试开始了吗_2020公务员面试公告已出,5月28日开始面试

重磅&#xff01;上海市2020年度考试录用公务员职位报名及面试工作公告出了&#xff01;报岗时间&#xff1a;2020年5月11日10:00至5月15日18:00岗位调剂&#xff1a;2020年5月18日10:00至5月20日18:00面试时间&#xff1a;2020年5月28日至6月1日面试时需携带哪些证件和材料?答…

阿米洛键盘取消win_阿米洛花旦娘静电容V2键盘测评:不止是一把好看的键盘

文丨me王bigfun社区原文地址&#xff1a;【开箱/测评】阿米洛花旦娘静电容V2键盘&#xff0c;不止是一把好看的键盘 - bigfun序&#xff1a;我想要换一把好的键盘&#xff0c;因为这把雷柏的V500键盘已经跟了我4年&#xff0c;现在的它又老又丑&#xff0c;抚摸起来的手感还很生…

NY : 括号匹配问题

括号配对问题 时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;3描述现在&#xff0c;有一行括号序列&#xff0c;请你检查这行括号是否配对。 输入第一行输入一个数N&#xff08;0<N<100&#xff09;,表示有N组测试数据。后面的N行输入多…

【代码笔记】Web-ionic-select

一&#xff0c;效果图。 二&#xff0c;代码。 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>Todo</title> <meta name"viewport" content"initial-scale1, maximum-scale1, user-scalableno…

adf开发_ADF:动态视图对象

adf开发今天&#xff0c;我想写有关动态视图对象的信息&#xff0c;该对象允许我在运行时更改其数据源&#xff08;SQL查询&#xff09;和属性。 我将使用oracle.jbo.ApplicationModule :: createViewObjectFromQueryStmt方法来解决此问题。 我将逐步介绍如何执行此操作 创建…

stm32f407能跑linux吗_跑步能跑进医院?那我该做跑步运动吗?想健康一点太难了...

跑步能跑进医院&#xff1f;那我该做跑步运动吗&#xff1f;想健康一点太难了&#xff0c;小编学生时期最喜欢的课程永远都是体育课&#xff0c;但最头疼的项目却是磨人的800米和1000米&#xff0c;那简直是我的的噩梦&#xff0c;近日&#xff0c;西安一名初中生跑步居然跑进了…

60秒内使用Java 9的Project Jigsaw的JavaFX HelloWorld

到目前为止&#xff0c;您可能已经听说过Java 9的新模块系统&#xff0c;即项目Jigsaw。 如果您不了解Java 9的新模块系统&#xff0c;则应访问Mark Reinhold的论文“模块系统的状态” 。 此外&#xff0c;您还应该访问nipafx Nicolai Parlog的出色博客&#xff0c; 网址为http…

互补输出级采用共集形式是为了使_天津大学胡文平《先进材料》:溶液法制备厘米级高度取向有机晶体阵列,可用于高性能有机场效应晶体管...

有机场效应晶体管(OFET)以其低成本和柔性受到了广泛关注&#xff0c;在显示驱动、射频识别标签和逻辑电路等方面具有潜在应用。包括小分子材料和共轭聚合物在内的可溶性有机半导体(OSCs)由于其可溶液加工而引起了许多研究者的兴趣&#xff0c;这种溶液可加工性可通过在柔性基底…

c++ 显示图片_飞利浦256P1FR显示器一线直连MacBook使用体验分享

前言嗨&#xff0c;大家好&#xff0c;我是默咖&#xff0c;一个喜欢分享的数码控。最近刚忙完给媳妇升级桌面&#xff0c;自己就忍不住想要换一个Type-C直连MacBook Pro的显示器了&#xff0c;不仅仅为了可以单线直连MacBook Pro也是为了减少拓展坞再接一个转接头的麻烦&#…

ghost快速安装系统的详细步骤?

很多时候我们安装系统都是在很快的时间内给安装完毕&#xff0c;不用像原来那样安装一个系统需要一个多小时&#xff0c;有了ghost是比较方便&#xff0c;十几分钟就可以把系统安装完&#xff0c;这也是DIY爱好者的福音&#xff0c;没有事情的时候安装下自己的系统&#xff0c;…

python安装库报错Microsoft visual c++ 14.0 is required问题解决办法

下载安装包安装即可&#xff1a; https://964279924.ctfile.com/fs/1445568-239446865 or http://www.liangchan.net/liangchan/10220.html转载于:https://www.cnblogs.com/stkares/p/9384424.html

Apache PDFBox命令行工具:无需Java编码

在博客文章Apache PDFBox 2中 &#xff0c;我演示了将Apache PDFBox 2用作从Java代码中调用的库来操作PDF。 事实证明&#xff0c;Apache PDFBox 2还提供了可以直接从命令行直接使用的命令行工具 &#xff0c;而无需其他Java编码。 有几种命令行工具可用&#xff0c;我将在本文…

在分析了47,251个依赖关系之后,2016年排名前100的Java库

谁在上面&#xff0c;谁在后面&#xff1f; 我们分析了Github上的47,251个依赖关系&#xff0c;并抽取了前100个Java库 长周末我们最喜欢的消遣是浏览Github并搜索流行的Java库。 我们决定与您分享乐趣和信息。 我们分析了Github上前3,862个Java项目使用的12,059个独特Java库…

tortoise清理本地分支_本地:延庆运污水环卫抽化粪池

北京兴百荣清洁公司是清理排水管道的技术服务中心。提供下水道疏通&#xff0c;化粪池清理&#xff0c;抽污水&#xff0c;化粪池清掏&#xff0c;管道清淤&#xff0c;下水道清洗&#xff0c;化粪池清理&#xff0c;抽粪&#xff0c;管道疏通&#xff0c;雨水管道清理&#xf…

win7(windows 7)系统下安装SQL2005(SQL Server 2005)图文教程

由于工作需要&#xff0c;今天要在电脑上安装SQL Server 2005。以往的项目都是使用Oracle&#xff0c;MS的数据库还真的没怎么用过&#xff0c;安装Oracle已经轻车熟路&#xff0c;但装SQL Server好像还有点小麻烦&#xff0c;所以记录下来&#xff0c;以留备用。 ------------…

抓娃娃机爪不动怎么办_黄子韬吃娃娃菜能把临时牙咬断?种植牙到底结实不结实?...

黄子韬的临时牙上热搜了&#xff0c;最高排名热搜榜第四位。有关牙齿的事儿瞬间让我这个口腔医生来了八卦之心&#xff0c;在看了后面的各种评论之后&#xff0c;我大概梳理清楚这到底是怎么回事了&#xff1a;小时候因为调皮所以摔断了门牙&#xff0c;前些日子门牙做了种植牙…