Git(四)底层命令:git对象、树对象、提交对象
目录
- 一、知识回顾
- 1.1 Linux 基础命令
- 1.2 .git 文件夹解析
- 二、git 对象(数据对象)
- 2.1 hash-object 存储对象
- 2.2 cat-file 查看对象
- 三、树对象
- 3.1 ls-files 查看暂存区
- 3.2 update-index 创建暂存区
- 3.3 write-tree 生成树对象
- 3.4 更新暂存区,生成第二棵树
- 3.5 read-tree 树A加入树B,生成第三棵树
- 3.6 查看树对象
- 四、提交对象
- 4.1 commit-tree 创建提交对象
- 4.2 查看提交对象
- 4.3 创建第二次提交对象
- 五、总结

- 官网地址: https://www.git-scm.com/
- 官方文档: https://www.git-scm.com/docs
- 官方电子书: https://git-scm.com/book/zh/v2
- GitHub: https://github.com/git/git
一、知识回顾
1.1 Linux 基础命令
在开始学习 Git 的底层命令之前,我们先来回顾一下 Linux 的基础命令:
-
clear:清除屏幕。 -
echo 'test content':将信息输出到控制台。 -
echo 'test content' > test.txt:将信息输出到 test.txt 文件中。 -
ll:查看当前目录下的文件详细信息。 -
find 目录名:查看对应目录下的子孙目录和文件。 -
find 目录名 -type f:查看对应目录下的子孙文件。 -
rm 文件名:删除文件 -
mv 文件名A 文件名B:移动、重命名文件A为文件B。 -
cat 文件名:查看文件内容。 -
vim 文件名:查看、编辑文件。按 i 进入插入模式,进行文件的编辑;
按 Esc 退出插入模式;
输入
:q!强制退出(不保存);输入
:wq写入退出;输入
:set nu查看行号。
1.2 .git 文件夹解析
.git 文件夹内容如下:

二、git 对象(数据对象)
Git 的核心部分是一个简单的 键值对数据库。我们可以向该数据库插入任意类型的内容,它会返回一个键值,通过该键值可以在任意时刻再次取回该内容。我们根据在数据库中存储的数据类型进行了如下分类:
| 数据类型 | 对象类型 |
|---|---|
blob | git 对象(数据对象) |
tree | 树对象 |
commit | 提交对象 |
2.1 hash-object 存储对象
git hash-object 命令可将任意数据保存于 .git/objects 目录(即 对象数据库),并返回指向该数据对象的唯一键值。
-w选项会指示该命令不要只返回键,还要将该对象写入数据库中。--stdin选项则指示该命令从标准输入读取内容;若不指定此选项,则在命令尾部给出带存储文件的路径。
示例一:echo 'test content' | git hash-object -w --stdin
示例二:git hash-object -w test.txt
向数据库写入内容,并返回对应键值:
首先,我们需要初始化一个新的 Git 版本库,并确认 .git/objects 目录不包含文件:
# 初始化新仓库
$ git init test
Initialized empty Git repository in /tmp/test/.git/
# 进入目录
$ cd test
# 查看目录和文件
$ find .git/objects
.git/objects
.git/objects/info
.git/objects/pack
# 确认 objects 目录中不包含文件
$ find .git/objects -type f
可以看到 Git 对 objects 目录进行了初始化,并创建了 pack 和 info 子目录,但均为空。接着,我们用 git hash-object 创建一个新的数据对象并将它手动存入新 Git 数据库中:
$ echo 'test content' | git hash-object -w --stdin
d670460b4b4aece5915caf5c68d12f560a9fe3e4
在这种最简单的形式中,git hash-object 会接受你传给它的东西,而它只会返回可以存储在 Git 仓库中的唯一键。
git hash-object 命令输出一个长度为 40 个字符的校验和。这是一个 SHA-1 哈希值——一个将带存储的数据外加一个头部信息(header)一起做 SHA-1 校验运算而得的校验和。现在我们查看 Git 是如何存储数据的:
$ find .git/objects -type f
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
如果再次查看 objects 目录,那么可以在其中找到一个与新内容对应的文件。这就是开始时 Git 存储内容的方式——一个文件对应一条内容,以改内容加上特定头部信息一起的 SHA-1 校验和为文件命名。校验和的前两个字符用于命名子目录,余下的 38 个字符用作文件名。
2.2 cat-file 查看对象
cat-file 命令可以从 Git 那里取回存储在对象数据库中的内容。
-p选项可指示该命令自动判断内容的类型,并为我们显示大致的内容。-t选项可显示内部存储的对象类型。
$ git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4
test content
至此,我们已经掌握了如何向 Git 中存入内容,以及如何将它们取出。我们同样可以将这些操作应用与文件中的内容。例如,可以对一个文件进行简单的版本控制。首先,创建一个新文件并将其内容存入数据库:
$ echo 'version 1' > test.txt
$ git hash-object -w test.txt
83baae61804e65cc73a7201a7252750c76066a30
接着,向文件里写入新内容,并再次将其存入数据库:
$ echo 'version 2' > test.txt
$ git hash-object -w test.txt
1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
对象数据库记录下了该文件的两个不同版本,当然之前我们存入的第一条内容也还在:
$ find .git/objects -type f
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
现在可以再删掉 test.txt 的本地副本,然后用 Git 从对象数据库中取回它的第一个版本:
$ git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test.txt
$ cat test.txt
version 1
或者取回第二个版本:
$ git cat-file -p 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a > test.txt
$ cat test.txt
version 2
然而,记住文件的每一个版本所对应的 SHA-1 值并不现实;另一个问题是:再这个简单的版本控制系统中,文件名并没有被保存——我们仅保存了文件的内容。上述类型的对象我们称之为 数据对象(blob object)。利用 git cat-file -t 命令,我们就可以根据对象的 SHA-1 值获取 Git 内部存储的对象类型。
$ git cat-file -t 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
blob
问题:
- 记住文件的每一个版本所对应的 SHA-1 值并不现实。
- 在 Git 中,我们仅保存了文件内容,文件名没有被保存。
解决方案:树对象
三、树对象
树对象(tree object),它能解决文件名保存的问题,也允许我们将多个文件组织到一起。Git 以一种类似于 UNIX 文件系统的方式存储内容,但做了些许简化。所有内容均以树对象和数据对象(git对象)的形式存储,其中树对象对应了 UNIX 中的目录项,数据对象(git对象)则大致上对应了 inodes 或文件内容。一个树对象包含了一条或多条树对象记录(tree entry),每条记录含有一个指向数据对象或者子树对象的 SHA-1 指针,以及相应的模式、类型、文件名信息。一个树对象
我们可以通过 update-index、write-tree、read-tree 等命令来构建树对象并塞入到暂存区。
在讲构建树对象之前,我们需要先了解一个命令 git ls-files。
3.1 ls-files 查看暂存区
git ls-files -s:查看暂存区当前的样子。
-s选项来显示文件的状态。
3.2 update-index 创建暂存区
首先,清空目录,初始化一个新的仓库,并将 test.txt 的首个版本放入数据库。
# 初始化新的仓库
$ git init
Initialized empty Git repository in C:/Users/lenovo/Desktop/test/.git/
# 创建首个版本
$ echo 'test.txt v1' > test.txt
# 放入数据库
$ git hash-object -w test.txt
warning: in the working copy of 'test.txt', LF will be replaced by CRLF the next time Git touches it
560a3d89bf36ea10794402f6664740c284d4ae3b
# 查看暂存区
$ git ls-files -s
我们可以看到,此时暂存区为空。然后我们使用 update-index 命令为 test.txt 的首个版本创建一个暂存区:
# 创建暂存区
$ git update-index --add --cacheinfo 100644 560a3d89bf36ea10794402f6664740c284d4ae3b test.txt
-
--add选项:因为此前该文件并不在暂存区中,首次需要 --add。 -
--cacheinfo选项:因为将要添加的文件位于 Git 数据库中,而不是位于当前目录下,所以需要 --cache。 -
文件模式:
100644,表明这是一个普通文件;100755,表示一个可执行文件;120000,表示一个符号链接。
再次查看暂存区:
$ git ls-files -s
100644 560a3d89bf36ea10794402f6664740c284d4ae3b 0 test.txt
这样我们的 SHA-1 键值和文件名就对应上了。然后,我们再去数据库看一下有没有新增内容:
$ find .git/objects/ -type f
.git/objects/56/0a3d89bf36ea10794402f6664740c284d4ae3b
发现没有新增内容,还是只有首个版本的 test.txt,这就说明 update-index 只在暂存区内生成数据,并不会操作数据库。
3.3 write-tree 生成树对象
git write-tree 命令是将暂存区做一个快照。相当于给暂存区拍张照,生成一个树对象,放到数据库里面去。
继续实战,将 3.2 中暂存区中的内容生成一个树对象:
$ git write-tree
06e21bb0105e2de6c846725a9a7172f57dd1af96
接下来,我们看一下返回的哈希所对应的数据类型:
$ git cat-file -t 06e21bb0105e2de6c846725a9a7172f57dd1af96
tree
我们可以看到,write-tree 命令生成的数据类型为 树对象。然后我们看一下这个树对象在不在我们的版本库(数据库)里面:
$ find .git/objects/ -type f
.git/objects/06/e21bb0105e2de6c846725a9a7172f57dd1af96
.git/objects/56/0a3d89bf36ea10794402f6664740c284d4ae3b
可以看到数据库中的对象增加了一个刚放进去的数据对象。
由此可知,我们可以通过多次执行 update-index 命令,在缓存区中存放多个内容,然后通过 write-tree 命令一次性将所有暂存区的内容生成快照,保存为树对象。
总结:
git 对象,代表文件的初始版本;树对象,代表项目的初始版本。
补充:上面执行了 write-tree 生成树对象后,我们可以再去看一下暂存区中还有没有内容:
$ git ls-files -s
100644 560a3d89bf36ea10794402f6664740c284d4ae3b 0 test.txt
由执行结果可知,write-tree 命令将暂存区生成快照保存为树对象后,并不会将暂存区清空。
3.4 更新暂存区,生成第二棵树
接下来,我们继续操作:
1)新增 new.txt 到数据库:
# 新增一个 new.txt 文件
$ echo "new v1" > new.txt
# 生成 git 对象
$ git hash-object -w new.txt
warning: in the working copy of 'new.txt', LF will be replaced by CRLF the next time Git touches it
eae614245cc5faa121ed130b4eba7f9afbcc7cd9
# 查看数据库
$ find .git/objects/ -type f
.git/objects/06/e21bb0105e2de6c846725a9a7172f57dd1af96
.git/objects/56/0a3d89bf36ea10794402f6664740c284d4ae3b
.git/objects/ea/e614245cc5faa121ed130b4eba7f9afbcc7cd9
2)创建 test.txt 的第二个版本:
# 编辑 test.txt
$ vi test.txt
# 查看 test.txt
$ cat test.txt
test.txt v1
test.txt v2
# 生成 git 对象
$ git hash-object -w test.txt
warning: in the working copy of 'test.txt', LF will be replaced by CRLF the next time Git touches it
c31fb1e89d8b6b3ef34cdb5a2f999d6e29b822ba
3)查看数据库:
$ find .git/objects/ -type f
.git/objects/06/e21bb0105e2de6c846725a9a7172f57dd1af96 # workspace项目的第一个版本(树对象)
.git/objects/56/0a3d89bf36ea10794402f6664740c284d4ae3b # test.txt文件的第一个版本(git对象)
.git/objects/c3/1fb1e89d8b6b3ef34cdb5a2f999d6e29b822ba # test.txt文件的第二个版本(git对象)
.git/objects/ea/e614245cc5faa121ed130b4eba7f9afbcc7cd9 # new.txt文件的第一个版本(git对象)
4)生成项目的第二个版本
数据库中的前两个对象属于项目的第一个版本,我们可以将后面两个对象生成项目的第二个版本:
# 更新暂存区 test.txt
$ git update-index --cacheinfo 100644 c31fb1e89d8b6b3ef34cdb5a2f999d6e29b822ba test.txt
# 查看暂存区
$ git ls-files -s
100644 c31fb1e89d8b6b3ef34cdb5a2f999d6e29b822ba 0 test.txt
可以发现由于暂存区中 test.txt 的更新,对应的哈希值也随之更新了。然后我们继续将 new.txt 放入暂存区,并生成项目第二个版本的树对象:
# 创建缓存区 new.txt
$ git update-index --add --cacheinfo 100644 eae614245cc5faa121ed130b4eba7f9afbcc7cd9 new.txt
# 查看缓存区
$ git ls-files -s
100644 eae614245cc5faa121ed130b4eba7f9afbcc7cd9 0 new.txt
100644 c31fb1e89d8b6b3ef34cdb5a2f999d6e29b822ba 0 test.txt
# 生成树对象
$ git write-tree
9d74ec4055e0f1edc1921d749c250380ca7b5ebd
# 查看数据库
补充: git update-index 命令后面加 --add 选项,可以直接将文件放到数据库中,然后再为文件创建、更新缓存区。例如:上面 new.txt 文件的 git hash-object 命令和 git update-index 命令可以合并为:
$ git update-index --add new.txt
5)查看数据库
$ find .git/objects/ -type f
.git/objects/06/e21bb0105e2de6c846725a9a7172f57dd1af96 # workspace项目的第一个版本(树对象)
.git/objects/56/0a3d89bf36ea10794402f6664740c284d4ae3b # test.txt文件的第一个版本(git对象)
.git/objects/9d/74ec4055e0f1edc1921d749c250380ca7b5ebd # workpace项目的第二个版本(树对象)
.git/objects/c3/1fb1e89d8b6b3ef34cdb5a2f999d6e29b822ba # test.txt文件的第二个版本(git对象)
.git/objects/ea/e614245cc5faa121ed130b4eba7f9afbcc7cd9 # new.txt文件的第一个版本(git对象)
此时,数据库中共 5 个对象,项目的两个版本的对象关系如下:

3.5 read-tree 树A加入树B,生成第三棵树
git read-tree 命令是将一棵树读取到暂存区。然后配合 write-tree 命令再将暂存区重新做一个快照,生成一个树对象,放到数据库里面去。
--prefix=bak选项指定了树的前缀为“bak”。
继续实战,将 3.3 中的树对象加入到 3.4 中的树对象:
# 从第一棵树读取到暂存区
$ git read-tree --prefix=bak 06e21bb0105e2de6c846725a9a7172f57dd1af96
# 查看暂存区
$ git ls-files -s
100644 560a3d89bf36ea10794402f6664740c284d4ae3b 0 bak/test.txt
100644 eae614245cc5faa121ed130b4eba7f9afbcc7cd9 0 new.txt
100644 c31fb1e89d8b6b3ef34cdb5a2f999d6e29b822ba 0 test.txt
我们可以看到,读取后,暂存区中增加了一个 bak 前缀的 test.txt 文件。我们继续将暂存区生成第三棵树:
# 生成新的树对象
$ git write-tree
17d1ee3eac87d38448e7ff2cc92e88ed4e9aa094
# 查看数据库
$ find .git/objects/ -type f
.git/objects/06/e21bb0105e2de6c846725a9a7172f57dd1af96 # workspace项目的第一个版本(树对象)
.git/objects/17/d1ee3eac87d38448e7ff2cc92e88ed4e9aa094 # workspace项目的第三个版本(树对象)
.git/objects/56/0a3d89bf36ea10794402f6664740c284d4ae3b # test.txt文件的第一个版本(git对象)
.git/objects/9d/74ec4055e0f1edc1921d749c250380ca7b5ebd # workpace项目的第二个版本(树对象)
.git/objects/c3/1fb1e89d8b6b3ef34cdb5a2f999d6e29b822ba # test.txt文件的第二个版本(git对象)
.git/objects/ea/e614245cc5faa121ed130b4eba7f9afbcc7cd9 # new.txt文件的第一个版本(git对象)
目前上面的数据结构,我们可以整理为下图:(图中同时包含了三棵树)

补充: read-tree 命令仅作了解,实际过程中,我们并不会将一棵树加入另一棵树中。
3.6 查看树对象
由于树对象和 git 对象一样,都是存储在数据库中,我们使用 git cat-file 命令查看即可:
$ git cat-file -p 17d1ee3eac87d38448e7ff2cc92e88ed4e9aa094
040000 tree 06e21bb0105e2de6c846725a9a7172f57dd1af96 bak
100644 blob eae614245cc5faa121ed130b4eba7f9afbcc7cd9 new.txt
100644 blob c31fb1e89d8b6b3ef34cdb5a2f999d6e29b822ba test.txt
问题:
- 树对象的提交只有哈希和文件名,我们看不到文件版本的相关说明。
解决方案:提交对象
四、提交对象
4.1 commit-tree 创建提交对象
我们可以通过调用 commit-tree 命令创建一个提交对象,为此需要指定一个树对象的 SHA-1 值,以及该提交的父提交对象(如果有的话,需要指定。第一次将暂存区做快照就没有父对象)。
-p选项可以用于指定父提交对象的 SHA-1 值。
注意:
git commit-tree不但生成提交对象,而且会将对象的快照(树对象)提交到本地库中。
我们先来创建第一棵树的提交对象:
# 创建提交对象
$ echo 'first commit' | git commit-tree 06e21bb0105e2de6c846725a9a7172f57dd1af96
92f28813cce27fa514cf3be80a4d4b158afdca27
4.2 查看提交对象
由于提交对象和 git 对象、树对象一样,都是存储在数据库中,我们使用 git cat-file 命令查看即可:
# 查看数据类型
$ git cat-file -t 92f28813cce27fa514cf3be80a4d4b158afdca27
commit
# 查看数据内容
$ git cat-file -p 92f28813cce27fa514cf3be80a4d4b158afdca27
tree 06e21bb0105e2de6c846725a9a7172f57dd1af96 # 树对象
author acgkaka <acgkaka@example.com> 1698337169 +0800 # 作者
committer acgkaka <acgkaka@example.com> 1698337169 +0800 # 提交者first commit # 提交注释
4.3 创建第二次提交对象
接下来,我们可以创建第二次提交对象,然后将第一次提交对象作为父对象:
补充: 这里可以只用树对象和父提交对象 SHA-1 值的前部分(一般6位)即可。
# 创建提交对象
$ echo 'second commit' | git commit-tree 9d74ec -p 92f288
1be40a21a3cc7c92e73721967abe30c9ce2a5a51
# 查看提交对象
$ git cat-file -p 1be40a
tree 9d74ec4055e0f1edc1921d749c250380ca7b5ebd # 树对象
parent 92f28813cce27fa514cf3be80a4d4b158afdca27 # 父提交对象
author acgkaka <acgkaka@example.com> 1698338744 +0800 #
committer acgkaka <acgkaka@example.com> 1698338744 +0800second commit
第三次提交对象以此类推。三次提交对象创建完毕后,图示如下:

五、总结
git对象里面存储的不是增量,而是一次快照。树对象才是真正的一个项目版本的快照;提交对象只是对树对象做了一次封装。
补充: 提交对象也说明了 为什么 Git 回滚如此简单,因为每个分支名实际相当于一个指向提交对象的指针,当进行版本回退时,只需要将指针调整到需要的提交对象即可,其他地方均无需改动。
整理完毕,完结撒花~ 🌻
参考地址:
1.深入Git底层原理丨一套掌握git版本控制系统,https://www.bilibili.com/video/BV1Yi4y137eF
相关文章:
Git(四)底层命令:git对象、树对象、提交对象
目录 一、知识回顾1.1 Linux 基础命令1.2 .git 文件夹解析 二、git 对象(数据对象)2.1 hash-object 存储对象2.2 cat-file 查看对象 三、树对象3.1 ls-files 查看暂存区3.2 update-index 创建暂存区3.3 write-tree 生成树对象3.4 更新暂存区,…...
LVS-DR模式+keepalived+nginx+tomcat实现动静分离、负载均衡、高可用实验
实验条件: test2——20.0.0.20——主服务器——ipvsadm、keepalived服务 test3——20.0.0.30——备服务器——ipvsadm、keepalived服务 nginx5——20.0.0.51——后端真实服务器1(tomcat的代理服务器)——nginx服务 nginx6——20.0.0.61—…...
canvas 状态管理
本文简介 带尬猴,我是德育处主任 canvas 绘图时会根据当前状态来绘制。很多的 canvas 库都利用到这一特性。比如 p5.js 利用了 canvas 状态特性衍生出 push 和 pop 函数实现状态隔离(既然提到了,下一篇就讲这个)。 有兴趣了解 p…...
vue中如何给后端过来的数组中每一个对象加一个新的属性和新的对象(不影响后端的原始数据)
方法: 先看后端的原数据 1、给数组中每一个对象加一个新的属性: 输出查看数组list的值: 2、给数组list加入新的对象: 输出结果: 3、总结: 如果是数组中每个对象新增属性就用map遍历每个对象加入新增的属性…...
SpringAOP源码解析之TargetSource(四)
前言 在Spring框架中,TargetSource是一个接口,用于封装获取目标对象(也就是被代理的对象)的逻辑。它的主要作用是提供代理对象使用的目标对象,并且允许在运行时动态地切换目标对象。TargetSource在Spring的AOP&#x…...
Centos7 安装nvidia显卡驱动
参考一:https://blog.csdn.net/awen19921106/article/details/131331450 参考二:https://www.cnblogs.com/lishanyang/p/17326021.html 报错一: ERROR: Unable to find the kernel source tree for the currently running kernel. Please …...
22 行为型模式-状态模式
1 状态模式介绍 2 状态模式结构 3 状态模式实现 代码示例 //抽象状态接口 public interface State {//声明抽象方法,不同具体状态类可以有不同实现void handle(Context context); }...
Jetpack:018-Jetpack中的导航一
文章目录 1. 概念介绍2. 使用方法2.1 基本概念2.2 传统用法2.3 新的用法 3. 示例代码4. 内容总结 我们在上一章回中介绍了Jetpack库中对话框相关的内容,本章回中主要介绍 导航。闲话休提,让我们一起Talk Android Jetpack吧! 1. 概念介绍 我…...
Linux常见问题解决操作(yum被占用、lsb无此命令、Linux开机进入命令界面等)
Linux常见问题解决操作(yum被占用、lsb无此命令、Linux开机进入命令界面等) 问题一、新安装的Linux使用命令lsb_release提示无此命令,需先安装再使用 Linux安装lsb命令 lsb是Linux Standard Base的缩写(Linux基本标准ÿ…...
层次式架构的设计理论与实践
层次式架构的设计理论与实践 层次式架构概述 层次式架构的定义和特性 定义 特性 层次式架构的一般组成(表现层、中间层、数据访问层和数据层) 表现层框架设计 设计模式 MVC MVP MVVM XML技术 UIP设计思想 表现层动态生成设计思想(基于XML界面管理技术) 中间层架构设计 业务…...
【shell】read -t -n1
if read -t 5 -p "Please enter your name:" name thenecho "Hello, $name, welcome to my script" else#起到换行的作用echo#输入计数 -n1read -n1 -p "Do you want to continue [Y/N]?" answercase $answer inY | y) echoecho "Fine, co…...
【嵌入式项目应用】__cJSON在单片机的使用
目录 前言 一、JSON和cJson 二、cJSON是如何表示JSON数据的 三、如何封装完整的JSON数据 1. 先将串口打通,方便电脑查看log日志。 2. 增加cjson.c文件,已经在main.c中 3. 准备打包如下的JSON包 4. 代码部分,先将几个部分初始化指针 …...
【智能家居】
面向Apple developer学习:AirPlay | Apple Developer Documentation Airplay AirPlay允许人们将媒体内容从iOS、ipad、macOS和tvOS设备无线传输到支持AirPlay的Apple TV、HomePod以及电视和扬声器上。 网页链接的最佳实践 首选系统提供的媒体播放器。内置的媒体播…...
Android stdio 无法新建或打开AIDL文件(解决方法)
1.在gradle文件中添加如下代码 2.AIDL要求minsdk>16,并且要使aidl true(在Gradle中添加) android{ buildFeatures { aidl true } } 我们看见,可以创建AIDL文件了 3.接着,我们看到文件出现如下提示 4.在gradle…...
如何进行渗透测试以提高软件安全性?
对于各种规模的企业和组织来说,软件安全是一个至关重要的问题。随着网络攻击越来越复杂,软件中的漏洞越来越多,确保你的软件安全比以往任何时候都更重要。提高软件安全性的一个有效方法是渗透测试(penetration testing)…...
YOLOv5 添加 OTA,并使用 coco、CrowdHuman数据集进行训练。
YOLO-OTA 第一步:拉取 YOLOv5 的代码第二步:添加 ComputeLossOTA 函数第二步:修改 train 和 val 中损失函数为 ComputeLossOTA 函数1、在 train.py 中 首先添加 ComputeLossOTA 库。2、在 train.py 修改初始化的损失函数3、在 train.py 修改一…...
SpringBoot 日志
目录 1.如何使用日志 2.自定义打印日志 3.日志级别 3.1 日志从低到高级别 3.2 日志级别设置 为什么 Spring Boot 可以打印日志?并设置日志级别? 4.日志的持久化 5.lombok——更加简单的输出日志 5.1 使用slf4j 注解输出日志 5.2 lombok 执行原…...
非小米笔记本小米妙享中心安装最新教程 3.2.0.464 兼容所有Windows系统
小米妙享中心 3.2.0.464 版本帮助 : 支持音频流转、屏幕镜像、屏幕拓展、键鼠拓展、无线耳机、小米互传 目录 小米妙享中心 3.2.0.464 版本帮助 : 1.常规教程使用安装包方式安装失败 或者 1.1安装失败可使用大佬的加载补丁方法解决 补充卸载残留 1.2 截图存档 2. 本教程…...
基于大数据的社交平台数据爬虫舆情分析可视化系统 计算机竞赛
文章目录 0 前言1 课题背景2 实现效果**实现功能****可视化统计****web模块界面展示**3 LDA模型 4 情感分析方法**预处理**特征提取特征选择分类器选择实验 5 部分核心代码6 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于大数据…...
MYSQL(事务)
一、什么是事务,四大特性 事务:一组操作的集合,它是一个不可分割的单位,事务会将这些操作作为一个整体一起像系统提交,这些操作要么同时成功,要么同时失败 四大特性(ACID) 原子性&am…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
