当前位置: 首页 > news >正文

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 的核心部分是一个简单的 键值对数据库。我们可以向该数据库插入任意类型的内容,它会返回一个键值,通过该键值可以在任意时刻再次取回该内容。我们根据在数据库中存储的数据类型进行了如下分类:

数据类型对象类型
blobgit 对象(数据对象)
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 目录进行了初始化,并创建了 packinfo 子目录,但均为空。接着,我们用 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

问题:

  1. 记住文件的每一个版本所对应的 SHA-1 值并不现实。
  2. 在 Git 中,我们仅保存了文件内容,文件名没有被保存。

解决方案:树对象


三、树对象

树对象(tree object),它能解决文件名保存的问题,也允许我们将多个文件组织到一起。Git 以一种类似于 UNIX 文件系统的方式存储内容,但做了些许简化。所有内容均以树对象和数据对象(git对象)的形式存储,其中树对象对应了 UNIX 中的目录项,数据对象(git对象)则大致上对应了 inodes 或文件内容。一个树对象包含了一条或多条树对象记录(tree entry),每条记录含有一个指向数据对象或者子树对象的 SHA-1 指针,以及相应的模式、类型、文件名信息。一个树对象

我们可以通过 update-indexwrite-treeread-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

问题:

  1. 树对象的提交只有哈希和文件名,我们看不到文件版本的相关说明。

解决方案:提交对象


四、提交对象

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 对象&#xff08;数据对象&#xff09;2.1 hash-object 存储对象2.2 cat-file 查看对象 三、树对象3.1 ls-files 查看暂存区3.2 update-index 创建暂存区3.3 write-tree 生成树对象3.4 更新暂存区&#xff0c;…...

LVS-DR模式+keepalived+nginx+tomcat实现动静分离、负载均衡、高可用实验

实验条件&#xff1a; test2——20.0.0.20——主服务器——ipvsadm、keepalived服务 test3——20.0.0.30——备服务器——ipvsadm、keepalived服务 nginx5——20.0.0.51——后端真实服务器1&#xff08;tomcat的代理服务器&#xff09;——nginx服务 nginx6——20.0.0.61—…...

canvas 状态管理

本文简介 带尬猴&#xff0c;我是德育处主任 canvas 绘图时会根据当前状态来绘制。很多的 canvas 库都利用到这一特性。比如 p5.js 利用了 canvas 状态特性衍生出 push 和 pop 函数实现状态隔离&#xff08;既然提到了&#xff0c;下一篇就讲这个&#xff09;。 有兴趣了解 p…...

vue中如何给后端过来的数组中每一个对象加一个新的属性和新的对象(不影响后端的原始数据)

方法&#xff1a; 先看后端的原数据 1、给数组中每一个对象加一个新的属性&#xff1a; 输出查看数组list的值&#xff1a; 2、给数组list加入新的对象&#xff1a; 输出结果&#xff1a; 3、总结&#xff1a; 如果是数组中每个对象新增属性就用map遍历每个对象加入新增的属性…...

SpringAOP源码解析之TargetSource(四)

前言 在Spring框架中&#xff0c;TargetSource是一个接口&#xff0c;用于封装获取目标对象&#xff08;也就是被代理的对象&#xff09;的逻辑。它的主要作用是提供代理对象使用的目标对象&#xff0c;并且允许在运行时动态地切换目标对象。TargetSource在Spring的AOP&#x…...

Centos7 安装nvidia显卡驱动

参考一&#xff1a;https://blog.csdn.net/awen19921106/article/details/131331450 参考二&#xff1a;https://www.cnblogs.com/lishanyang/p/17326021.html 报错一&#xff1a; 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库中对话框相关的内容&#xff0c;本章回中主要介绍 导航。闲话休提&#xff0c;让我们一起Talk Android Jetpack吧&#xff01; 1. 概念介绍 我…...

Linux常见问题解决操作(yum被占用、lsb无此命令、Linux开机进入命令界面等)

Linux常见问题解决操作&#xff08;yum被占用、lsb无此命令、Linux开机进入命令界面等&#xff09; 问题一、新安装的Linux使用命令lsb_release提示无此命令&#xff0c;需先安装再使用 Linux安装lsb命令 lsb是Linux Standard Base的缩写&#xff08;Linux基本标准&#xff…...

层次式架构的设计理论与实践

层次式架构的设计理论与实践 层次式架构概述 层次式架构的定义和特性 定义 特性 层次式架构的一般组成(表现层、中间层、数据访问层和数据层) 表现层框架设计 设计模式 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. 先将串口打通&#xff0c;方便电脑查看log日志。 2. 增加cjson.c文件&#xff0c;已经在main.c中 3. 准备打包如下的JSON包 4. 代码部分&#xff0c;先将几个部分初始化指针 …...

【智能家居】

面向Apple developer学习&#xff1a;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&#xff08;在Gradle中添加&#xff09; android{ buildFeatures { aidl true } } 我们看见&#xff0c;可以创建AIDL文件了 3.接着&#xff0c;我们看到文件出现如下提示 4.在gradle…...

如何进行渗透测试以提高软件安全性?

对于各种规模的企业和组织来说&#xff0c;软件安全是一个至关重要的问题。随着网络攻击越来越复杂&#xff0c;软件中的漏洞越来越多&#xff0c;确保你的软件安全比以往任何时候都更重要。提高软件安全性的一个有效方法是渗透测试&#xff08;penetration testing&#xff09…...

YOLOv5 添加 OTA,并使用 coco、CrowdHuman数据集进行训练。

YOLO-OTA 第一步&#xff1a;拉取 YOLOv5 的代码第二步&#xff1a;添加 ComputeLossOTA 函数第二步&#xff1a;修改 train 和 val 中损失函数为 ComputeLossOTA 函数1、在 train.py 中 首先添加 ComputeLossOTA 库。2、在 train.py 修改初始化的损失函数3、在 train.py 修改一…...

SpringBoot 日志

目录 1.如何使用日志 2.自定义打印日志 3.日志级别 3.1 日志从低到高级别 3.2 日志级别设置 为什么 Spring Boot 可以打印日志&#xff1f;并设置日志级别&#xff1f; 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 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于大数据…...

MYSQL(事务)

一、什么是事务&#xff0c;四大特性 事务&#xff1a;一组操作的集合&#xff0c;它是一个不可分割的单位&#xff0c;事务会将这些操作作为一个整体一起像系统提交&#xff0c;这些操作要么同时成功&#xff0c;要么同时失败 四大特性&#xff08;ACID&#xff09; 原子性&am…...

npm start启动的是什么

npm start 命令是在一个 Node.js 项目中执行的一个自定义命令&#xff0c;用于启动该项目。该命令是在 package.json 文件中定义的&#xff0c;通常被用于启动一个 Web 应用程序或服务。 具体来说&#xff0c;当在项目目录下执行 npm start 命令时&#xff0c;npm 将会在该项目…...

基于PyTorch的MNIST手写体分类实战

第2章对MNIST数据做了介绍&#xff0c;描述了其构成方式及其数据的特征和标签的含义等。了解这些有助于编写合适的程序来对MNIST数据集进行分析和识别。本节将使用同样的数据集完成对其进行分类的任务。 3.1.1 数据图像的获取与标签的说明 MNIST数据集的详细介绍在第2章中已…...

conda 复制系统环境

直接复制 想要通过 conda 直接复制一个已存在的环境&#xff0c;你可以使用 conda create 命令并配合 --clone 参数。以下是具体步骤&#xff1a; 查看现有的环境: 首先&#xff0c;你可以使用以下命令来查看所有的 conda 环境&#xff1a; conda env list这会给你一个环境列表…...

如何在Microsoft Visual Studio 中使用Cpp代码调用python代码

Microsoft Visual Studio中Cpp调用Python代码 本文介绍如何在Microsoft Visual Studio中&#xff0c;开发cpp项目时&#xff0c;调用python代码。 文章目录 Microsoft Visual Studio中Cpp调用Python代码前言一、Cpp生成exe文件1.1 安装python环境1.2 配置Microsoft Visual Stu…...

DAY35 435. 无重叠区间 + 763.划分字母区间 + 56. 合并区间

435. 无重叠区间 题目要求&#xff1a;给定一个区间的集合&#xff0c;找到需要移除区间的最小数量&#xff0c;使剩余区间互不重叠。 注意: 可以认为区间的终点总是大于它的起点。 区间 [1,2] 和 [2,3] 的边界相互“接触”&#xff0c;但没有相互重叠。 示例 1: 输入: [ […...

代码随想录算法训练营第2天| 977有序数组的平方、209长度最小的子数组。

JAVA代码编写 977. 有序数组的平方 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每个数字的平方 组成的新数组&#xff0c;要求也按 非递减顺序 排序。 示例 1&#xff1a; 输入&#xff1a;nums [-4,-1,0,3,10] 输出&#xff1a;[0,1,9,16,100] 解释&…...

微信小程序通过startLocationUpdate,onLocationChange获取当前地理位置信息,配合腾讯地图解析获取到地址

先创建个getLocation.js文件 //获取用户当前所在的位置 const getLocation () > {return new Promise((resolve, reject) > {let _locationChangeFn (res) > {resolve(res) // 回传地里位置信息wx.offLocationChange(_locationChangeFn) // 关闭实时定位wx.stopLoc…...

C/C++字符三角形 2020年12月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析

目录 C/C字符三角形 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 C/C字符三角形 2020年12月 C/C编程等级考试一级编程题 一、题目要求 1、编程实现 给定一个字符&#xff0c;用它构造一个底边长5个字…...

Python数据挖掘:入门、进阶与实用案例分析——基于非侵入式负荷检测与分解的电力数据挖掘

文章目录 摘要01 案例背景02 分析目标03 分析过程04 数据准备05 属性构造06 模型训练07 性能度量08 推荐阅读赠书活动 摘要 本案例将根据已收集到的电力数据&#xff0c;深度挖掘各电力设备的电流、电压和功率等情况&#xff0c;分析各电力设备的实际用电量&#xff0c;进而为电…...

基于 Qt控制开发板 LED和C语言控制LED渐变亮度效果

## 资源简介 在STM32开发板,板载资源上有两个可自由控制的 LED。如下图原理 图其中我们以操作 LED1 为示例,LED1 为出厂系统的心跳指示灯。 ## 应用实例 想要控制这个 LED,首先出厂内核已经默认将这个 LED 注册成了 gpio-leds类型设备。所以我们可以直接在应用层接口直接…...