Git 笔记

1. Git 概述

1.1. Git 简介与特点

Git是分布式的版本控制工具,其特点如下:

  • 速度快
  • 简单的设计
  • 对非线性开发模式的强力支持(允许上千个并行开发的分支)
  • 完全分布式
  • 有能力高效管理类似 Linux 内核一样的超大规模项目(速度快和数据多)

    1.2. Git与SVN对比

    1.2.1. SVN

    SVN是集中式版本控制软件,版本库是集中放在中央服务器的。每个程序员使用自己电脑,首先要从中央服务器哪里得到最新的版本,编程完将完成的代码推送到中央服务器。集中式版本控制系统是必须联网才能工作
    标准的集中式版本控制工具管理方式:
    01-Git笔记 - 图1
    集中管理方式在一定程度上看到其他开发人员在干什么,而管理员也可以很轻松掌握每个人的开发权限。但是相较于其优点而言,集中式版本控制工具缺点很明显:
  1. 服务器单点故障,一旦宕机无法提交代码,即容错性较差
  2. 离线无法提交代码,无法及时记录开发人员的提交行为

每天都同步一次即可,需要手动同步上传代码

1.2.2. Git

Git是分布式版本控制软件,它可以没有中央服务器,每个人的电脑就是一个完整的版本库。工作的时候就不需要联网了,因为版本都是在自己的电脑上。当多人开发时,只需把各自的修改推送到远程仓库,就可以所有成员都可以看到修改了。
分布式版本控制工具管理方式:
01-Git笔记 - 图2

1.2.3. 总结

  1. svn 是集中式版本控制工具,git 是分布式版本控制工具
  2. svn 不支持离线提交,git 支持离线提交代码

    1.3. Git 工作流程

  3. 从远程仓库中克隆 Git 资源作为本地仓库。

  4. 从本地仓库中checkout代码然后进行代码修改
  5. 在提交前先将代码提交到暂存区。
  6. 提交修改。提交到本地仓库。本地仓库中保存修改的各个历史版本。
  7. 在修改完成后,需要和团队成员共享代码时,可以将代码push到远程仓库。

Git 的工作流程图
01-Git笔记 - 图3

1.4. Git 相关概念

相关名词

  • 本地仓库:是在开发人员自己电脑上的Git仓库,存放开发者的代码(.git 隐藏文件夹就是本地仓库)
  • 远程仓库:是在远程服务器上的Git仓库,存放代码(可以是github.com或者gitee.com 等开源代码仓库,或者自家公司的服务器)
  • 工作区: 本地编写代码(文档)的地方
  • 暂存区: 在本地仓库中的一个特殊的文件(index) 叫做暂存区,临时存储开发者即将要提交的文件

01-Git笔记 - 图4
相关操作

  • Clone:克隆,就是将远程仓库复制到本地仓库
  • Push:推送,就是将本地仓库代码上传到远程仓库
  • Pull:拉取,就是将远程仓库代码下载到本地仓库,并将代码克隆到本地工作区

    2. Git 安装

    2.1. Git 下载网址

    Git下载网址:https://git-scm.com/download

笔记使用的版本:

  • window版本:Git-2.16.2-64-bit.exe
  • linux版本:git-2.16.2.tar.gz

2.2. Git 相关图形化客户端

示例使用Git-2.23.0-64-bit.exe

  • 选择软件的安装位置

01-Git笔记 - 图5

  • 选择需安装的组件(默认即可,直接下一步)

01-Git笔记 - 图6

  • 选择使用的编辑器(默认即可,直接下一步)

01-Git笔记 - 图7

  • 环境变量调整

01-Git笔记 - 图8

  • 选择使用OpenSSH

01-Git笔记 - 图9

  • 使用OpenSSL库

01-Git笔记 - 图10

  • 配置命令行会话(默认即可)

01-Git笔记 - 图11

  • 配置终端(默认即可)

01-Git笔记 - 图12

  • 配置额外的选项(默认即可)

01-Git笔记 - 图13
01-Git笔记 - 图14

  • 安装完成

01-Git笔记 - 图15

  • 验证是否安装成功。打开右键菜单,若出现“Git GUI Here”、“Git Bash Here”则代表安装成功

01-Git笔记 - 图16
或者命令窗口,输入git --version查看git的版本
01-Git笔记 - 图17

3. git 仓库的特殊文件

3.1. .gitkeep文件

.gitkeep文件是用来保证当前目录即使为空,也会上传到github上

3.2. .gitignore 忽略规则文件(待整理)

.gitignore 的文件用于声明忽略文件或不忽略文件的规则,规则对当前目录及其子目录生效

注意:该文件因为没有文件名,没办法直接在windows目录下直接创建(win10系统后来一些版本可以直接创建没有文件名的文件),可以通过命令行 Git Bash 来 touch 指令来创建。

4. 分支 (branch)(整理中)

4.1. 分支的概念

几乎所有的版本控制系统都以某种形式支持分支。使用分支意味着可以把开发者本地工作区从开发主线上分离开来,避免影响开发主线。多线程开发,可以同时开启多个任务的开发,多个任务之间互不影响。

4.2. 创建分支

5. 标签 (tag)(整理中)

5.1. 标签的概念

如果项目达到一个重要的阶段,并希望永远记住那个特别的提交快照,可以给它打上标签(tag)
比如说,想为项目发布一个”1.0”版本。可以给最新一次提交打上(HEAD)”v1.0”的标签。标签可以理解为项目里程碑的一个标记,一旦打上了这个标记则,表示当前的代码将不允许提交

5.2. 标签的创建(图形化界面操作)

标签的创建和分支的创建操作几乎一样

5.3. 标签的切换与删除

6. Git 命令

掌握并熟练使用了命令行模式操作git 的话,会发现某些操作命令行比窗口化操作要简单

6.1. Git 配置

在安装好后首次使用前,需要先进行全局配置

6.1.1. 配置全局的用户信息

在空白位置打开右键菜单,点击【Git Bash Here】,打开Git命令行窗口。输入以下命令配置全局的用户名与邮箱

  1. $ git config --global user.name "用户名"
  2. $ git config --global user.email "邮箱地址"

也可以直接查看设置值
01-Git笔记 - 图18

6.1.2. 查看配置信息

  1. # 查看配置信息
  2. $ git config --list
  3. $ git config user.name

注:通过上面的命令设置的信息会保存在~/.gitconfig文件中

6.2. 命令行 - Git 常用操作

6.2.1. 本地仓库初始化

在空的目录中,执行以下命令,初始化git仓库,即由git来管理此目录

  1. $ git init

执行之后会在项目目录下创建【.git】的隐藏目录,这个目录是Git所创建的,不能删除,也不能随意更改其中的内容。

初始化仓库不带工作区

$ git init --bare

6.2.2. 查看仓库当前状态

用于查询当前仓库中有那些文件存在变动

# 查看状态
$ git status
# 查看状态 使输出信息更加简洁
git status –s

6.2.3. 添加文件到缓存区

git add 指令,用于添加单个(多个)文件到缓存区。
添加单个文件

$ git add 文件名

同时添加多个文件

$ git add 文件名1 文件名2 文件名3 …

添加当前目录中所有文件到缓存区。

$ git add .

6.2.4. 取消缓存区的文件

将暂存区的文件取消暂存指定的文件(取消 add)

$ git reset 文件名

6.2.5. 提交至版本库

git commit 指令,将当前缓存区的内容提交到版本库。

  • -m 参数用于指定本次提交的注释。注意:注释的内容必须使用""英文双引号包裹
  • <文件名> 非必需,可以指定提交某个文件 ``` $ git commit -m “注释内容” <文件名>
#### 6.2.6. 删除本地工作区文件

$ git rm <文件名>

#### 6.2.7. 回退本工作区库误删文件

$ git checkout head <文件名>

#### 6.2.8. 查看版本
`git log` 指令,用于查看当前git的提交记录(版本)

$ git log

参数 `--pretty=oneline`,将每个git的提交记录在一行显示

$ git log —pretty=oneline

#### 6.2.9. 版本回退
`git reset` 指令用于版本的回退

$ git reset —hard 提交编号


> 注:”提交编号“是通过 `git log` 指令查看

> 在使用回退指令的时候 commit id 可以不用写全,git会自动识别,但是至少需要写前4位字符


#### 6.2.10. 查看历史版本
如果发生版本回退的操作,此时使用`git log`就无法查询回退到此版本之前的操作记录,所以需要使用 `git reflog` 指令来查看历史操作,获取最新的 commit id

$ git reflog

### 6.3. 命令行 - git 远程仓库操作
#### 6.3.1. 查看远程
查看远程,列出指定的每一个远程服务器的简写

$ git remote

查看远程,列出简称和地址

$ git remote -v

查看远程仓库详细地址

$ git remote show <仓库简称>

#### 6.3.2. 添加/移除远测仓库
添加远程仓库

$ git remote add

移除远程仓库和本地仓库的关系(只是从本地移除远程仓库的关联关系,并不会真正影响到远程仓库)

$ git remote rm

#### 6.3.3. 克隆远程仓库到本地
`clone` 指令用于克隆远程仓库到本地

$ git clone 远程Git仓库地址


> 注:远程仓库分两种,基于http/https协议或者基于ssh协议


#### 6.3.4. 推送到远程仓库
`push` 指令用于将修改的版本推送到远程仓库某个分支

$ git push [remote-name] [branch-name]

基于http/https协议的远程仓库,首次提交时可能会出现403无权限的错误,需要修改【.git/config】文件内容,增加相应远程仓库的有效的用户名与密码

原配置

[remote “origin”] url = https://github.com/用户名/仓库名.git

修改为

[remote “origin”] url = https://用户名:密码@github.com/用户名/仓库名.git


> 注:推送到基于ssh协议的远程仓库,在push的时候并没有提示要求输入帐号密码,因为公私玥已经实现了用户身份鉴权,也不需要修改此配置文件。


#### 6.3.5. 远程仓库拉取版本
##### 6.3.5.1. 手动拉取与合并
从远程仓库拉取 (拉取到.git 目录,不会合并到工作区,工作区发生变化)

$ git fetch <分支名称>

手动合并。把某个版本的某个分支合并到当前工作区

$ git merge /<分支名称>

##### 6.3.5.2. 自动拉取与合并工作区
`pull` 指令用于拉取远程仓库的版本记录。(拉取到 .git 目录,合并到工作区,工作区不发生变化。相当于 `fetch` + `merge`)

$ git pull <分支名称>


> 拉取时如果出现版本冲突,需要手动进行冲突的合并


注意:如果当前本地仓库不是从远程仓库克隆,而是本地创建的仓库,并且仓库中存在文件,此时再从远程仓库拉取文件的时候会报错(fatal: refusing to merge unrelated histories),解决此问题可以在 `git pull` 命令后加入参数 `--allow-unrelated-histories`

强制拉取合并

$ git pull <分支名称> —allow-unrelated-histories

### 6.4. 命令行 - 分支管理命令
默认分支名称为 master。_2020年Github开始修改为 main_
#### 6.4.1. 查看分支

$ git branch


> 注意:当前的分支前面有个标记“`*`”。


列出所有远程分支

$ git branch -r

列出所有本地分支和远程分支

$ git branch -a

#### 6.4.2. 创建分支

$ git branch <分支名>

#### 6.4.3. 切换分支

$ git checkout <分支名>

#### 6.4.4. 删除分支

$ git branch -d <分支名>


> 注意:在删除分支的时候,一定要先退出要删除的分支(或切换到其他分支),然后才能删除该分支。或者如果分支已经修改过,则不允许删除。


强制删除分支(慎用)

$ git branch -D <分支名>

#### 6.4.5. 合并分支

$ git merge 被合并的分支名

合并分支需要先使用 `checkout` 切换到待合并到的分支,然后再使用 `merge` 指令指定要合并的分支。**需要注意:合并所有分支之后,需要使用 `push` 指令推送到远程仓库中**
#### 6.4.6. 提交分支至远程仓库

$ git push <仓库简称> <分支名称>

#### 6.4.7. 删除远程仓库分支

$ git push origin –d 分支名称

### 6.5. 命令行 - 标签 tag
#### 6.5.1. 查看 tag 信息
列出所有tag

$ git tag

查看tag详细信息

$ git show [tagName]

#### 6.5.2. 新建一个 tag

$ git tag [tagName]

#### 6.5.3. 提交指定 tag

$ git push [仓库简称] [tagName]

#### 6.5.4. 新建一个分支指向某个 tag

$ git checkout -b [branch] [tag]

#### 6.5.5. 删除本地 tag

$ git tag -d [tag]

#### 6.5.6. 删除远程 tag (注意 空格)
**注意空格**

$ git push origin :refs/tags/[tag]

# Git 扩展知识
## 1. git上的分支命名规范
### 1.1. git常用分支说明

- `master`
- 主分支,永远是可用的、稳定的、可直接发布的版本,不能直接在该分支上开发。只有计划发布的版本功能在`develop`分支上全部完成,而且测试没有问题了才会合并到`master`上。


- `develop`
- 开发主分支,代码永远是最新,所有新功能以这个分支来创建自己的开发分支,该分支只做只合并操作,不能直接在该分支上开发
- 例如要开发一个注册功能,那么就会从`develop`分支上创建一个`feature`分支`fb-register`,在`fb-register`分支上将注册功能完成后,将代码合并到`develop`分支上。这个`fb-register`就完成了它的使命,可以删除了。如果再需要开发一个登录功能,按刚刚上述操作流程再次进行


- `feature-xxx`
- 功能开发分支,在`develop`上创建分支,以自己开发功能模块命名,功能测试正常后合并到`develop`分支


- `release`
- 预分布分支,在合并好`feature`分支的`develop`分支上创建,主要是用来测试bug的分支,修改好bug并确定稳定之后合并到`develop`和`master`分支,然后发布`master`分支


- `release-fix`
- 功能bug修复分支,在`release`上创建分支修复,修复好测试出来的bug之后合并回`release`分支。


- `hotfix-xxx`
- 紧急bug修改分支,项目上线之后可以会遇到一些环境问题需要紧急修复,在`master`分支上创建,流程跟`release`分支相似,修复完成后合并到`develop`和`master`分支



**开发项目时git分支管理流程图**<br />![开发项目时git分支管理流程图](https://gitee.com/moonzero/images/raw/master/code-note/20190316175236283_27122.jpg)<br />**_注意事项:_**

- 一个分支尽量开发一个功能模块,不要多个功能模块在一个分支上开发。
- 开发过程中,如果组员A开发的功能依赖组员B正在开发的功能,可以待组员B开发好相关功能之后,组员A直接pull组员B的分支下来开发,不需要先将组员B的分支merge到develop分支。
- feature 分支在申请合并之前,最好是先 pull 一下 develop 主分支下来,看一下有没有冲突,如果有就先解决冲突后再申请合并。
### 1.2. git分支命名规范
| 
分支
 | 命名
 | 说明
 |
| --- | --- | --- |

| 
主分支
 | `master`/`main`
 | 主分支,所有提供给用户使用的正式版本,都在这个主分支上发布
 |

| 
开发分支
 | `dev`/`develop`
 | 开发分支,永远是功能最新最全的分支
 |

| 
功能分支
 | `feature-*`
 | 新功能分支,某个功能点正在开发阶段
 |

| 
发布版本
 | `release-*`
 | 发布定期要上线的功能
 |

| 
修复分支
 | `bug-*`
 | 修复线上代码的 bug
 |


## 2. git提交规范
### 2.1. 中文式提交格式参考

<新功能|bug修复|文档改动|格式化|重构|测试代码>: (影响范围) <主题>

解释为什么要做这些改动

issue #?

### 2.2. 提交类型

- 关于commit时类别,一般通用的如下
- feat:新功能(feature)
- fix:修复bug
- docs:文档(documentation)变动
- style:格式(不影响代码运行的变动),如格式化,缺失分号等,但不包括生产时紧急的bug修复
- refactor:重构(即不是新增功能,也不是修改bug的代码变动)
- perf:代码优化
- test:增加测试
- build:构建工具或外部依赖的更改,比如后端maven,前端package,json等
- ci:更改项目级的配置文件或脚本
- chore:构建过程或辅助工具的变动,除上面之外的修改
- revert:撤销先前的提交


### 2.3. 提交注释示例

<类型>: <主题>

解释为什么要做这些改动(限制每行72个字)

———————————————————————

注意:

提交模板的内容,如果最左侧带”#”,内容不会提交到git中

主题和内容以一个空行分隔

主题限制为最大50个字

主题行结束不用标点

内容每行72个字

内容用于解释为什么和是什么,而不是怎么做

————————- 例子 ————————————-

feat: 增加账号激活功能

#

因为账号初始化时……

……

所以……

———————— 例子结束 ———————————-

```