学习Git后能收获什么?
- 学习基本的Git 命令了解其原理,遇到Git的相关问题时,能自行排查解决
- 学习研发流程中正确的流程和规范,正确使用Git
Git 是什么?
Git是一种分布式版本控制系统,用于跟踪代码的修改、管理和协作开发。它可以记录文件的修改历史,并允许多人合作开发同一个项目,通过分支管理系统可以进行代码的并行开发和合并。Git具有快速、高效和灵活的特性,广泛应用于软件开发领域。
介绍版本控制的发展历史,为什么会出现Git
介绍Git 的发展历史?
引用官方Git文档中的部分词.“version control system" 版本控制系统
他是什么?记录一个或若干文件的变化,以便于在出错时可以及时的回滚,也方便于将来查询特定版本的修订情况
我们为什么要学习Git?
-
协同工作
业界大多数公司都是基于Git进行代码管理,因此Git是程序员必备技能
-
开源社区
目前大多数开源项目都是由Git维护的,参加这些项目开发需要使用Git
那么问题来了,我们怎么实现版本控制呢?
目前来说版本控制有三种方法,分别是
-
本地版本控制
最初方式:
本地复制文件夹,完成版本控制,通过不同的文件名来区分版本。当然这种最初的方式在现在的毕业论文当中
- 毕业论文.doc
- 毕业论文改1.doc
- 毕业论文改2.doc
- 毕业论文完成版.doc
- 毕业论文最终版.doc
- 毕业论文最最终版.doc
- 毕业论文最终终极版.doc
- 毕业论文绝对不改版1.doc
- 毕业论文绝对不改版2.doc
- 毕业论文打死不改版.doc
- 遗书.doc
这种便是很常见的本地版本控制,这种方法效果很明显,你做了多少个版本(doge,以及你入土的心路历程。
好处就是这种方法简单快捷,无脑操作,备注可以直观体现在文件名上面。
缺点也非常明显
- 首先本地的版本控制只能保存在本地,无法进行多人的协作 (eg: 腾讯文档 飞书)使用场景特别局限
- 特别容易犯错,要是不小心覆盖错了文件,没有任何后悔药可以食用
- 如果项目文件特别大的时候,保存在本地的多个副本进行版本控制费时费力。
这种方式的解决方案:开发了一些本地的版本控制软件——RCS,大多都是采用某种简单的数据库来记录文件的历次更新差异。
原理:在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。
-
集中式版本控制
上面的例子大家已经熟悉了,这时候就有人提出解决办法,如果用一个远程服务器来保存所有人的文件不就可以了。因此集中版本控制便诞生而出
-
代表性工具——SVN
-
原理:
1.提供一个远程的服务器来保存文件,所有用户的提交都保存到该服务器中
2.对于不同用户提交的增量文件 Diff ,需要本地自行协商上传哪一份文件作为云服务器的存储版本
-
优点:
1.适用于一些游戏美术团队的素材,因为其支持二进制文件,对大文件的支持更好 2.学习简单,更易于操作。只要会上传文件就行。
-
缺点:
1.本地不存储版本管理的概念,所有提交只能连上服务器才能提交 2.分支的支持不够好,对于大型项目团队合作比较困难 3.用户本地不保存所有版本的代码,如果服务器发生故障容易导致历史版本的丢失
-
-
分布式版本控制
-
代表性工具——Git
-
原理:
1.每个库都有完整提交历史 2.每次提交记录都是由完整的文件快照,而不是记录增量(不推荐提交大文件) 3.通过 Push 操作完成和远端代码的同步
-
优点:
1.分布式开发,每个库都是完整的提交历史,支持本地提交,强调个体 2.分支管理功能强大,方便团队合作,多人协同开发 3.效验和机制保证完整性,一般只添加数据,很少执行删除操作,不容易导致代码丢失
-
缺点:
1.相对于SVN更复杂,学习成本更高,命令操作更多 2.对于大文件的支持不佳,可通过
git-lfs 工具弥补这个功能 -
与SVN的不同之处
-
-
Git 发展历史
Linus Torvalds 同时也是 Linux 作者
开发时间:只花了俩周时间
基于 Git 的平台
- Github 全球最大的代码托管平台,大部分的开源项目都可以放到这个平台
- Gitlab 全球最大开源代码托管平台,定制化高,项目所有代码都是开源的,便于在自己的服务器上完成 Gitlab 的搭建
- Gerrit 由 Google 开发的一个代码托管平台,主要对Android的开源项目支持较好-安卓多仓
-
Git的基本使用方式
在之前我们介绍了 GIt 的前世今生,现在我们需要了解 Git 的一些基本命令,才能更好的让 Git 为我们所用
Mac 默认就可以直接使用 Win 安装 Gitbash
分为三部分
-
配置
git config
git remote
-
提交代码
git add
git commit
-
远端同步
-
拉取代码
clone
pull
fetch
-
推送代码
push
-
-
-
明明配置好 Git ,为什么还是拉取不了代码?
没有配置密钥,无法拉取,配置权限
-
Fetch 远端分支,为什么没有在本地历史中出现?
-
Git 项目初始化
mkdir study
cd study 进入 study 这个文件夹
git init 把这个目录变成git可以管理的仓库其他参数
--initial-branch 初始化的分支
--bare 创建一个罗仓库 (纯 Git 目录)
--template 通过模板构建预先创建好的系统目录
执行
tree <folder> /f 命令查看文件夹及其内部文件情况 Git 目录卷 SYS 的文件夹 PATH 列表 卷序列号为 D4D8-5401 C:\USERS\xxx\DEMO\.GIT │ config / │ description │ HEAD │ ├─hooks │ applypatch-msg.sample │ commit-msg.sample │ fsmonitor-watchman.sample │ post-update.sample │ pre-applypatch.sample │ pre-commit.sample │ pre-merge-commit.sample │ pre-push.sample │ pre-rebase.sample │ pre-receive.sample │ prepare-commit-msg.sample │ push-to-checkout.sample │ update.sample │ ├─info │ exclude │ ├─objects │ ├─info │ └─pack └─refs ├─heads └─tagslike this Windows下打开文件夹默认为空,不可见。
Git config
不同级别的 Git 配置
--global
--system
--local
每个级别的配置可能重复,但是低级别的配置会覆盖高级别的配置
常见的Git 配置
在开始使用 Git 前,你需要自报家门,让别人知道你是谁,因此需要先进行用户名的配置
用户名配置
git config --global user.name "example" git config --global user.email name1@example.mail.com`Instead of 配置
git config --global url.git@github.com:.insteadOf https://github.com HTTP 和 SSH 协议之间的转换Git 命令别名的配置
git cpmfig --global alias.cin "commit --amend --no-edit"这里的
alias 可以简单理解为配置别名的缩写 使用了以上命令 即可使用cin 代替commit --amend --no-editGit Remote
git remote -v 使用这个命令查看 Remote ,默认是没有的,需要我们自行配置我们需要添加 Remote ,可以使用 HTTP 或 SSH,用到这行命令
git remote add origin_http example.com 之后再执行查看 Remote的命令就会发现多出了俩个值origin_http example.com (fetch) origin_http example.com (push)此时我们查看 .git 文件夹内的 config 文件,会发现结尾多出了刚才添加的 Remote 配置
[remote "origin_http"] url = example.com fetch = +refs/heads/*:refs/remotes/origin_http/*如果不小心输入错误,我们可以在命令后添加
-h 的参数,查看帮助命令,学习如果删除 Remote 即git remote -h ,受限于篇幅,不完整贴出运行结果同一个 Origin 设置 不同的 Push 和 Fetch URL ,例如我们 Fork 项目时 可能会用到
HTTP Remote
需要我们进行免密配置,以免每次登录都需要输入
免密配置俩种方式
-
内存
-
硬盘
将秘银信息存在指定的文件当中
通常来说,不考虑采用这种方式来连接远端操作,不安全
SSH Remote
URL:git@github.com:git/git.git
免密配置
目前的Key 的类型有四种,分别是 dsa 、rsa、ecdsa、ed25519
默认使用的时 rsa ,但是由于一些安全问题,现在已经不在推荐使用 dsa 和 rsa (部分 Windows 系统层面禁止使用) ,优先推荐使用 ed25519
使用命令
ssh-keygen -t ed25519 -C "your_email@example.com" 密钥默认存在 ~/.ssh/id_ed25519.pub在运行命令时会出现以下信息
Enter file in which to save the key (C:\Users\xxx/.ssh/id_ed25519): 直接 Enter 即可 这里的目录也是上面 ~ 省略的上级文件夹
Overwrite(y/n)? 直接 输入 y 后回车 打开系统中.pub 后缀的公钥文件,将里面的内容复制到代码托管平台 SSH配置部分即可 -
-
Git Add
首先,我们要知道
git add 的命令目的是将文件作出的修改从工作区添加到暂存区使用
git add . 命令可以通配添加所有修改变化,正常格式为git add 单个文件名|通配符
git cat-file -p <object> 即可查看object 目录内包含的加密文件信息 先执行tree 命令查看所有文件夹内文件需要注意!
-
命令里
<object> 由 文件夹名 + 文件名组成eg:以下是
tree 命令执行后的部分结果, 根据执行结果这里的<object> 实际是 012a517ca74b3dc7a35ca7c70a782138840d0469│├─objects │ ├─01 │ │ 2a517ca74b3dc7a35ca7c70a782138840d0469 -
知道了object后便可以使用
cat-file 来查看加密后的文件了,组合成完整命令便可以查看 -
如果在执行时出现以下类似的错误,可能不只限定于
git add 命令报错。fatal: not a git repository (or any of the parent directories): .git如有这样的提示,代表你可能进入到了一个错误的文件夹,其文件夹内没有
.git 子文件夹,使用cd 命令进入到当初使用git init的文件夹即可。
-
-
Git status
使用
git status 命令查看 Git 状态 可能输出以下结果,代表没有任何文件需要提交说明我们在最近一次提交之后,没有做任何改动,是一个 "working tree clean",翻译过来就是干净的工作目录。
On branch test #test为你所在分支的名称,一般为master nothing to commit, working tree clean -
Git commit
聊完了 Git add 我们就要知道 Git commit 实际上就是让处于暂存区的修改真正的提交到本地仓库中
通常我们习惯于使用
git commit -m "your text" 来提交,"your text" 可以填写你对这一版本的注释,每提交一次就是完成了一次的版本管理如果你没有在commit 命令后
-m <comment> 选项,Git 会尝试为你打开一个编辑器以填写提交信息。 如果 Git 在你对它的配置中找不到相关信息,默认会打开 vim。屏幕中会出现以下输出信息:# Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: hello.php # ~ ~ ".git/COMMIT_EDITMSG" 9L, 257CPS:此时的界面 为 Vim 编辑器 可直接在开头加上本次commit 的备注,
:wq 即可保存配置并退出
-
当然你也可以使用
git commit -m "your text" 来提交,通常会输出类似下图的信息 第二行输出多少文件改变,并给出具体的文件修改树[master 258742d] add file 6 files changed, 217 insertions(+) create mode 100644 wwwroot/Program.cs create mode 100644 wwwroot/Startup.cs create mode 100644 wwwroot/WeatherForecast.cs create mode 100644 wwwroot/appsettings.json create mode 100644 wwwroot/redme.txt create mode 100644 wwwroot/tools.getquicker.cn.csproj
-
git log
git log 可以查看commit 的记录commit 258742d75cc3f748bb4042e8afd87c74ed1af040 (HEAD -> master) Author: Petercode <Petercode1129@gmail.com> Date: Sat Aug 12 17:51:10 2023 +0800 add file commit 5967d5b954e59163b0f3828b685ed196d4e86d26 Author: Petercode <Petercode1129@gmail.com> Date: Mon Aug 7 23:25:20 2023 +0800 nice try fatal: Not a valid object name
Objects
commit / tree / blob 在git里面都统一称为 Object
- 通过commit 寻找到 Tree 信息,每个 Commit 都会存储到对应的 tree id
- 通过tree 存储的信息,获取到对应的目录树信息
- 从tree中获得 blob id 通过blob id 获取对应的文件内容
Refs
运行 tree 命令以下为截取的refs文件夹内的文件情况
└─refs
├─heads
│ master
│
└─tags
我们使用 git checkout -b test 创建一个 test 的分支,再次使用 tree 命令
└─refs
├─heads
│ master
│ test
│
└─tags
Refs 文件中存储的内容 就是对应 的 Commit ID
因此把 ref 当作指针,指向对应的 commit 来表示对应的 Ref 版本。
而不同种类的 ref refs / heads 前缀表示的是分支,除此之外还有其他种类的 ref