Git 之四 - Git 对 Github 远程库的操作

Git 的四个工作区域

ad

创建远程库与本地库

1
2
3
4
5
# 登录Github的Web页面创建远程库,并记录如下的远程库地址
# https://github.com/xxxx/remote-test.git

# 创建本地库,建议本地库的名称与远程库的名称一致
$ git init remote-test

Git 配置远程库别名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 进入本地库的根目录
$ cd remote-test

# 查看远程库别名
$ git remote -v

# 添加远程库别名,例如下面远程库的别名是origin,地址是Github远程仓库的Https URL
$ git remote add origin https://github.com/xxxx/remote-test.git

# 删除远程库别名
$ git remote rm origin

# 重命名远程库别名
$ git remote rename origin origin2

Git 远程库的 Pull 与 Push 操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 进入本地库的根目录
$ cd remote-test

# 从远程库origin的master分支Pull(拉取)最新到工作区,并在工作区进行合并(Merge)操作,origin是远程库别名,master是远程库分支的名称
$ git pull origin master

# 创建新文件
$ touch api.json

# 添加新文件到暂存区
$ git add api.json

# 添加新文件到本地库
$ git commit api.json -m 'update'

# 将最新的文件Push(推送)到远程库origin的master分支,origin是远程库别名,master是远程库分支的名称;如果Pull到Github的远程仓库(Https URL),默认会提示输入Github的帐号和密码
$ git push origin master

Git 远程库的 Clone 操作

1
2
3
4
5
6
7
8
9
10
# 将远程库Clone到本地,默认分支是master
$ git clone https://github.com/xxxx/remote-test.git

# 或者Clone远程库到本地,并指定本地目录的名称,默认分支是master
$ git clone https://github.com/xxxx/remote-test.git remote-project

# 上述命令的作用:
# 初始化本地库,即执行"git init"命令
# 完整地把远程库的master分支Pull下来,即执行"git pull"命令
# 创建远程库别名(origin + 远程库地址),即执行"git remote add"命令

Git 远程库的 Fetch 操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 首次执行会创建本地库origin的master分支(origin/master),然后从远程库origin的master分支Fetch(抓取)最新到本地库origin的master分支(origin/master),不影响当前工作区的内容
$ git fetch origin master

# 查看本地库的master分支与本地库origin的master分支(origin/master)的差异
$ git diff master origin/master

# 或者
$ git diff HEAD FETCH_HEAD

# 合并本地库origin的master分支(origin/master)到本地库的master分支
$ git merge origin/master

# 或者
$ git merge FETCH_HEAD

# 指令Pull与Fetch的区别: Pull = Fetch + Merge

解决 Pull 操作产生的冲突

Pull = Fetch + Merge,也就是说根本问题是 “如何解决合并分支后产生的冲突”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 从远程库origin的master分支Pull(拉取)最新到工作区,并在工作区进行合并(Merge)操作,假设此时Git提示有文件产生冲突
# git pull origin master

# 第一步,手动编辑产生冲突的文件,并修改文件内容,直至冲突的文件内容都修改掉
$ vim api.json
<<<<<<< HEAD
edit by hot_fix s
=======
edit by hot_fix2
>>>>>>> master

# 第二步,标记冲突已解决,将之前产生冲突的文件添加到暂存区
$ git add api.json

# 第三步,提交修改,此时commit参数不能带具体文件名
$ git commit -m 'update message'

解决 Push 失败的问题

如果不是基于远程库的最新版本所做的修改,不能进行 Push 操作,必须先将远程库最新版本的文件 Pull 下来再进行 Push 操作。Pull 下来之后如果文件产生冲突,则按照上面” 解决 Pull 操作产生的冲突” 的步骤进行操作。

Git 远程库的分支创建操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 本地创建分支
$ git branch develop

# 本地切换到指定分支
$ git checkout develop

# 将分支代码添加到暂存区
$ git add --all

# 将分支代码提交到本地库
$ git commit -am 'create branch develop'

# 将分支代码Push到远程库的分支,此时远程库会自动创建分支
$ git push origin develop

SSH 免密码登录 Github

当远程库的地址是基于 HTTPS 协议的时候,每次 Push 操作都需要手动输入 Github 的用户名和密码;Windows 系统下会自动保存凭据(帐号信息),可以避免每次都手动输入帐号信息;而 Linux 下则没有自动保存凭据的功能,因此 Github 官方提供了基于 SSH 免密码登录的方式进行 Push 操作,以此来解决每次都要输入帐号信息的问题;SSH 免密码登录的方式同样适用于 Windows 系统,此方法的局限性在于本地只能操作一个 Github 帐号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ cd ~/.ssh

# 生成SSH的公钥文件id_rsa.pub与私钥文件id_rsa,并指定邮箱地址
$ ssh-keygen -t rsa -C xxxx@gmail.com

# 或者指定公钥和私钥文件的文件名
$ ssh-keygen -t rsa -C xxxx@gmail.com -f id_rsa.github

# 将公钥文件id_rsa.pub的文本内容复制到Github相应的SSH Keys配置页面
$ cat id_rsa.pub

# 进入本地库的根目录
$ cd remote-test

# 删除旧的远程库别名
$ git remote rm origin

# 添加新的远程库别名,远程库的地址基于SSH协议
$ git remote add origin git@github.com:xxxx/remote-test.git

# 测试使用“SSH免密码登录”的方式进行Push操作
$ git push origin master

Github Fork 的项目和上游项目同步代码

当成功 Fork 一个项目后,无论怎么修改 Fork 出来的项目,原来的项目(Github 叫做 upstream,一般译作上游项目)是不会受到影响的,这在上游项目来说自然是极好的保护。但是 Fork 出来的项目如何能够及时反映上游项目的变更呢?这就首先需要设置本地项目的 “远程仓库” 属性,即告诉 Git 命令,本地项目的上游项目是哪一个,比如下面针对 weld-core 项目举例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 设置上游的远程仓库
$ git remote add upstream https://github.com/weld/core

# 查看所有远程仓库
$ git remote -v
origin https://github.com/subaochen/core.git (fetch)
origin https://github.com/subaochen/core.git (push)
upstream https://github.com/weld/core (fetch)
upstream https://github.com/weld/core (push)

# 将上游远程仓库的最新变化同步到本地
$ git fetch upstream

# 查看当前项目的所有分支
$ git branch -a
* 2.0
remotes/origin/1.1
remotes/origin/1.2
remotes/origin/2.0
remotes/origin/2.0.0
remotes/origin/2.0.0.Beta5-branch
remotes/origin/HEAD -&gt; origin/2.0
remotes/origin/master
remotes/upstream/1.1
remotes/upstream/1.2
remotes/upstream/2.0
remotes/upstream/2.0.0
remotes/upstream/2.0.0.Beta5-branch
remotes/upstream/2.1
remotes/upstream/2.2
remotes/upstream/2.2.0
remotes/upstream/2.3
remotes/upstream/eap6.2.x
remotes/upstream/master
remotes/upstream/weld-osgi-2.x

# 确保本地代码的分支设置得当,一般设置为 origin/master
$ git checkout origin/master

# 合并上游远程仓库和本地仓库的代码(即将分支 origin/master 与 upstream/master 合并在一起)
$ git merge upstream/master

# 提交本地变更,Push 代码到 origin/master
$ git push origin master

# 其实同步上游远程仓库代码的步骤,可以合并成一条命令,该命令相当于上面的:fetch + merge
# 第一个参数 upstream 表示远程仓库的 upstram/master 分支
# 第二个参数 master 表示本地 Fork 库的 origin/master 分支
$ git pull upstream master

Git 从远程仓库获取特定分支

1
2
3
4
5
6
7
8
9
10
# 列出远程仓库的所有分支
$ git branch -a
remotes/origin/dev
remotes/origin/release

# 拉取特定的远程分支,例如checkout远程的origin/dev分支,并在本地将其命名为dev分支,同时切换到本地的dev分支
$ git checkout -b dev origin/dev

# 切换回master分支
$ git checkout master

清空 Github 特定的仓库

清空 Github 特定的仓库,而不是删除并重新创建仓库,同时保留本地仓库原来的所有文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 创建临时的仓库目录(保证不对本地仓库原来的文件进行任何操作)
$ mkdir -p /tmp/reset-repo

# 进入临时仓库目录
$ /tmp/reset-repo

# 创建README.md(必须得有一个文件)
$ touch README.md

# 初始化Git
$ git init
$ git add .
$ git commit -m "Initial commit"

# 重新设置源仓库的地址
$ git remote add origin git@github.com:<YOUR ACCOUNT>/<YOUR REPOS>.git

# 重新Push到源仓库(这里演示使用的是master分支)
$ git push -u --force origin master

.gitignore 常用模板