1.Git是什么
在我们工作学习时候,在编写文档,开发代码时候,为了防止文档丢失,代码开发之后发现不如之前的版本,这时候就需要备份之前的文档,代码,不得不创建一个副本,防止修改当前文档,代码之后,找不到之前的版本了,但随着版本数量的增多,随之就会出现一些问题,比如:这些文档我修改了哪些内容?一不小心删除了其中一个文档,怎么找回来?
1.1 版本控制器
为了更方便我们管理这些不同版本的文件,便有了版本控制器。版本控制器通俗来讲就是可以记录我对工程文件的每一次改动和版本迭代的一个管理系统,同时也支持多人协作,比如:别人可以看到我提交的文档,根据我的文档再进行编写。
- 现在最主流的版本控制器就是Git.Git可以控制电脑上所有格式的文件,是一个免费的开源的分布式管理系统。
- Git是开放源代码的代码托管工具,最早是在LInux下开发的。开始也只能适用于Linux平台,后面慢慢的被移植到Windows。现在可以在Linux,Unix,Mac和Windows中正常运行
2.Git安装
Git官方下载链接:Git下载链接
找到你想要下载的版本,点击下载即可
这里我讲解一下LInux上Git的安装过程.
2.1 Linux下Git安转过程
- Linux — contos:
sudo yum install git -y
- Linux — ubuntu
sudo apt install git -y
- 查看给git版本
git --version
3.Git基本操作
3.1创建本地仓库
仓库是版本控制的一个文件目录,如果我们想对文件进行版本控制就必须先创建一个仓库出来。
创建Git本地仓库的命令为
git init
创建一个目录以后,我们就可发现目录下就多了一个.git的隐藏文件,.git目录是Git用来跟踪管理仓库的。
.git 目录(通常称为.git文件夹)是 Git 版本库的核心,存储了 Git 进行版本控制所需的所有元数据和对象。以下是其包含的文件和目录
3.2配置Git
安装Git首先要做的事情就是设置你的用户名称和e-email地址
配置命令:
- git config [–global] user.name “Your name”
- git config [–global] user.email “email@example.com”
其中 –global 是一个可选项,如果使用了给选项,机器上Git仓库都会使用这个配置。如果你希望在不同仓库中使用不同的配置,就可以不用 –global 选项,但不许在仓库中执行命令。
查看配置命令:
- git config -l
删除配置信息:- git config [–global] --unset user.name
- git config [–global] --unset user.email
(注意:如果你是用global选项创建的name和email,删除配置信息的时候也需要带global选项)
4.工作区、暂存区、版本库
- 工作区: 你正在编辑的项目文件所在的目录(即本地可见的文件和文件夹,.git 目录外的所有内容)
- 暂存区: 一般存放在 .git 目录下的 index 文件(.git/index中),暂存区也叫做索引
- 版本库: 英文名 repository ,Git 的核心数据库,存储所有提交历史、分支、标签等元数据(位于 .git 目录),版本库中的所有文件都可以被 Git 管理起来,他会记录每个文件的修改删除,以便还原其中的某个版本。
4.1 工作区、暂存区和版本库的关系:
- 在创建 版本库 时,Git会为我们会为我们创建唯一一个 master 分支,以及指向 master 的一个指针 HEAD.
- 在对工作区 修改或新增 的文件执行 git add 命令时,暂存区目录是的文件索引就会被更新
- 当执行提交操作 git commit 时,master分支会做相应的更新,可以理解为暂存区的目录树真正的被写入到了版本库中。
4.2 工作区的修改何时生成 Git 对象?
- 未暂存时:仅修改工作区的内容(不执行任何 Git 命令),不会生成新的 Git 对象。
- 执行 git add:
Git 会将工作区的修改内容转换为 Blob 对象,存储在 .git/objects 中。同时更新暂存区(Index),记录这些 Blob 对象的哈希值。 - 执行 git commit:
Git 会根据暂存区的 Blob 对象生成 Tree 对象(目录结构)和 Commit 对象(提交信息),并写入 .git/objects。
4.3 添加文件(git add,git commit,git log,git reflog)
在 .git 目录下新建一个或多个文件或目录,执行命令 git add 命令后将文件添加到暂存区:
- 添加一个文件或多个文件到暂存区:git add [file1] [file2]
- 添加指定目录到暂存区:git add [dir]
- 添加当前目录下的所有文件到暂存区:git add .
再使用 git commit 命令将暂存区内容添加到本地仓库:
将暂存区的全部内容添加到本地仓库中:git commit -m “message”
将暂存区的指定文件或目录添加到仓库中:git commit [file1] [dir1] … -m “message”(注意 -m 选项是不能够被忽略的,后面的 message 需要用户自己填写,用来记录你的提交细节)
如果我们将代码提交到本地仓库中了,我们可以使用 git log 或者 git reflog 命令,来查看历史提交记录,如果嫌输出信息太多,可以加上 –pretty=oneline 参数
这里的一长串字符串 3dfccaa7cbeb30e19a73b22d6ed70835a7fce695 表示的是每次提交的 commit id ,这是由SHA1计算出来的一个非常大的数字,用16进制表示。
4.4 .git文件分析
.git目录结构:
index 就是暂存区,add后的内容添加到这里
HEAD 就是默认指向 master 分支的指针:
默认的master分支:
这里的 commit id 保存的就是当前最新的 commit idobjects 为Git的对象库,里面包含了创建的各种版本库对象及内容。
执行 git add:
Git 会将工作区的 修改内容(注意是修改内容) 转换为 Blob 对象,存储在 .git/objects 中。同时更新暂存区(Index),记录这些 Blob 对象的哈希值。
执行 git commit:
Git 会根据暂存区的 Blob 对象生成 Tree 对象(目录结构)和 Commit 对象(提交信息),并写入 .git/objects。
查找 object 时要将 commit id 分成2部分,其前2位是⽂件夹名称,后38位是⽂件名称。
找到这个⽂件之后,⼀般不能直接看到⾥⾯是什么,该类⽂件是经过 sha (安全哈希算法)加密过的⽂件,我们可以使⽤ git cat-file 命令来查看版本库对象的内容:
hooks存放自动化脚本(如 pre-commit、post-receive),在特定 Git 操作时触发
refs/ 存储指向提交的引用(指针)。
子目录:
heads/: 分支的引用(如 main 分支对应 refs/heads/main)。
tags/: 标签的引用(如 v1.0 对应 refs/tags/v1.0)。
remotes/: 远程分支的引用(如 origin/main)。config 当前仓库的本地配置(如远程仓库地址、别名、分支跟踪规则)。全局配置在 ~/.gitconfig 中。
description 仓库的描述信息(默认未使用,常用于 GitWeb 等工具) ‘
logs/ 记录分支和 HEAD 的变更历史(如提交、重置、合并)。
文件:
HEAD: 当前 HEAD 的移动记录。
refs/heads/branch: 分支的历史变更。info/ 仓库的附加信息。
文件:
exclude: 仓库级别的忽略规则(类似 .gitignore,但仅对本仓库生效)。
4.5 修改文件
在上面我们了解到 Git 会将工作区的 修改内容(注意是修改内容) 转换为 Blob 对象,存储在 .git/objects 中。那我们怎么查看修改的内容呢?
- 首先我们可以通过 git status 命令查看·你上次提交是否对文件有修改。
- 通过 git diff [file] 命令用来显示暂存区和工作区文件的差异,看代码哪里修改了。也可以通过 git diff HEAD – [file] 俩查看版本库和工作区文件的区别
testfile:
5 版本回退
执行 git reset 用于回退版本,可以指定退回某一次提交的版本。回退本质上是要将版本库中的内容进行退回,工作区和暂存区有命令行参数决定。
git reset [–soft | --mixed | --hard] [HEAD]
- –mixed 为默认选项,使⽤时可以不⽤带该参数。该参数将暂存区的内容退回为指定提交版本内
容,⼯作区⽂件保持不变。 - –soft 参数对于⼯作区和暂存区的内容都不变,只是将版本库回退到某个指定版本。
- –hard 参数将暂存区与⼯作区都退回到指定版本。切记⼯作区有未提交的代码时不要⽤这个命令,因为⼯作区会回滚,你没有提交的代码就再也找不回了,所以使⽤该参数前⼀定要慎重。
- HEAD 说明:
可直接写成 commit id,表⽰指定退回的版本
◦HEAD 表示当前版本
HEAD^ 上⼀个版本
HEAD^^ 上上⼀个版本
以此类推…
可以使⽤ 〜数字表示:
HEAD~0 表示当前版本
HEAD~1 上⼀个版本
HEAD^2 上上⼀个版本
以此类推…
工作区 | 暂存区 | 版本库 | 参数 |
---|---|---|---|
不回退 | 不回退 | 回退 | –soft |
不回退 | 回退 | 回退 | –mixed(默认选项) |
回退 | 回退 | 回退 | –hard |
如果 git reset --hard 之后反悔了,还可以回退到回退之前的那一个版本吗?
答案是可以的,通过 git reflog 拿到 commit id ,然后再执行 git reset --hard 【commit id】 就可以回退了
git 回退可以理解为master存储的 commit id 改变了,如下图的示意图:
6. 撤销修改
如果你在编写代码时发现自己写的代码看起来不怎么完美,想要撤销修改,这时候有几种办法,通过 git diff [file] 之后手动删除代码,但这样很有可能就会出现bug。
这时候Git就为我们提供了很好的办法,如下表:
情况 | 工作区没有add | 已经add,但没有commit | 已经add并且commit |
---|---|---|---|
解决办法 | git checkout – [file] | git reset --mixed + git checkout – [file] | git reset --hard HEAD^ |
其中 git checkout – [file] 命令让⼯作区的⽂件回到最近⼀次 add 或 commit 时的状态
7. git 删除文件
在 Git 中删除文件也是一个修改操作。我们在 Git 中提交之后想要删除 commit提交 后的文件,就可以使用一下命令来将 工作区 和 暂存区 的文件删除:
git rm [file]
通过 git rm [file] 之后就可以把工作区 和 暂存区 的文件删除,然后再对删除提交,执行 git commit -m “delete file” 提交修改,,就可以将版本库中的文件删除。
8.创建分支
- Git 查看分支: git branch
其中 * 表示当前 HEAD 指向的分支是 master 分支 - Git 创建分支: git branch sub 创建一个叫sub的分支
其中 sub 和 master 指向同一个提交
- Git 切换分支: git checkout sub 切换到sub分支
9.合并分支
当我们在一个分支中开发代码,将代码提交以后,切换到另一个分支,另一个分支不可以看到我们开发代码的分支的内容,当前分支还是指向自己最新提交的一次提交。
比如:
我在 sub 分支上写了代码,提交以后 sub 就指向最新的一次提交,然后我们切换当 master 分支,就看不到 sub 分支开发的代码。
如图所示:
为了在 master 分支上看到最新的提交,就需要将 sub 分支合并到 master 分支上:git merge sub
当我们合并分支以后,我们可以看到有个 fast forward ,也就是直接将 master 指向当前提交,所以合并速度非常快。
10.删除分支
如果某个分支对我们来说没有用了,这时候我们就可以删除没有用的分支:
git branch -d sub , 删除 sub 分支( 注意 :如果我们正处于当前分支,就不可以删除)
11.合并冲突
我们新创建一个分支,当我们在 sub 分支上 CODE 文件中修改了内容,并提交了代码,然后再切换到 master 分支上,在 master 分支上修改了 CODE 文件的内容,并提交了代码,这时候的状态就变成了这样:
如果这时候我们想要合并 sub 上的代码,就会发生合并冲突
这时候我们就需要手动解决冲突,并提交修正后的结果
CODE 中的内容:(其中 Git 会用 <<<<<<< ,======= ,>>>>>>> 来表示不同分支冲突的内容,其中 HEAD 表示当前的分支,sub 表示另一个分支)
<<<<<<< HEAD
I am master
=======
I am sub
>>>>>>> sub
修改后的内容:
I am sub
I am master
提交修改后的内容就冲突就解决了。可以通过 git log --graph --pretty=oneline --abbrev-commit 来查看合并情况
使用完后可以把 sub 分支删除:
git branch -d sub
11. Fast forward 模式
上面我们在合并分支的时候看到了有个 Fast-forword ,当我们在合并分支时候,如果没有产生冲突,就不可以看到到底在哪合并了分支。
如果我们想要查看分支合并情况,就可以使用一下命令:
git merge --no-ff -m "merge with no-ff" sub
其中 -m 后的语句就表示合并之后在提交的描述,sub 就是分支
12. git stash
当我们在开发代码时,master 分支上突然出现了一个 Bug ,需要我们解决,但是我们还在开发代码,代码还没开发完,怎么办?这时候我们就可以使用如下命令将我们开发的代码存储起来:
git stash
如果我们想要将存储的内容重新拿出来,恢复内容会将 stash 中的内容删除,就可以使用如下命令:
git satsh pop
将内容恢复:
git stash apply
恢复一部分内容(恢复最近一次暂存的修改):
git stash apply stash@{0}
恢复后想要删除 stash 中的内容不可用 git stash pop,需要用:
git stash drop
查看存储的内容:
git stash list
13.远程仓库
如果你想要将代码上传到远端仓库,比如 github ,gitee 之类的代码托管平台,就需要在远端创建一个仓库,这里我用 gitee 来演示。
首先创建一个仓库
克隆远程仓库
点击你创建的仓库,然后点击克隆
点击复制
执行命令:
git clone [你复制的https网址]
- 远程仓库推送
默认主机名一般为 origin
git push <远程主机名> <本地分支名>:<远程分支名>
或者
git push <远程主机名> <本地分支名>
- 拉取远程仓库
git pull <远程主机名> <远程分支名>:<本地分支名>
或者
git pull <远程主机名> <远程分支名>
14. 配置git
如果在某些文件你不想提交到远程仓库就可以在本地仓库中创建一个 .gitignore 文件。
配置 .gitignore 文件
通配符:
- *:匹配任意字符(除 /),如 *.log 忽略所有日志文件。
- ?:匹配单个字符,如 debug?.log 匹配 debug1.log 但排除 debug10.log。
- ** :匹配多级目录,如 logs/**/*.tmp 忽略所有子目录中的 .tmp 文件。
- 目录与路径:
/ 开头:仅匹配根目录,如 /build 忽略根目录下的 build 目录。
/ 结尾:仅匹配目录,如 cache/ 忽略名为 cache 的目录及其内容。
否定规则:
! 开头:排除特定文件,如 !important.log 强制包含 important.log
15. 标签
- 创建标签
git tag [tagname]
2.查看所有标签
git tag
- 查看对应标签信息
git show [tagname]
- 删除标签
git tag -d [tagname]
- 推送指定标签到远程仓库
git push origin [tagname]
- 推送所有标签到远程仓库
git push origin --tags
- 删除远程仓库中的标签
先从本地删除
git tag -d [tagname]
然后删除远程仓库中标签
git push origin :refs/tags/[tagname]