Git 版本管理
01 用户信息
# 查看 git 版本
git -v
# 每台设备初次使用时的设定
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
# 查看设置
git config --list
02 仓库基础操作
# 初始化一个仓库
git init
# 克隆一个仓库
git clone <repo directory> [repo name]
# 本地仓库连接到远程仓库 (origin 是默认推荐的远程仓库名称)
git remote add origin <server>
# 取消本地仓库与远程仓库的关联
git remote remove origin
# 添加到暂存区
git add <filename>
git add *
# 移除暂存区
git rm --cached <filename>
# 提交到存储区
git commit -m <msg>
# 推送到远程仓库
git push origin master
# 从远程仓库拉取
git pull origin master
# 显示工作区和暂存区的状态
git status
# 显示远程仓库地址
git remote -v
# 查看提交历史
git log
git log --oneline
# 恢复删除的文件(仅在工作区删除)
git restore <filename> # 从存储区恢复到工作区
# 恢复删除的文件(存储区中也删除了)
git reset --hard <hash> # 修改head头,部分提交历史会丢失
git revert <hash> # 恢复删除的文件,提交历史不会丢失
# 查看指定文件的修改记录
git blame <file>
03 分支操作
- 从 master 主分支创建分支的时候,会把 master 上的内容都复制到新分支中,之后在分支上的操作不会互相影响;
- 合并分支时,新分支中删除的文件在 master 中会被删除,新分支添加的文件在 master 中会被添加
- 合并冲突
# 创建分支
git branch <branchname>
# 查看本地分支
git branch -v
# 查看远程分支
git branch -r
# 切换分支
git checkout <branchname>
git checkout -b <branchname> # 创建并切换到新分支
# 删除分支
git branch -d <branchname>
# 合并分支
git merge <branchname> # 把 branchname 合并到当前分支
# fetch
git pull = git fetch + git merge
解决冲突
一、Git 简介
Git 是一款版本控制系统,它可以追踪文件的更改,并能多人协同开发,它最初由 Linus Torvalds 在 2005 年为更好地管理 Linux 内核而设计的; Git 是目前最流行的版本控制系统,主要功能有:
- 代码备份
- 版本回退
- 协同开发
- 权限控制
二、下载安装
下载地址:https://git-scm.com/ ,随后“傻瓜式”安装(一路下一步即可)
注意:如果自定义安装路径,切记路径中不要包含中文!
三、Git 基本使用
1. 起始配置
第一次使用 Git 的时候,我们需要配置姓名和邮箱,让 Git 知道当前开发者的基本信息
配置姓名:
git config --global user.name "Your Name"
配置邮箱:
git config --global user.email "email@example.com"
注意点:
- 命令中的各单词中间有空格。
- 上述两个命令只在第一次使用 Git 时运行, 若输入错误, 重新运行命令即可。
- 可以使用
git config --list
或git config -l
命令来查看配置信息 。 - 上述这两个命令不用自己手敲, 直接复制粘贴,随后修改【姓名】与【邮箱】即可。
2. linux 常用命令
Windows 为图形化操作形式,Linux 一般使用命令与系统进行交互,常用的命令如下:
命令 | 含义 |
---|---|
mkdir | 创建文件夹(make directory) |
cd | 改变工作目录,(change directory 缩写) |
touch | 创建一个文件 |
ls | 查看文件夹下的文件 (list 单词的缩写) |
cat | 查看文件内容 |
Tab | 路径自动补全 |
clear | 清屏(也可以使用 ctrl + L 快捷键) |
rm | 删除文件或文件夹 (删除不会进入回收站) -r 递归删除(用来删除文件夹) |
ctrl + c | 取消命令 c cancel 缩写 |
上下方向键 | 查看命令历史 |
3. vim 编辑器
Vim 是一款命令行下的文本编辑器,编辑方式跟图形化编辑器不同,基本操作
- 命令行
vim 文件名
打开文件 - 按
i
进入编辑模式 - 开始编辑文件内容
ESC
+:wq
保存并退出(w => write q => quit)ESC
+:q!
不保存并退出
4. Git 的三个区
以生活中做菜为例,整个过程中涉及到三个区域:① 货架、② 购物车、③ 厨房
Git 中同样也分为三个区域,分别是:
- 工作区(代码编辑区)
- 暂存区(暂时存储区)
- 版本区(版本控制区)
工作区、暂存区、版本区,三个区共同组成了一个 Git 仓库
5. 基本操作流程
**第一步:**创建一个空文件夹(名称不要包含中文),随后双击打开文件夹。
**第二步:**在文件夹空白处右键 ,随后点击 启动命令行。
**第三步:**创建一个 Git 仓库,命令为:git init
,命令执行成后,提示如下:
git init
执行后,会出现一个文件夹,这表示当前文件夹已成为一个 Git 仓库。
**第四步:**创建一些文件并编写代码,比如创建 【a.txt】,此时工作区已经有了新文件。
**第五步:**把工作区中【a.txt】添加到暂存区,具体命令为:git add a.txt
,此命令无提示。
补充:git add -A
可以把工作区中的所有文件,都添加到暂存区,比较常用。
**第六步:**把暂存区【a.txt】添加到版本区,具体命令为:git commit -m 'xxx'
,随后提示如下:
注意:此时我们先不用关心上图中的具体提示,后面会详细讲解。
关键步骤图示:
6. Git 三区的位置
Git 的三区位置大致如下(了解即可)
7. 查看仓库状态
git status
命令用于显示仓库当前的状态,git status -s
也用于查看仓库状态,但提示更为简短。
1. 若没有需要提交的内容,提示如下
2. 若工作区的内容没有提交暂存区,提示如下
3. 若暂存区的内容没有提交版本区,提示如下
8. 小练习
在工作区创建四个文件,如下图,接下来我们进行六个操作,并进行练习:
操作一
对 a、b 两个文件分别进行 git add
和git commit -m
操作,让二者接受版本控制。
使用git status -s
查看仓库状态如下:
结果含义:新增了 c 和 d 两个文件,但目前两个文件还在工作区,没有接受版本控制。
具体分析:
- 红色的含义:操作停留在工作区
- ?的含义:当前文件还没有接受版本控制
操作二
在刚才的基础上继续操作,对 c 文件进行git add
操作,将 a 存入暂存区。
使用git status -s
查看仓库状态如下:
结果含义:新增的 c 文件,已经存入了暂存区,新增的 d 文件还在工作区中。
具体分析:
- 绿色的含义:操作已经存入暂存区
- A的含义:新增(单词:add)
操作三
在刚才的基础上继续操作,对 a、b 文件进行内容修改后保存,不执行任操作。
使用git status -s
查看仓库状态如下:
结果含义:修改了 a 文件和 b 文件,且修改还停留在工作区中。
具体分析:
- 红色的含义:操作停留在工作区
- M 的含义:修改(单词: modify)
操作四
在刚才的基础上继续操作,对 a 文件进行git add
操作,将 a 存入暂存区。
结果含义:修改了 a 文件,且修改已存入暂存区;修改了 b 文件,且修改还停留在工作区
操作五
执行git add -A
命令,随后执行git commit -m '提交所有'
命令。
使用git status -s
查看仓库状态,没有任何提示,如下图:
操作六
在工作区中删除 d 文件,随后不执行任何操作。
使用git status -s
查看仓库状态如下:
结果含义:删除了 d 文件,且删除动作还停留在工作区中。
具体分析:
- 红色的含义:操作停留在工作区
- D 的含义:修改(单词: delete)
9. 删除暂存
git rm --cached <file>
可以将文件从暂存区中删除。
10. 对比差异
git diff
用于对比:工作区 vs 暂存区
git diff --cached
用于对比:暂存区 vs 仓库区
diff 命令的返回格式如下图:
注意:实际开发中文件多,且修改内容也多,我们会借助 git 的 GUI 工具进行文件差异对比。
11. 查看版本日志
借助于下面命令,可以查看整个 git 的提交记录
git log
:按提交时间降序列出所有提交,最新的提交会首先显示。
git log --oneline
:在git log
的基础上,以简洁的一行显示每个提交。
如果内容偏多, 需要使用方向键上下滚动, 按 q 退出。
12. 版本回退
Git 可以将项目代码内容切换到历史的任何一个版本,使用 git reset --hard 版本号
使用场景如下:
- 创建一个 git 仓库,随后创建:a、b、c、d 四个文件
- 随后对四个文件,分别依次执行:
git add
、git commit
进行版本控制 - 随后使用
git log --online
查看版本记录
- 现在我们使用
git reset --hard 版本号
把代码回滚到:刚提交完 b 文件的时候
- 两个注意点:
注意点 1:git reset --hard
会有如下动作:
① 切换版本区 HEAD (指针)指向
② 还原暂存区到对应版本
③ 还原工作区到对应版本
执行 git reset --hard
之前,最好进行: git add
、git commit
操作!
--soft:重置 HEAD 到指定提交,所有的更改都会自动添加到暂存区,对工作区无影响。
--mixed (默认值):重置 HEAD 到指定的提交,并且重置暂存区,对工作区无影响。
--hard:重置 HEAD 到指定的提交,并且重置暂存区,重置工作区!
注意点 2:使用 git reset --hard
版本回滚后,使用 git log
只能看到当前版本之前的记录,例如:刚才回到了 **13f46ca**
这个版本,那使用 git log --online
就会看到:
此时:看不见 c 文件和 d 文件的提交记录了,因为对于13f46ca 这个版本来说,c 文件和 d 文件的提交记录属于未来,是看不到的,要想看到最完整的日志记录,可以使用git reflog
命令。
13. 修改提交
git commit --amend
命令可以修改最近一次提交,它可以:
- 重新编辑上次的提交信息。
如果在一次提交后,意识到提交信息有误或不够详细,可以使用 git commit --amend
来重新编辑上次提交信息
- 将新的更改添加到上次提交中。
如果在一次提交后,意识到忘记将某文件提交了,可以先使用 git add
将这些遗漏的更改添加到暂存区,然后通过 git commit --amend
将它们添加到上一个提交中。
场景演示(重新编辑上次的提交信息)
- 创建一个 a 文件,其内容如下(包含 4 行内容)
- 随后对 a 文件进行版本控制,但提交信息编写有误
- 查看一下提交记录
- 随后使用
git commit --amend
命令进行修改提交,弹出 vim 编辑框,随后编辑好正确的提交信息,保存并退出
- 此时提示提交成功
- 随后查看提交日志如下:
场景演示(将新的更改添加到上次提交中)
- 进行了一次提交后,查看提交记录如下:
- 但发现 a 文件中少写了一些代码,随后我们补上了少写的代码,然后想对最近一次提交进行修改,执行
git add -A
后使用git commit --amend
命令进行修改提交。
- 随后弹出 vim 编辑框,我们在编辑框里重新编写提交说明,随后保存并退出。
。
- 随后提交完毕,我们使用
git log --online
查看提交记录,发现提交已经被修改。
14. 忽略文件
在项目开发过程中有些文件不应该存储到版本库中,这个时候配置忽略这些文件。
git 中需要创建一个文件 『.gitignore
』文件来设置忽略,『.gitignore
』文件与.git
目录同级,常用规则如下:
内容 | 含义 |
---|---|
temp | 忽略任何路径下的名为 temp 的文件、文件夹。 |
*.log | 忽略任何路径下以.log 结尾的文件。 |
/dist | 忽略根目录下的 dist 文件,不会忽略其他目录下的 dist 文件 |
备注:.gitkeep
文件可以把空文件夹提交
15. 分支
15.1. 分支的概念
分支是 git 的一个重要特性,它可以让开发人员从主线上分离出来,在一个独立的线路上继续开发,最后可以灵活的选择合并分支,还是丢弃分支。用一个生活中的例子,来理解分支:
比如我们正在写一本小说,这本小说的当前内容就像是 git 中的 master 分支,现在我们有几个新的想法,比如:新的角色、新的剧情,但不确定这些是否最终一定出现在故事里,所以我们可以这样做:
- 可以为每个新的想法,创建一个新的笔记本(一个笔记本就相当于 git 中的一个新分支)
- 每个笔记本(分支)中都可以自由地探索想法,且不会搅乱你的当前内容(master 分支)
- 当我们觉得一个剧情线非常好,并且想要将其包含在故事中时,就会把那个笔记本的内容(分支)合并到你的当前内容(master 分支)中。
- 如果某个想法实验失败,可以选择抛弃那个笔记本(相当于 git 中的删除分支),且这个过程不会影响当前内容(master分支)
15.2. 创建与切换分支
- 使用
git branch xxx
可以创建分支,其中xxx
是分支名字
备注:创建完 test 分支后,tets 分支并不是空的,而且保留了 master 分支当前所有的提交记录。
- 使用
git branch
可以查看所有分支
- 使用
git checkout xxx
可以切换分支
- 注意点如下:
① 切换分支前,最好把当前分支管理好,即最好进行:add
、commit
操作。
② 切换分支后,工作区、暂存区、会受到影响,具体为:
- 工作区:会变为切换到的分支的最后一次提交的状态
- 暂存区:同上,且如果暂存区有未提交的更改,那这些更改会被带到新分支的暂存区上。
比如:在 test 分支对 x 文件进行了暂存,没提交,随后切换到 master 分支时,x 文件会自动加在 master 分支的暂存区
15.3. 合并分支(快速合并)
例如我们有 master 和 test 两个分支,test 分支是领先于 master 分支的,且 tets 分支包含 master 的所有历史记录,那么这时就可以触发 git 的快速合并,具体演示如下:
第一步:创建 a、b 两个文件,随后提交到 master 分支。
第二步:创建 test 分支,随后在 test 分支创建一个 c 文件,随后提交到 test 分支。
第三步:切回 master 分支
此时发现工作区中 c 文件消失(因为 master 分支中没有 c 文件)。
第四步:把 test 分支合并到 master 分支
使用git merge test
合并分支,合并成功后,会发现工作区中已经有了 c 文件,且可以查看到 c 文件的提交记录。
15.4. 合并分支(提交合并)
场景描述:当进行分支合并时,若两个分支有不一致的版本,则会提示输提示输入提交信息,在当前分支形成一个新的提交记录,具体场景请执行上述 15.3
的前三步,然后接下来执行下面步骤:
第四步:切到 master 分支后,创建 d 文件,随后提交到 master 分支。
第五步:在 master 分支中合并 test 分支
输入git merge test
命令,进行分支合并
出现如下提示,含义是本次分支合并,存在不一样的版本,请为生成的新版本编写说明
输入完说明后,保存并退出
随后提示合并完毕
15.5. 删除分支
git branch -d xxx
可用于删除一个分支,其中xxx
是分支名,例如我们删除 test 分支:若删除时提示下图,说明:要删除的分支包含了一些尚未合并到其他分支的内容。
解决办法有三种:
- 第一种方式:将要删除的分支合并到一个其他的分支,再进行删除。
- 第二种方式:使用
git branch -D xxx
强制删除。 - 第三种方式:使用
git config advice.forceDeleteBranch false
命令关掉该提示。
15.6. 分支变基
在 Git 中,合并(merge)和变基(rebase)都是用于整合来自不同分支的更改的操作,它们区别如下:
- 合并(merge):
将两个分支的历史合并在一起,gti 会创建一个新的“合并提交”,所有的分支和合并点都会被保留在历史中,有完整的历史记录。
- 变基(rebase)
将一个分支(test)上的提交重新应用到另一个分支(master)上,变基会重写项目历史,因为它实际上是在创建一系列新的提交,会产生一个更线性的历史记录,看起来更干净、更简单。
15.7. tag(标签)
在 Git中,标签(Tag)是用来指向特定提交的引用,通常用于标记项目中的重要点,比如版本发布。标签分为两种类型:
- 轻量标签(Lightweight)
轻量标签只是简单地指向一个提交,不包含其他信息,创建轻量标签不会存储任何额外的信息。
- 附注标签(Annotated)
附注标签存储了额外的信息,例如:标签名、标签信息、创建者名字、电子邮件、创建日期等。因为它们包含了更多的信息,附注标签更适用于公共或正式发布的场合,比如软件版本的发布。
创建标签
命令 | 作用 |
---|---|
git tag 标签名 版本号 | 给指定提交打 轻量标签 |
git tag -a 标签名 版本号 -m "标签描述" | 给指定提交打 附注标签 |
上述两个命令可以不写版本号,不写就是给最新提交打标签 | |
git tag | 查看标签 |
git show 标签名 | 查看标签信息 |
git tag -d 标签名 | 删除标签 |
15.8. 游离分支
git checkout
也可以将代码签出到指定版本,即可以执行git checkout 具体版本号
,当签出到指定版本时,签出的代码出于一个游离分支中,如下图操作:
游离分支上可以对代码进行版本控制,但要注意:一旦从游离分支切走,游离分支的提交不会交给任何一个分支,所以对于游离分支我们的原则是:
- 尽量不修改游离分支的代码(只是看一看某个版本的代码)。
- 若确实需要修改游离分支代码,应该从当前游离分支,创建出一个新的分支,随后去修改。
- 若修在游离分支上发生了提交,随后从游离分支切走了,就要使用 reflog 寻找游离分支的提交。
16. GitFlow
GitFlow 是团队开发的一种最佳实践,将代码划分为以下几个分支
分支 | 含义 |
---|---|
master | 主分支,只保存正式发布的代码。 |
develop | 开发分支,开发者的编写的代码最终要出现在这个分支。 |
hotfix | 线上 bug 修复分支,修复完毕后要合并回 master 和 develop 分支,同时在 master 分支上打一个tag。 |
feature | 功能分支,当开发某个功能时创建一个单独的分支,开发完毕后再合并到 dev 分支。 |
release | 待发布分支,Release分支基于Develop分支创建,在这个Release分支上测试。 |
四、Gitee
1. Gitee 简介
Gitee 是一个 Git 仓库管理网站,可以创建远程中心仓库,为多人合作开发提供便利,与 Gitee 类似的网站还有很多,例如:GitHub、GitLab 等等,本教程选择 Gitee 进行讲解,有了 Gitee 的基础后 GitHub 和 GitLab 也同样能很快上手。
2. 关联远程库
第一步:维护好本地仓库(所有文件均接受版本控制)。
git add xxxx
git commit -m '注释'
第二步:注册并激活 Gitee 账号。
第三步:创建远程仓库,并获取仓库的地址。
第四步:配置本地仓库关联远程仓库:
git remote add origin https://xxxx/xxxx/xxxxx.git
备注:
- 查看当前仓库关联远程仓库地址:
git remote -v
- 更改远程仓库的 URL:
git remote set-url origin 新的仓库URL
- 删除与远程仓库的关联:
git remote remove origin
3. 推送代码
将本地仓库的 master 分支推送到远程仓库
git push -u origin master
命令说明:
- push 表示推送。
- -u(upstream) 表示关联,加上 -u 以后,后续提交时可以直接使用 git push 即可。
- origin 远端仓库的别名。
- master 本地仓库的分支名称。
4. 拉取代码
当本地仓库想获得远程仓库的最新修改时,可以使用git pull
命令拉取远端代码。
git pull
备注:git pull 会将远端代码自动执行合并操作,即:将远程分支的修改合并到本地当前分支。
5. 关于冲突
- 合并/变基引起的冲突:两个分支在同一文件的同一位置都有修改时,合并或变基时会引起冲突。
- 拉取引起的冲突:不同的开发者修改了同一文件的同一位置都有修改时,拉取代码会有冲突。
6. 克隆远程库
获取一个远程仓库的地址,随后执行克隆命令
git clone https://xxxx/xxxx/xxxx.git
使用 --depth 1
参数可以克隆仓库的最近一次提交,这样可以减少克隆所需的时间和空间。
git clone --depth 1 https://xxxx/xxxx/xxxx.git
注意点:
- 克隆下来的仓库,使用
git branch
命令,只能看到默认分支,其他分支其实也已经克隆下来了,但不出现在git branch
列表中,需要使用git branch -r
或gir branch -a
来查看。
- 需要切换到其他分支时,可以直接
git checkout -b xxx origin/xxx
来进行切换,当然对于 1.7.0 以后得 git 版本,也可以使用简短的命令:git checkout xxx
来切换。
7. SSH 协议
7.1. 公钥加密
我们来举个例子,你在 A 城市,想给你在 B 城市的朋友张三发送一个机密的信件,由于工作原因,你无法亲自去送,同时你也担心快递不能严格的保密。这时你就可以使用公钥加密技术,大致思路是:
- 张三先给你一个特制的保险箱(公钥)****,这个保险箱 仅有一把 能打开它的钥匙,钥匙在张三那里。
- 你将信件放入保险箱并锁上,随后交给快递员,快递员携带着这个箱子去送货,但 无法打开 它。
- 快递到达,**张三手里的钥匙(私钥)**打开保险箱,取出信件。
总结:
- 通过这种方式,即使在不完全可信的通道上,你的信件也能安全到达目的地,没有人能够在途中打开保险箱并窃取它。这就是公钥加密的工作原理。
- 使用公钥(所有人可见的保险箱)来加密信息,而只有对应的私钥(只有接收者持有的钥匙)能解密信息。这种方法不仅保护了数据的安全性,还确保了数据传输的私密性和完整性。
7.2. SSH 简介
SSH(Secure Shell)是一种网络协议,SSH利用公钥加密技术提供了一种安全的方法,来管理和操作远程计算机,保护数据的安全和隐私
7.3. Gitee 使用 ssh
第一步:生成 SSH 公钥
- 使用
ssh-keygen -t ed25519 -C"Gitee SSH Key"
命令生成公钥。 - 提示输入公钥的保存地址,如无需修改,直接回车即可:
- 提示是否为私钥建立密码,如需要直接输入,不需要直接回车:
- 提示确认密码,输入和上一步相同的密码即可,若无密码直接回车:
- 提示生成完毕
第二步:在 Gitee 上配置公钥
- 输入
ls ~/.ssh/
命令查看生成的公钥与私钥
- 私钥文件
id_ed25519
- 公钥文件
id_ed25519.pub
- 使用
cat ~/.ssh/id_ed25519.pub
查看公钥
- 复制公钥,添加到 Gitee 设置中
第三步:本地库与远端交互
- 尝试使用 ssh 方式克隆仓库
- 第一次操作,此处会有提示,输入 yes 即可
- 克隆成功
后续的拉取,推送,可以直接尽心,无序任何的密码输入。
五、VSCode 中使用 git
1. 插件推荐
VSCode 中有很多 git 相关的插件,本教程中推荐下面两个:
2. 创建仓库
如图所示点击操作,即可借助Vscode
来创建仓库
不同的工具创建出来的主分支名字可能不一样,比如 Vscode 中通过点击下方按钮创建的仓库,主分支的名字就叫main
,当然也可以进行修改,让 Vscode 默认的主分支名是 master
3. 版本控制
点击“+”将文件添加到暂存区(相当于git add
命令)
点击【提交】将文件添加到版本区(相当于git commit
命令)
4. 撤销暂存
点击“-”撤销对 b 文件的暂存
5. 查看日志
点击【Git Graph】查看仓库日志
6. 对比差异
点击文件名对比文件和上次提交的差异
点击某个版本的提交后,按住 ctrl 点击另一个版本号,可以对比两个版本的区别
7. 版本回退
借助 Git Graph 以游离分支的形式回退(本质是 git checkout 版本号
)
借助 Git History 版本回退(本质是 git reset --hard 版本号
或 git reset --soft 版本号
)
8. 添加 tag
9. 创建分支
10. 分支合并
在当前分支上鼠标右键,随后选择将当前分支合并到哪个分支
选择 Yes,merge
11. 分支变基
12. 推送代码
13. 拉取代码
14. 处理冲突
六、附录
1. Git 官方书籍
https://git-scm.com/book/zh/v2/
2. git 目录介绍
- hooks 目录包含客户端或服务端的钩子脚本,在特定操作下自动执行
- info 信息文件夹. 包含一个全局性排除文件,可以配置文件忽略
- logs 保存日志信息
- objects 目录存储所有数据内容,本地的版本库存放位置
- refs 目录存储指向数据的提交对象的指针(分支)
- config 文件包含项目特有的配置选项
- description 用来显示对仓库的描述信息
- HEAD 文件指示目前被检出的分支
- index 暂存区文件,是一个二进制文件 (git ls-files)
切记: 不要手动去修改 .git 文件夹中的内容
3. CRLF
CRLF 是Carriage-Return Line-Feed 的缩写。
CR 表示的是 ASCII 码的第 13 个符号 \r 回车,LF 表示的是 ASCII 码表的第 10 个符号 \n 换行。
每个操作系统对回车换行的存储方式不同
- windows 下用 CRLF(\r\n)表示
- linux 和 unix 下用 LF(\n)表示
- mac 系统下用 CR(\r)表示
4. 卸载密码管理工具
执行命令: git config --system --unset credential.helper