什么是DevOps





什么是持续化部署





| 主机名 |       ip       | 备注 |
| :----: | :------------: | :--: |
|  test  | 192.168.188.60 | git  |

### 工作原理

![](https://figure-bed-1304788733.cos.ap-guangzhou.myqcloud.com/typora/202204181148000.png#alt=image-20220418114756740)

Workspace：工作区
Index / Stage：暂存区
Repository：仓库区（或本地仓库）
Remote：远程仓库

登录远程仓库的方式：

http方式：[https://github.com/ops-weibowen/Test1.git](https://github.com/ops-weibowen/Test1.git)
ssh秘钥方式：git@github.com:ops-weibowen/testgit.git

理解工作区与暂存区的区别？

工作区：就是你在电脑上看到的目录，比如目录下testgit里的文件(.git隐藏目录版本库除外)。
或者以后需要再新建的目录文件等等都属于工作区范畴。

版本库(Repository)：工作区有一个隐藏目录.git，这个不属于工作区，这是版本库。
其中版本库里面存了很多东西，其中最重要的就是stage(暂存区)，
还有Git为我们自动创建了第一个分支master，以及指向master的一个指针HEAD。

我们前面使用Git提交文件到版本库有两步：

第一步：是使用 git add 实际上就是把文件添加到暂存区。
第二步：使用git commit 提交更改，实际上就是把暂存区的所有内容提交到当前分支上。



git官网：https://git-scm.com/download/linux

### 安装与操作

#### 1.配置阿里源的epel源

```shell
[root@test ~]# yum -y install wget
[root@test ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
[root@test ~]# yum makecache
```

#### 2.yum安装

```shell
[root@test ~]# yum install -y git

# 因为git 的子命令比较多，建议安装上  bash 自动补齐功能扩展
[root@test ~]# yum -y install bash-completion bash-completion-extras

# 验证
[root@test ~]# git --version
git version 1.8.3.1
```

#### 3.设置标识

**输入本机操作人的相关信息：**
**因为Git是分布式版本控制系统，所以需要填写用户名和邮箱作为一个标识。**
**注意：git config --global 参数，有了这个参数，表示你这台机器上所有的Git仓库都会使用这个配置，当然也可以对某个仓库指定的不同的用户名和邮箱。企业一般用来区分不同项目组的仓库**

```shell
[root@test ~]# git config --global user.name "shy"
[root@test ~]# git config --global user.email "2364695562@qq.com"
```

#### 4.创建并初始化版本库

```shell
[root@test ~]# mkdir /opt/code   # 创建一个工作空间
[root@test ~]# cd /opt/code/   # 进入空间
[root@test code]# git init   # 初始化
初始化空的 Git 版本库于 /opt/code/.git/

[root@test code]# ls -al
总用量 0
drwxr-xr-x  3 root root  18 4月  18 11:18 .
drwxr-xr-x. 4 root root  29 4月  18 11:17 ..
drwxr-xr-x  7 root root 119 4月  18 11:18 .git
```

#### 5.提交到仓库

```shell
[root@test code]# echo "这是第一次提交" >> README.md   # 在code工作区间 创建一个文本文件README.md，内容为这是第一次提交
[root@test code]# git add .   # 把所有文件从工作区，放入暂存区；没有任何显示，说明添加成功。
[root@test code]# echo "这是第二次提交" >> README.md
[root@test code]# git add README.md   # 把指定文件从工作区，放入暂存区
[root@test code]# git commit -m "第一次正式提交"   # 把文件从 暂存区提交到仓库；-m 后面输入的是本次提交的说明，可以输入任意内容，输入说明对自己对别人阅读都很重要
[master（根提交） 1fb223e] 第一次正式提交
 1 file changed, 2 insertions(+)
 create mode 100644 README.md
[root@test code]# git status   # 查看git的状态
# 位于分支 master
无文件要提交，干净的工作区

[root@test code]# git log   # 查看提交历史
commit 1fb223ecdcd8bb8490c3a23405347235ef4fa826
Author: shy <2364695562@qq.com>
Date:   Mon Apr 18 11:25:05 2022 +0800

    第一次正式提交
 
 
 
[root@git code]# echo "today is a good day" >>b1.txt
[root@git code]# git status 
# 位于分支 master
# 未跟踪的文件:
#   （使用 "git add <file>..." 以包含要提交的内容）
#
#	b1.txt
提交为空，但是存在尚未跟踪的文件（使用 "git add" 建立跟踪）



# 修改未提交状态
[root@git code]# echo 789 >b1.txt 
[root@git code]# git status 
# 位于分支 master
# 要提交的变更：
#   （使用 "git reset HEAD <file>..." 撤出暂存区）
#
#	新文件：    b1.txt
#
# 尚未暂存以备提交的变更：
#   （使用 "git add <file>..." 更新要提交的内容）
#   （使用 "git checkout -- <file>..." 丢弃工作区的改动）
#
#	修改：      b1.txt




# 对比查看修改了什么,拿工作区的文件与已添加到暂存区的文件进行对比，若已添加到暂存区，则无法对比		
[root@git code]# git diff b1.txt
diff --git a/b1.txt b/b1.txt
index 9f358a4..0c2b781 100644
--- a/b1.txt
+++ b/b1.txt
@@ -1 +1 @@
-123456
+789
```



撤出暂存区

```
[root@git code]# git reset b1.txt
[root@git code]# git status
# 位于分支 master
# 未跟踪的文件:
#   （使用 "git add <file>..." 以包含要提交的内容）
#
#	b1.txt
提交为空，但是存在尚未跟踪的文件（使用 "git add" 建立跟踪）
```









#### 6.拉取仓库到本地

```shell
[root@test ~]# cd /opt/code/
[root@test code]# git clone https://gitee.com/kangjie1209/monitor.git
正克隆到 'monitor'...
remote: Enumerating objects: 435, done.
remote: Total 435 (delta 0), reused 0 (delta 0), pack-reused 435
接收对象中: 100% (435/435), 8.78 MiB | 2.97 MiB/s, done.
处理 delta 中: 100% (54/54), done.
[root@test code]# ls
monitor  README.md
```

#### 7.查看历史版本记录

```shell
[root@test code]# git log
commit a35bb11a753f9ff92b8ce2773d907088a3218d8b
Author: shy <2364695562@qq.com>
Date:   Mon Apr 18 13:38:49 2022 +0800

    第三次正式提交

commit 509567032c13fc3d1a1c37b76aa4424619f2791f
Author: shy <2364695562@qq.com>
Date:   Mon Apr 18 13:36:16 2022 +0800

    第二次正式提交

commit 1fb223ecdcd8bb8490c3a23405347235ef4fa826
Author: shy <2364695562@qq.com>
Date:   Mon Apr 18 11:25:05 2022 +0800

    第一次正式提交
```

#### 8.查看操作日志

```shell
[root@test code]# git reflog		#git log命令的精简版
a35bb11 HEAD@{0}: commit: 第三次正式提交
5095670 HEAD@{1}: commit: 第二次正式提交
1fb223e HEAD@{2}: commit (initial): 第一次正式提交


```

#### 9.回退操作

```shell
[root@git code]# echo this is a funny day >index.html
[root@git code]# ll
总用量 12
-rw-r--r-- 1 root root 20 10月 25 11:17 a1.txt
-rw-r--r-- 1 root root 20 10月 25 14:26 index.html
-rw-r--r-- 1 root root 44 10月 25 10:34 README.md
[root@git code]# git status
# 位于分支 master
# 未跟踪的文件:
#   （使用 "git add <file>..." 以包含要提交的内容）
#
#	index.html
提交为空，但是存在尚未跟踪的文件（使用 "git add" 建立跟踪）
[root@git code]# git add .
[root@git code]# git status
# 位于分支 master
# 要提交的变更：
#   （使用 "git reset HEAD <file>..." 撤出暂存区）
#
#	新文件：    index.html
#
[root@git code]# git commit -m "增加一个HTML页面"
[master cf74199] 增加一个HTML页面
 1 file changed, 1 insertion(+)
 create mode 100644 index.html
[root@git code]# git log
commit cf741998a4df5c955580462ff10ffb6aeb253a73
Author: kelvinlin123 <429496374@qq.com>
Date:   Tue Oct 25 14:27:16 2022 +0800

    增加一个HTML页面

commit 2aa182668600eb855b745a4da8e5f382f442d810
Author: kelvinlin123 <429496374@qq.com>
Date:   Tue Oct 25 11:20:41 2022 +0800

    a1.txt测试

commit b46b58f04045634eaeb2bedcb2e675f8a23d0dff
Author: kelvinlin123 <429496374@qq.com>
Date:   Tue Oct 25 10:38:05 2022 +0800

    提交到本地仓库测试
[root@git code]# git reflog
cf74199 HEAD@{0}: commit: 增加一个HTML页面
2aa1826 HEAD@{1}: commit: a1.txt测试
b46b58f HEAD@{2}: commit (initial): 提交到本地仓库测试
[root@git code]# git reset --hard 2aa1826
HEAD 现在位于 2aa1826 a1.txt测试
[root@git code]# git reflog
2aa1826 HEAD@{0}: reset: moving to 2aa1826
cf74199 HEAD@{1}: commit: 增加一个HTML页面
2aa1826 HEAD@{2}: commit: a1.txt测试
b46b58f HEAD@{3}: commit (initial): 提交到本地仓库测试

[root@git code]# ll
总用量 8
-rw-r--r-- 1 root root 20 10月 25 11:17 a1.txt
-rw-r--r-- 1 root root 44 10月 25 10:34 README.md
此时，你会发现并没有index.html文件

[root@git code]# git reset --hard cf74199		#再回退到“增加一个HTML页面”
HEAD 现在位于 cf74199 增加一个HTML页面
[root@git code]# git reflog
cf74199 HEAD@{0}: reset: moving to cf74199
b46b58f HEAD@{1}: reset: moving to b46b58f
2aa1826 HEAD@{2}: reset: moving to 2aa1826
cf74199 HEAD@{3}: commit: 增加一个HTML页面
2aa1826 HEAD@{4}: commit: a1.txt测试
b46b58f HEAD@{5}: commit (initial): 提交到本地仓库测试
[root@git code]# ll
总用量 12
-rw-r--r-- 1 root root 20 10月 25 15:13 a1.txt
-rw-r--r-- 1 root root 20 10月 25 15:13 index.html
-rw-r--r-- 1 root root 44 10月 25 15:10 README.md

此时,index.html文件又回复了
```

**git reset --hard HEAD^ 命令可以回滚到上一个 版本， ^^ 表示上上一个版本，依次类推**
**如果想回退更多的版本， 可以使用   git reset --hard HEAD~10 ， 向后回退 10个版本**
**如果我们想回退到 任意一个 指定 的版本，可以使用 它的  版本号信息**
**git reset --hard   a35bb11**
**通常写 commit 版本号的前7位即可**

#### 10.撤销操作（针对本地仓库有文件的情况下）

**10.1 未提交到远程仓库**

```shell
[root@test code]# echo "这是第三次提交" >> README.md   # 追加新内容进去
[root@git code]# cat README.md 
这是第一次提交
这是第二次提交
这是第三次提交
[root@test code]# git status   # 未提交
# 位于分支 master
# 尚未暂存以备提交的变更：
#   （使用 "git add <file>..." 更新要提交的内容）
#   （使用 "git checkout -- <file>..." 丢弃工作区的改动）
#
#	修改：      README.md
#
修改尚未加入提交（使用 "git add" 和/或 "git commit -a"）
[root@test code]# git checkout README.md   # 撤销操作
[root@test code]# git status
# 位于分支 master
无文件要提交，干净的工作区
[root@test code]# git reflog   # 因为没有提交到仓库里面，所以没有记录
f69c6a5 HEAD@{0}: reset: moving to f69c6a5
a35bb11 HEAD@{1}: reset: moving to a35bb11
f69c6a5 HEAD@{2}: commit: 增加一个HTML页面
a35bb11 HEAD@{3}: commit: 第三次正式提交
5095670 HEAD@{4}: commit: 第二次正式提交
1fb223e HEAD@{5}: commit (initial): 第一次正式提交

[root@git code]# cat README.md 
这是第一次提交
这是第二次提交
注：此时发现文件已经复原
```

**10.2 已提交未到仓库**

```shell
[root@git code]# echo 这是第三次提交 >>README.md 
[root@git code]# git add .
[root@git code]# git status 
# 位于分支 master
# 要提交的变更：
#   （使用 "git reset HEAD <file>..." 撤出暂存区）
#
#	修改：      README.md
#
[root@git code]# git reset HEAD README.md 
重置后撤出暂存区的变更：
M	README.md
[root@git code]# cat README.md 
这是第一次提交
这是第二次提交
这是第三次提交
[root@git code]# git status
# 位于分支 master
# 尚未暂存以备提交的变更：
#   （使用 "git add <file>..." 更新要提交的内容）
#   （使用 "git checkout -- <file>..." 丢弃工作区的改动）
#
#	修改：      README.md
#
修改尚未加入提交（使用 "git add" 和/或 "git commit -a"）
[root@git code]# git checkout README.md
[root@git code]# cat README.md 
这是第一次提交
这是第二次提交
```

#### 11.删除文件及恢复

```shell
[root@test code]# ls
index.html  monitor  README.md
[root@test code]# git rm index.html   # 删除index.html并提交到仓库
rm 'index.html'
[root@test code]# git status
# 位于分支 master
# 要提交的变更：
#   （使用 "git reset HEAD <file>..." 撤出暂存区）
#
#	删除：      index.html
#
[root@test code]# git commit -m "delete index.html"
[master 32b9f84] delete index.html
 1 file changed, 1 deletion(-)
 delete mode 100644 index.html
[root@test code]# ls
monitor  README.md
[root@test code]# git reflog
32b9f84 HEAD@{0}: commit: delete index.html
f69c6a5 HEAD@{1}: reset: moving to f69c6a5
a35bb11 HEAD@{2}: reset: moving to a35bb11
f69c6a5 HEAD@{3}: commit: 增加一个HTML页面
a35bb11 HEAD@{4}: commit: 第三次正式提交
5095670 HEAD@{5}: commit: 第二次正式提交
1fb223e HEAD@{6}: commit (initial): 第一次正式提交
[root@test code]# git reset f69c6a5   # 通过head恢复
重置后撤出暂存区的变更：
D	index.html
[root@test code]# ls
monitor  README.md
[root@test code]# git status
# 位于分支 master
# 尚未暂存以备提交的变更：
#   （使用 "git add/rm <file>..." 更新要提交的内容）
#   （使用 "git checkout -- <file>..." 丢弃工作区的改动）
#
#	删除：      index.html
#
修改尚未加入提交（使用 "git add" 和/或 "git commit -a"）
[root@test code]# git checkout index.html
[root@test code]# ls
index.html  monitor  README.md

```

**如果我们发现删除 index.html 是误操作，怎么办恢复 ？？**

**这里有三个阶段可以操作：**

**1、工作区删除未 进入 暂存区时，使用  git  checkout  -- index.html  放弃**
**2、已经进入暂存区 时， 使用 git reset  HEAD  index.html  撤出缓存区，再  git  checkout  -- index.html 放弃**
**3、已经从暂存区提交时， 最终可以使用 版本控制方式，回退到删除前版本即可**



```
情况1：
[root@git code]# echo aaa >b1.txt
[root@git code]# ll
总用量 12
-rw-r--r-- 1 root root 20 10月 25 15:13 a1.txt
-rw-r--r-- 1 root root  4 10月 25 15:20 b1.txt
-rw-r--r-- 1 root root 44 10月 25 15:10 README.md
[root@git code]# git add .
[root@git code]# git status
# 位于分支 master
# 要提交的变更：
#   （使用 "git reset HEAD <file>..." 撤出暂存区）
#
#	新文件：    b1.txt
#
[root@git code]# git rm b1.txt
error: 'b1.txt' 有变更已暂存至索引中
（使用 --cached 保存文件，或用 -f 强制删除）
[root@git code]# git rm -f b1.txt
rm 'b1.txt'
[root@git code]# ll
总用量 8
-rw-r--r-- 1 root root 20 10月 25 15:13 a1.txt
-rw-r--r-- 1 root root 44 10月 25 15:10 README.md
[root@git code]# git status
# 位于分支 master
无文件要提交，干净的工作区


情况2：
[root@git code]# echo aaa >b1.txt
[root@git code]# git add .
[root@git code]# git status
# 位于分支 master
# 要提交的变更：
#   （使用 "git reset HEAD <file>..." 撤出暂存区）
#
#	新文件：    b1.txt
#
[root@git code]# rm -rf b1.txt		#直接工作区删除文件
[root@git code]# ll
总用量 8
-rw-r--r-- 1 root root 20 10月 25 15:13 a1.txt
-rw-r--r-- 1 root root 44 10月 25 15:10 README.md
[root@git code]# git status
# 位于分支 master
# 要提交的变更：
#   （使用 "git reset HEAD <file>..." 撤出暂存区）
#
#	新文件：    b1.txt
#
# 尚未暂存以备提交的变更：
#   （使用 "git add/rm <file>..." 更新要提交的内容）
#   （使用 "git checkout -- <file>..." 丢弃工作区的改动）
#
#	删除：      b1.txt
#
[root@git code]# git checkout b1.txt
[root@git code]# ll
总用量 12
-rw-r--r-- 1 root root 20 10月 25 15:13 a1.txt
-rw-r--r-- 1 root root  4 10月 25 15:23 b1.txt
-rw-r--r-- 1 root root 44 10月 25 15:10 README.md

```



**小结：**
**git  --version**
**git  add   readme.txt**
**git  commit -m  "your message"**
**git  status**
**git  log**
**git  reflog**
**git  reset  --hard   HEAD^  当前的上一个版本**
**git reset --hard   a35bb11  去到一个指定的版本**
**git  rm  readme.txt**
**git  checkout  -- readme.txt   #撤销工作区的修改**

**工作区 + 暂存区 + 本地仓库 +  ssh / https  ++++ 远程仓库**



#### 12.远程仓库

可以使用github或者gitee，这里使用的是gitee

##### 12.1 新建仓库

![](https://figure-bed-1304788733.cos.ap-guangzhou.myqcloud.com/typora/202204192253421.png#alt=)

##### 12.2 建立连接

![](https://figure-bed-1304788733.cos.ap-guangzhou.myqcloud.com/typora/202204192258006.png#alt=)

```shell
[root@test ~]# cd /opt/code/
[root@test code]# git config --global user.name "sushiyi"
[root@test code]# git config --global user.email "2364695562@qq.com"
[root@test code]# git remote add origin https://gitee.com/sushiyi/shy.git   # 配置远程git版本库
[root@test code]# git push -u origin "master"   # 推送到哪个分支
Username for 'https://gitee.com': sushiyi   # gitee的用户名
Password for 'https://sushiyi@gitee.com':    # gitee的密码
Counting objects: 11, done.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (11/11), 1.08 KiB | 0 bytes/s, done.
Total 11 (delta 0), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-6.3]
To https://gitee.com/sushiyi/shy.git
 * [new branch]      master -> master
分支 master 设置为跟踪来自 origin 的远程分支 master。
```

```shell
# 删除本地的仓库拉取远程仓库
# 地址获取如下图
[root@test code]# cd 
[root@test ~]# rm -rf /opt/code/   # 删除原来的
[root@test ~]# cd /opt/
[root@test opt]# ls
yum
[root@test opt]# git clone https://gitee.com/sushiyi/shy.git   # 拉取远程仓库
正克隆到 'shy'...
Username for 'https://gitee.com': sushiyi
Password for 'https://sushiyi@gitee.com': 
remote: Enumerating objects: 11, done.
remote: Counting objects: 100% (11/11), done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 11 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (11/11), done.
# 验证
[root@test opt]# ls   
shy  yum
[root@test opt]# cd shy 
[root@test shy]# ls
index.html  monitor  README.md
```

![](https://figure-bed-1304788733.cos.ap-guangzhou.myqcloud.com/typora/202204192310152.png#alt=)

##### 12.3 为远程仓库免密

注：公钥分为两种：一为仓库的公钥，只有读权限，一种个人设置的公钥，具有读写权限

![](https://figure-bed-1304788733.cos.ap-guangzhou.myqcloud.com/typora/202204192315721.png#alt=)

```shell
[root@test shy]# ssh-keygen -t RSA -N '' -f ~/.ssh/id_rsa    # 生成密钥
[root@test shy]# cat ~/.ssh/id_rsa.pub   # 复制公钥到远程仓库，如下图
# 会弹出框输入密码，成功添加
```

![](https://figure-bed-1304788733.cos.ap-guangzhou.myqcloud.com/typora/202204192333332.png#alt=)

```shell
[root@test shy]# ssh -T git@gitee.com   # 首次使用需要确认并添加主机到本机SSH可信列表
# 在gitee修改远程仓库里面的README.md文件，然后拉取一下，地址需要换成ssh的，如下图
```

![](https://figure-bed-1304788733.cos.ap-guangzhou.myqcloud.com/typora/202204192340590.png#alt=)

```shell
[root@test shy]# cd 
[root@test ~]# rm -rf /opt/shy/
[root@test opt]# git clone git@gitee.com:sushiyi/shy.git   # 此时不再需要输入密码
正克隆到 'shy'...
remote: Enumerating objects: 14, done.
remote: Counting objects: 100% (14/14), done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 14 (delta 1), reused 0 (delta 0), pack-reused 0
接收对象中: 100% (14/14), done.
处理 delta 中: 100% (1/1), done.
[root@test opt]# ls
shy  yum
[root@test opt]# cat shy/README.md 
这是第一次提交
这是第二次提交
this is a test
测试远程拉取，免密
[root@test opt]# cd shy/
[root@test shy]# git remote add origin git@gitee.com:sushiyi/shy.git
fatal: 远程 origin 已经存在。
[root@test shy]# git remote add shy git@gitee.com:sushiyi/shy.git   # 配置远程git版本库
[root@test shy]# ls
index.html  monitor  README.md
[root@test shy]# echo "this is a test" >> /opt/shy/test.txt
[root@test shy]# git add .
[root@test shy]# git status
# 位于分支 master
# 要提交的变更：
#   （使用 "git reset HEAD <file>..." 撤出暂存区）
#
#	新文件：    test.txt
#
[root@test shy]# git commit -m "测试免密推送到远程仓库"
[master c31994f] 测试免密推送到远程仓库
 1 file changed, 1 insertion(+)
 create mode 100644 test.txt
[root@test shy]# git push -u shy "master"
Counting objects: 4, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 321 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-6.3]
To git@gitee.com:sushiyi/shy.git
   c4673d7..c31994f  master -> master
分支 master 设置为跟踪来自 shy 的远程分支 master。
# 再去远程仓库会发现已经免密推送成功
```

##### 12.4 查看添加的gitee远程仓库源和删除源

```shell
[root@test shy]# git remote -h
用法：git remote [-v | --verbose]
  或：git remote add [-t <分支>] [-m <master>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <名称> <url>
  或：git remote rename <旧名称> <新名称>
  或：git remote remove <名称>
  或：git remote set-head <名称> (-a | -d | <分支>)
  或：git remote [-v | --verbose] show [-n] <名称>
  或：git remote prune [-n | --dry-run] <名称>
  或：git remote [-v | --verbose] update [-p | --prune] [(<组> | <远程>)...]
  或：git remote set-branches [--add] <名称> <分支>...
  或：git remote set-url [--push] <名称> <新的地址> [<旧的地址>]
  或：git remote set-url --add <名称> <新的地址>
  或：git remote set-url --delete <名称> <地址>

    -v, --verbose         冗长输出；必须置于子命令之前
```

```shell
[root@test shy]# git remote -v show
origin	git@gitee.com:sushiyi/shy.git (fetch)   # 因为是第一个添加的源，所以默认是用origin
origin	git@gitee.com:sushiyi/shy.git (push)
shy	git@gitee.com:sushiyi/shy.git (fetch)
shy	git@gitee.com:sushiyi/shy.git (push)
```

```shell
# 删除 origin 源 ，保留后面免密的源
[root@test shy]# git remote remove origin

# 验证
[root@test shy]# git remote -v show
shy	git@gitee.com:sushiyi/shy.git (fetch)
shy	git@gitee.com:sushiyi/shy.git (push)
```

```shell
[root@test shy]# echo "别白嫖了" >> README.md 
[root@test shy]# git status
# 位于分支 master
# 尚未暂存以备提交的变更：
#   （使用 "git add <file>..." 更新要提交的内容）
#   （使用 "git checkout -- <file>..." 丢弃工作区的改动）
#
#	修改：      README.md
#
修改尚未加入提交（使用 "git add" 和/或 "git commit -a"）
[root@test shy]# git add .
[root@test shy]# git commit -m "update readme"
[master 3c2834f] update readme
 1 file changed, 1 insertion(+)
[root@test shy]# git status   # 这里会有提示与远程仓库的区别并提示领先远程仓库
# 位于分支 master
# 您的分支领先 'shy/master' 共 1 个提交。
#   （使用 "git push" 来发布您的本地提交）
#
无文件要提交，干净的工作区
[root@test shy]# git push -u shy   # 此时会有个报错，但实际推送成功，不影响结果

或者

# 使用 git push 来将本地仓库推送到gitee上
[root@test shy]# git push -u shy master
```

**把本地库的内容推送到远程，使用 git push命令，实际上是把当前分支master推送到远程。**
**由于远程库是空的，我们第一次推送master分支时，加上了 –u参数，**

**Git不但会把本地的master分支内容推送的远程新的master分支，还会把本地的master分支和远程的master分支关联起来，**
**在以后的推送或者拉取时就可以简化命令。**

**从现在起，只要本地作了提交，就可以通过如下命令：**
**[root@test  ~]#  git push origin master **

**把本地master分支的最新修改推送到github上了，现在你就拥有了真正的分布式版本库了。**

##### 12.5 从远程库克隆

```shell
[root@test opt]# git clone git@gitee.com:sushiyi/shy.git
```

**小结**
**要克隆一个仓库，首先必须知道仓库的地址，然后使用git clone命令克隆。**
**Git支持多种协议，包括https，但ssh协议速度最快。**
**如果本地已经有对应的仓库就是用git pull origin master下载代码及快速合并，就是差异更新**

**常用命令解释 [https://www.php.cn/tool/git/469391.html](https://www.php.cn/tool/git/469391.html)**

#### 13.分支

**用于代码的区分**

代码管理中的“分支”是什么意思？？

举个例子：
你正在做新项目新需求的开发，但是现在有个  紧急的Bug需要修改，老板说今天修改完成晚上给到测试人员。

第二天紧急更新APP，现在的新需求还未开发完成，不一起更新；

你看着手里没有分支的代码是不是一脸懵逼；
这时候我们需要两个分支：一个分支做开发、一个分支改BUG；

```
        bug
    成 熟
         A--------
```

几乎所有的版本控制系统都以某种形式支持分支。
使用分支意味着你可以把你的工作从开发主线上**分离开来**，以免影响开发主线。
在很多版本控制系统中，这是一个略微低效的过程——常常需要完全创建一个源代码目录的副本。
对于大项目来说，这样的过程会耗费很多时间。

有人把 Git 的分支模型称为它的“必杀技特性”，也正因为这一特性，使得 Git 从众多版本控制系统中脱颖而出。

为何 Git 的分支模型如此出众呢？
Git 处理分支的方式可谓是难以置信的轻量，创建新分支这一操作几乎能在瞬间完成，并且在不同分支之间的切换操作也是一样便捷。
与许多其它版本控制系统不同，Git 鼓励在工作流程中频繁地使用分支与合并，哪怕一天之内进行许多次。
理解和精通这一特性，你便会意识到 Git 是如此的强大而又独特，并且从此真正改变你的开发方式。

![](https://figure-bed-1304788733.cos.ap-guangzhou.myqcloud.com/typora/202204202000474.png#alt=image-20220420200012063)

##### master 主干：

线上的版本：主干的代码不做开发，目的是保留现在线上的版本，如果现在线上的代码出现任何的BUG或紧急添加新功能，
就从master拉下来一个分支master_alter，master_alter 分支的代码修改或添加后，然后测试打包发布，
发布后把这个分支master_alter 合并到 master；
然后  删除master_alter分支，这时master任然是线上的版本；

##### dev分支：

正在开发的版本：假如公司出了两个新的需求，要给现在的商城项目添加一个新的功能叫购物车，
然后我的这个分支叫dev_spc，日常的开发工作就一直在这个dev_spc这个分支上面；
还要给商城加上店铺功能，然后我旁边哥们的分支就叫 dev_shops，旁边这哥们他日常的开发工作就一直在这个dev_shops这个分支上面；
开发完成后从dev分支合并到release分支，发布后再合并到master主干；
**master主干的代码不做开发用，保留现在线上的版本代码；**

##### release 分支：

预发布的版本、正在测试的版本：
新需求已经开发完成，9.30号上线，这段的时间就是测试和修改BUG，
我们给这个分支起名字叫release_930，等release_930版本的代码发布上线后，
把release分支合并到master主干上，把release分支删除；

##### bugfix 分支 (可不用)

分支在实际开发中的意义所在

假设你准备开发一个新功能，但是需要两周才能完成，第一周你写了50%的代码，如果立刻提交，由于代码还没写完，
不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交，又存在丢失每天进度的巨大风险。
现在有了分支，就不用怕了。你创建了一个属于你自己的分支，别人看不到，还继续在原来的分支上正常工作，
而你在自己的分支上干活，想提交就提交，直到开发完毕后，再一次性合并到原来的分支上，这样，既安全，又不影响别人工作。

```shell
[root@test shy]# git branch   # 查看当前分支
* master

[root@test shy]# git branch dev   # 创建新的分支
[root@test shy]# git branch   # 当前在哪个分支前面会有个*
  dev
* master

[root@test shy]# git checkout dev   # 切换分支
切换到分支 'dev'
[root@test shy]# git branch
* dev
  master
  

# 切换分支并新建文件会发现不影响
[root@test shy]# cat dev.php 
<?php
echo ("test")
>
[root@test shy]# git status
# 位于分支 dev
# 未跟踪的文件:
#   （使用 "git add <file>..." 以包含要提交的内容）
#
#	dev.php
提交为空，但是存在尚未跟踪的文件（使用 "git add" 建立跟踪）
[root@test shy]# git add .
[root@test shy]# git commit -m "这是提交到dev"
[dev a22e523] 这是提交到dev
 1 file changed, 3 insertions(+)
 create mode 100644 dev.php
[root@test shy]# ls
dev.php  index.html  monitor  README.md  test.txt
[root@test shy]# git checkout master   # 切换到master发现新增的php文件在这边是没有的
切换到分支 'master'
[root@test shy]# ls
index.html  monitor  README.md  test.txt

# 当dev分支的代码测试没有问题想合并到master
# 如果想合并谁，需要先切换到当前分支再进行合并
[root@test shy]# git merge dev   # 在master分支合并dev
更新 3c2834f..a22e523
Fast-forward
 dev.php | 3 +++
 1 file changed, 3 insertions(+)
 create mode 100644 dev.php
[root@test shy]# git branch   # 当前分支是master
  dev
* master
[root@test shy]# ls   # 可以发现已经把dev分支新建的php已经合并过来
dev.php  index.html  monitor  README.md  test.txt
# 此时不需要add和提交，直接push就行
[root@test shy]# git push -u shy


# 切换分支并进行推送，远程仓库没有dev分支
[root@test shy]# git branch
  dev
* master
[root@test shy]# git checkout dev
切换到分支 'dev'
[root@test shy]# vim install.sh
[root@test shy]# cat install.sh 
#!/bin/bash
echo "install servers"
[root@test shy]# git add .
[root@test shy]# git commit -m "update shell to dev"
[dev 302d685] update shell to dev
 1 file changed, 2 insertions(+)
 create mode 100644 install.sh
[root@test shy]# git push -u shy dev   # 如果用的是git push -u shy会有个提示说远程仓库没有dev分支给出一个命令创建并推送
Counting objects: 4, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 309 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-6.3]
remote: Create a pull request for 'dev' on Gitee by visiting:
remote:     https://gitee.com/sushiyi/shy/pull/new/sushiyi:dev...sushiyi:master
To git@gitee.com:sushiyi/shy.git
 * [new branch]      dev -> dev
分支 dev 设置为跟踪来自 shy 的远程分支 dev。
```

![](https://figure-bed-1304788733.cos.ap-guangzhou.myqcloud.com/typora/202204202046657.png#alt=)

```shell
# 1. 在浏览器上操作远程仓库新建一个分支为test
# 2. 回去刷新发现是没有dev分支新建的shell脚本，因为创建分支的时候是在master，以master为起点创建的，所以创建test分支里面的东西和当时的master是一样的
# 3. 在本地仓库操作会把这结果具体呈现

[root@test shy]# git branch   # 现在是在dev分支
* dev
  master
[root@test shy]# git branch test   # 创建test分支
[root@test shy]# git branch   
* dev
  master
  test
[root@test shy]# git checkout test   # 切换到test
切换到分支 'test'
[root@test shy]# ls   # 验证发现有shell脚本
dev.php  index.html  install.sh  monitor  README.md  test.txt


# 创建新文件进行推送验证
[root@test shy]# git branch
  dev
  master
* test
[root@test shy]# vim test.sh
[root@test shy]# cat test.sh 
#!/bin/bash
echo "这是新的分支"
[root@test shy]# git add .
[root@test shy]# git commit -m "update to test"
[test ff5dfb5] update to test
 1 file changed, 2 insertions(+)
 create mode 100644 test.sh
[root@test shy]# git push -u shy test
Counting objects: 4, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 298 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-6.3]
To git@gitee.com:sushiyi/shy.git
   a22e523..ff5dfb5  test -> test
分支 test 设置为跟踪来自 shy 的远程分支 test。

# 此时去浏览器查看远程仓库会发现不同分支对应不同的代码
```

当Git无法自动合并分支时，就必须首先解决冲突。解决冲突后，再提交，合并完成。
解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容，再提交。
用git log --graph命令可以看到分支合并图。
模拟教程：[https://blog.csdn.net/KingOfMyHeart/article/details/89929369](https://blog.csdn.net/KingOfMyHeart/article/details/89929369)

多人协作的工作模式通常是这样：

1. 首先，可以试图用git push origin <branch-name>推送自己的修改；
2. 如果推送失败，则因为远程分支比你的本地更新，需要先用git pull试图合并；
3. 如果合并有冲突，则解决冲突，并在本地提交；
4. 没有冲突或者解决掉冲突后，再用git push origin <branch-name>推送就能成功！

如果git pull提示no tracking information，则说明本地分支和远程分支的链接关系没有创建，
用命令git branch --set-upstream-to <branch-name> origin/<branch-name>。
这就是多人协作的工作模式，一旦熟悉了，就非常简单。

小结
• 查看远程库信息，使用git remote -v；
• 本地新建的分支如果不推送到远程，对其他人就是不可见的；
• 从本地推送分支，使用git push origin branch-name，如果推送失败，先用git pull抓取远程的新提交；
• 在本地创建和远程分支对应的分支，使用git checkout -b branch-name origin/branch-name，本地和远程分支的名称最好一致；
• 建立本地分支和远程分支的关联，使用git branch --set-upstream branch-name origin/branch-name；
• 从远程抓取分支，使用git pull，如果有冲突，要先处理冲突。

#### 14.标签

发布一个版本时，我们通常先在版本库中打一个标签（tag），这样，就唯一确定了打标签时刻的版本。将来无论什么时候，取某个标签的版本，就是把那个打标签的时刻的历史版本取出来。所以，标签也是版本库的一个快照。
Git的标签虽然是版本库的快照，但其实它就是指向某个commit的指针（跟分支很像对不对？但是分支可以移动，标签不能移动），所以，创建和删除标签都是瞬间完成的。

```shell
# 在Git中打标签非常简单，首先，切换到需要打标签的分支上，然后，敲命令git tag <name>就可以打一个新标签
[root@test shy]# git branch
  dev
  master
* test
[root@test shy]# git reflog
ff5dfb5 HEAD@{0}: commit: update to test
302d685 HEAD@{1}: checkout: moving from dev to test
302d685 HEAD@{2}: commit: update shell to dev
a22e523 HEAD@{3}: checkout: moving from master to dev
a22e523 HEAD@{4}: merge dev: Fast-forward
3c2834f HEAD@{5}: checkout: moving from dev to master
a22e523 HEAD@{6}: commit: 这是提交到dev
3c2834f HEAD@{7}: checkout: moving from master to dev
3c2834f HEAD@{8}: commit: update readme
c31994f HEAD@{9}: commit: 测试免密推送到远程仓库
c4673d7 HEAD@{10}: clone: from git@gitee.com:sushiyi/shy.git
[root@test shy]# git tag v1.0 
[root@test shy]# git tag   # 查看所有标签
v1.0
```

**默认标签是打在最新提交的commit上的。有时候，如果忘了打标签，比如，现在已经是周五了，但应该在周一打的标签没有打，怎么办？**
**方法是找到历史提交的commit id，然后打上就可以了**

```shell
[root@test shy]# git log --pretty=oneline --abbrev-commit   # 显示历史提交
ff5dfb5 update to test
302d685 update shell to dev
a22e523 这是提交到dev
3c2834f update readme
c31994f 测试免密推送到远程仓库
c4673d7 update README.md.
f69c6a5 增加一个HTML页面
a35bb11 第三次正式提交
5095670 第二次正式提交
1fb223e 第一次正式提交
[root@test shy]# git tag v0.6 c31994f   # 给“测试免密推送到远程仓库”打标签
[root@test shy]# git tag
v0.6
v1.0

# 注意，标签不是按时间顺序列出，而是按字母排序的。可以用git show <tagname>查看标签信息
[root@test shy]# git show v0.6
commit c31994f95047ba36ff1e694a9b8acd72f6dc3b9e
Author: sushiyi <2364695562@qq.com>
Date:   Tue Apr 19 23:53:51 2022 +0800

    测试免密推送到远程仓库

diff --git a/test.txt b/test.txt
new file mode 100644
index 0000000..90bfcb5
--- /dev/null
+++ b/test.txt
@@ -0,0 +1 @@
+this is a test

# 可以看到，v0.6确实打在“测试免密推送到远程仓库”这次提交上。
# 还可以创建带有说明的标签，用-a指定标签名，-m指定说明文字
[root@test shy]# git tag -a v0.1 -m "version 0.1 released" 1fb223e
[root@test shy]# git tag
v0.1
v0.6
v1.0
```

• 命令git tag <tagname>用于新建一个标签，默认为HEAD，也可以指定一个commit id；

• 命令git tag -a <tagname> -m "blablabla..."可以指定标签信息；

• 命令git tag可以查看所有标签。

```shell
如果标签打错了，也可以删除：
$ git tag -d v0.1
Deleted tag 'v0.1' (was f15b0dd)
因为创建的标签都只存储在本地，不会自动推送到远程。所以，打错的标签可以在本地安全删除。
如果要推送某个标签到远程，使用命令git push origin <tagname>：
$ git push origin v1.0
Total 0 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
 * [new tag]         v1.0 -> v1.0
或者，一次性推送全部尚未推送到远程的本地标签：
$ git push origin --tags
Total 0 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
 * [new tag]         v0.9 -> v0.9
如果标签已经推送到远程，要删除远程标签就麻烦一点，先从本地删除：
$ git tag -d v0.9
Deleted tag 'v0.9' (was f52c633)
然后，从远程删除。删除命令也是push，但是格式如下：
$ git push origin :refs/tags/v0.9
To github.com:michaelliao/learngit.git
 - [deleted]         v0.9
要看看是否真的从远程库删除了标签，可以登陆gitee查看。
```

```shell
[root@test shy]# git push -u shy v1.0
Total 0 (delta 0), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-6.3]
To git@gitee.com:sushiyi/shy.git
 * [new tag]         v1.0 -> v1.0
# 更多操作参考上面
```

![](https://figure-bed-1304788733.cos.ap-guangzhou.myqcloud.com/typora/202204210016905.png#alt=)

