分布式版本控制系统Git介绍

news2024/11/25 12:32:58

Git 是一款开源的分布式版本控制系统,具备分布式、轻量级分支、强大的协作能力以及适用于大小项目的版本管理。本文简要介绍Git工具的特性、Git中的对象以及分支管理,以加深了解。


1、版本控制系统介绍

版本控制是指对软件开发过程中各种程序代码、配置文件及说明文档等文件变更的管理,是软件配置管理的核心思想之一。它的主要目的是跟踪和记录软件开发过程中的每个版本,记录每个版本的修改历史、版本号和发布日期等信息,以便更好地管理代码和文档,并帮助开发人员更好地协作和开发软件。

通过版本控制,开发人员可以随时回滚到之前的稳定版本,恢复错误或进行分支开发等操作,以便更好地管理软件开发过程中的变化和风险。

1.1 分布式版本控制系统

版本控制通常与版本控制系统(Version Control System,VCS)相关联,如Git、Mercurial、SVN等。这些系统提供了存储代码、管理版本历史、分支和合并等功能,帮助开发人员更好地协作和管理软件开发过程中的版本变化。

1.1.1 版本控制系统的发展

最早的版本控制系统是本地化管理的,采用某种简单的数据库记录文件的历次更新差异。但随着合作开发和协调工作的需要,集中式的版本控制系统(CVCS)出现了,不同的开发人员通过客户端连接到集中管理的服务器上,提交或读取最新的文件,比如常用的SVN就是这种工作模式。

在这里插入图片描述

在集中式的版本控制系统中,管理员可以轻松管控每个开发者的权限,并且维护成本低。但是这种架构下集中式服务器存在明显的单点故障,如果版本控制服务器宕机,则无法提供服务。如果服务器数据丢失并且无法恢复,那么整个项目的数据和变更历史也随之丢失。

为解决以上问题出现了分布式版本控制系统(DVCS),其基本设计理念是客户端不仅仅提取最新版本的快照,而是把代码仓库完整的镜像下来,相当于在本地有一份完整的数据拷贝。这样,当CVS服务器故障时,通过任何一个本地的镜像仓库就可以恢复数据。同时还可以和不同的远端代码仓库进行交互,设置不同的协作流程。

1.1.2 常见的版本控制系统

常用的分布式版本控制工具包括以下几种:

  1. Git:开源的分布式版本控制系统,广泛用于软件开发和项目版本管理。Git在处理大型项目和团队协作方面表现出色,是许多企业和开发团队的首选工具。
  2. Mercurial:另一种流行的分布式版本控制系统,与Git类似。它同样支持协作开发、分支管理、版本回滚等功能,并具有良好的跨平台支持性。
  3. SVN:Subversion(SVN)是一种集中式版本控制系统,它在一些团队和项目中仍然被广泛使用。SVN提供了易于使用的界面和强大的版本管理功能,尤其适用于小型团队和单个个体的项目管理。
  4. Perforce:一种高性能的分布式版本控制系统,适用于大型团队和大型项目的版本管理。Perforce提供了丰富的功能,包括版本控制、工作空间管理、分支和合并等,还支持多语言和跨平台支持。
  5. Bazaar:开源的分布式版本控制系统,提供类似于Git和Mercurial的功能。Bazaar强调易用性和可扩展性,支持多种平台和开发环境,包括Python、C++、Java等。

下面主要介绍Git版本控制工具的功能及使用。

1.2 Git版本控制系统特性介绍
1.2.1 直接记录快照

Git和其它VCS系统不同之处在于对待数据的方式上,其它系统如Mercurial、SVN等以文件变更列表的方式存储信息,存储的信息是一组基础文件以及随着时间累积的对文件的更新操作,通常称为基于差异的版本控制。如下图所示:

在这里插入图片描述

Git则是将文件系统的快照保存起来,每个版本保存的是当前文件系统的全量复制数据。每当提交更新或保存项目状态时,它基本上就会对当时的全部文件创建一个快照并保存这个快照的索引。为了效率,如果文件没有修改,Git不再重新存储该文件,而是只保留一个链接指向之前存储的文件。

在这里插入图片描述

1.2.2 本地执行操作

在Git中大部分操作只需要访问本地的文件和资源,因为本地磁盘上有项目的完整历史,大部分操作不需要和远端的服务端进行交互,瞬间完成文件查询和提交。比如浏览项目的历史,可以直接读取本地的数据库进行查询;或者想对比当前版本和历史版本的差异,可以直接在本地读取历史文件进行对比。这样在一些离线环境下也可以正常工作,非常的便捷。

1.2.3 完整性保证

Git中的所有数据在存储前都会计算校验和,如果在传输过程中丢失信息或者损坏文件,Git能够及时发现。Git使用SHA-1计算哈希值,基于Git中文件的内容或目录结构计算出来40个十六进制字符组成的字符串。

1.2.4 只添加数据操作

在Git中执行的绝大部分操作都是添加数据的操作,也就是Git中不会执行任何可能导致文件不可恢复的操作。在数据没有提交更新时有可能丢失,但是一旦提交到Git上,就很难丢失数据,因为每次更新时每个客户端本地都会保存一份完整的快照数据。

1.3 Git本地安装部署

1)使用以下命令在centos系统中安装Git

# yum install git –y
# git --version
git version 1.8.3.1

2)配置用户和email地址

# git config --global user.name "Tango"
# git config --global user.email tango@com
# git config --list
user.name=Tango
user.email=tango@com
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true

2、Git工具原理剖析

2.1 Git中三种状态
2.1.1 Git文件三种状态

在Git中文件有三种状态:已提交(committed)、已修改(modified) 和 已暂存(staged)

  • 已修改:表示修改了文件,但还没保存到数据库中。
  • 已暂存:表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
  • 已提交:表示数据已经安全地保存在本地数据库中。
2.1.2 Git项目三个阶段

在这里插入图片描述

基于这三个状态,Git项目分为三个阶段:工作区、暂存区以及Git目录

  • 工作区是对项目的某个版本独立提取出来的内容,这些数据是从Git仓库的压缩数据库中提取出来,放在磁盘上用于后续的使用或修改。
  • 暂存区是一个文件,保存了下次将要提交的文件列表信息,一般在Git仓库目录中。
  • Git仓库目录是Git用来保存项目的元数据和对象数据库的地方。
2.1.3 Git基本工作流程

Git基本工作流程如下:

  • 在工作区中修改文件;
  • 将想要下次提交的更改选择性地暂存,这样只会将更改的部分添加到暂存区;
  • 提交更新,找到暂存区的文件,将快照永久性存储到Git目录。

如果Git目录中保存着特定版本的文件,就属于 “已提交” 状态;如果文件已修改并放入暂存区,就属于“已暂存”状态;如果自上次检出后,作了修改但还没有放到暂存区域,就是“已修改”状态。

2.2 Git中对象
2.2.1 Git目录结构

当在一个新目录或已有目录执行git init时,Git会创建一个.git目录,.git目录的典型结构如下:

drwxr-xr-x. 2 root root   6 Jul  1 19:08 branches
-rw-r--r--. 1 root root  92 Jul  1 19:08 config
-rw-r--r--. 1 root root  73 Jul  1 19:08 description
-rw-r--r--. 1 root root  23 Jul  1 19:08 HEAD
drwxr-xr-x. 2 root root 242 Jul  1 19:08 hooks
drwxr-xr-x. 2 root root  21 Jul  1 19:08 info
drwxr-xr-x. 5 root root  40 Jul  1 19:13 objects
drwxr-xr-x. 4 root root  31 Jul  1 19:08 refs

有4个目录非常重要,是Git的核心组成部分:

  • HEAD文件:指向目前被检出的分支
  • index文件:保存暂存区信息
  • objects目录:存储所有数据内容
  • refs目录:存储指向数据(分支、远程仓库和标签等)的提交对象的指针

除了这4个目录,其它如description文件仅供GitWeb程序使用;config文件包含项目特有的配置选项; info目录包含一个全局性排除(global exclude)文件,用以放置那些不希望被记录在.gitignore文件中的忽略模式;hooks目录包含客户端或服务端的钩子脚本。

2.2.2 数据对象

Git的核心部分是一个简单的键值对数据库,向Git仓库中插入任意类型的内容,会返回一个唯一的键值,通过该键值可以在任意时刻再次取回该内容。

1)初始化Git版本库

# git init tango
Initialized empty Git repository in /usr/local/git/tango/.git/
# find .git/objects/
.git/objects/
.git/objects/pack
.git/objects/info

可以看到Git对objects目录进行了初始化,并创建了pack和info子目录,但均为空

2)使用git hash-object创建一个新的数据对象并将它手动存入Git数据库中

# echo 'test tango' | git hash-object -w --stdin
ef9624cb2770e61445fdba38dacd4af9c9240c19

上述命令将数据存储到Git库中并返回一个40字符的hash值,也是一个唯一键值

3)查看Git中存储的数据

# find .git/objects -type f
.git/objects/ef/9624cb2770e61445fdba38dacd4af9c9240c19

在objects找到与内容对应的文件,一个文件对应一条内容,文件的命名是以内容加上header信息通过HSA-1算法计算hash值取得。前两个字符用于命名子目录,余下的38个字符则用作文件名。通过cat-file命令可以显示保存的内容:

# git cat-file -p ef9624cb2770e61445fdba38dacd4af9c9240c19
test tango

上述保存的对象称为数据对象(Blob Object)

2.2.3 树对象

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

在这里插入图片描述

1)通过命令git update-index为一个单独文件创建一个暂存区,如test01

# echo "version 01" > test01
# git hash-object -w test01
df1c656f9be822fcb40701da71a32b10dc56cc50
# git update-index --add --cacheinfo 100644 \
> df1c656f9be822fcb40701da71a32b10dc56cc50 test01

2)通过git write-tree命令将暂存区内容写入一个树对象

# git write-tree
f2e68037cac9dcebccfdf85ad36dff4c04b0f19d
# git cat-file -p f2e68037cac9dcebccfdf85ad36dff4c04b0f19d
100644 blob df1c656f9be822fcb40701da71a32b10dc56cc50    test01
# git cat-file -t f2e68037cac9dcebccfdf85ad36dff4c04b0f19d
tree

3)创建新的树对象

# echo "new version" > test02
# git update-index --add test02
# git write-tree
f94cde1983fe96dec7cb0e83d09f66f63289d765
# git cat-file -p f94cde1983fe96dec7cb0e83d09f66f63289d765
100644 blob df1c656f9be822fcb40701da71a32b10dc56cc50    test01
100644 blob 2777791d6de7aac03f38b1b8403ad0fae82e28ac    test02

4)通过调用git read-tree命令,可以把树对象读入暂存区,并指定–prefix选项,将一个已有的树对象作为子树读入暂存区

# git read-tree --prefix=bak f2e68037cac9dcebccfdf85ad36dff4c04b0f19d
# git write-tree
79fdfbd5a6a32829908c40babd8781a1c143784e
# git cat-file -p 79fdfbd5a6a32829908c40babd8781a1c143784e
040000 tree f2e68037cac9dcebccfdf85ad36dff4c04b0f19d    bak
100644 blob df1c656f9be822fcb40701da71a32b10dc56cc50    test01
100644 blob 2777791d6de7aac03f38b1b8403ad0fae82e28ac    test02

工作目录的根目录包含两个文件以及一个名为bak的子目录,该子目录包含test01文件的第一个版本。

2.2.4 提交对象

提交对象(commit object)是快照信息的保存。通过调用commit-tree命令创建一个提交对象,指定树对象的hash值以及该提交的父提交对象。

# echo 'first commit' | git commit-tree f2e68
411366ee5bd910edf128778fbf991fb5a2209959

通过git cat-file命令查看这个新提交对象

# git cat-file -p 411366
tree f2e68037cac9dcebccfdf85ad36dff4c04b0f19d
author Tango <tango@com> 1688222097 +0800
committer Tango <tango@com> 1688222097 +0800

first commit

提交对象的格式很简单:它先指定一个顶层树对象,代表当前项目快照;然后是可能存在的父提交(前面描述的提交对象并不存在任何父提交);之后是作者/提交者信息;留空一行,最后是提交注释。

2.2 Git分支

1)Git提交保存数据的过程

在进行提交操作时,Git会保存一个提交对象,其中包含了指向暂存内容快照的指针,同时还有作者信息、提交时候的输入信息和指向它的父对象指针。

在这里插入图片描述

每次修改后提交,那么这次产生的提交对象会包含一个指向上次提交对象(父对象)的指针。

2)Git分支

Git分支,在本质上是指向提交对象的可变指针。Git的默认分支是Master,在多次提交操作后,其实已经指向最后那个提交对象的Master分支。Master分支在每次提交时候会自动移动。下图是分支及其提交历史:

在这里插入图片描述

3)分支创建

使用git branch命令可以创建分支,在提交对象上会创建一个分支。

4)Head指针和分支切换

在Git中Head指针是指向当前所在的本地分支,比如上图的master上。如果需要切换到一个已经存在的分支,比如新建的分支testing,使用命令git checkout完成。

# git checkout testing

在这里插入图片描述

再切换回master分支上更新提交时,就会忽略新的分支testing,出现项目交叉。因此可以在不同分支之间来回切换,并且最后还可以合并起来。Git分支的创建和销毁都非常高效,因为本质上是包含所指对象校验和。

在这里插入图片描述

2.3 分布式Git

与传统的集中式CVS相比,Git的分布式特性使得开发者之间的协作变得更为灵活便捷。集中式系统中通常使用的是单点协作模型,中心的服务器做代码仓库,所有的开发这作为客户端与其同步。当两个开发人员同仓库克隆代码下来并修改提交的时候,第一个开发者可以顺利的提交,但是第二个开发者必须等第一个开发人员提交后并将其中的工作合并进来再提交上去,才不会覆盖掉。在Git中通过权限控制,也支持这种传统的工作流程模式。

2.3.1 集成管理者工作流

Git支持分布式管理流程,允许多个仓库存在,每个开发者拥有自己仓库的写权限和其他所有人仓库的读权限。当开发人员要为项目贡献时,可以克隆一份项目代码到本地仓库,然后将自己的修改推送上去,并通知官方仓库的维护者拉取更新合并到主项目。维护者可以在本地将贡献者的仓库添加为远程仓库并测试,然后将合并后的修改推送到官方仓库。主要流程如下所示:

  1. 项目维护者推送到主仓库;
  2. 贡献者克隆此仓库,做出修改;
  3. 贡献者将数据推送到自己的公开仓库;
  4. 贡献者给维护者发送邮件,请求拉取自己的更新;
  5. 维护者在自己本地的仓库中,将贡献者的仓库加为远程仓库并合并修改;
  6. 维护者将合并后的修改推送到主仓库;

在这里插入图片描述

这是GitHub和GitLab等集线器式(hub-based)工具最常用的工作流程。

2.3.2 主管与副主管工作流

多仓库工作流程的变种,适用于超大型的项目,比如Linux内核项目。各个副主管(lieutenant)分别负责集成项目中的特定部分,副主管头上还有一位称为主管(dictator)的总集成管理者负责统筹,主管维护的仓库作为参考仓库,为所有协作者提供他们需要拉取的项目代码。整个流程如下:

  1. 普通开发者在自己的主题分支上工作,并根据master分支进行变基。这里是主管推送的参考仓库的master分支。
  2. 副主管将普通开发者的主题分支合并到自己的master分支中。
  3. 主管将所有副主管的master分支并入自己的master分支中。
  4. 最后,主管将集成后的master分支推送到参考仓库中,以便所有其他开发者以此为基础进行变基。

在这里插入图片描述

3、总结

Git 作为一款开源的分布式版本控制系统,广泛使用在开发项目的版本管理中。总结一下,具备以下特性:

  1. 分布式:Git是一个分布式的版本控制系统,每个开发者都保存完整的版本历史,不需要联网进行代码比较或签入。这使得开发人员可以在不同地点的设备上进行开发,不受网络限制。
  2. 轻量级分支:Git支持轻量级分支,使得团队成员可以方便地进行协作开发。分支的创建和切换非常快速,而且分支的合并也非常容易操作,这使得团队可以轻松地进行多个并行开发任务。
  3. 高效处理大型项目:Git在处理大型项目版本管理方面表现出色。它能够高效地管理大型项目的文件和版本历史,并提供快速的代码检索、比较和回滚等操作。
  4. 强大的协作功能:Git提供了丰富的协作功能,如分支、合并、标签等,以帮助团队成员更好地协同工作。通过远程仓库,开发人员可以方便地与其他成员共享代码,进行代码合并和协作开发。
  5. 可定制性:Git提供了丰富的配置选项和钩子(hooks),使得开发人员可以根据自己的需求和团队的工作流程进行定制。可以通过配置文件(如 .gitconfig)来设置个人和团队的偏好,以及定义自定义操作。
  6. 社区支持:Git是一个开源项目,拥有庞大的社区支持和活跃的开发人员。这使得 Git 能够持续地改进和发展,并与其他工具和库集成,满足不同场景的需求。

本文简要介绍了Git工具的特性,以及Git中的对象和Git分支管理和分布式工作流程实现。


参考资料:

  1. https://git-scm.com/book/zh/v2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/714226.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker是什么以及docker的常用命令

Docker简介 Docker是一种开源的容器化平台&#xff0c;用于构建、部署和运行应用程序。它允许开发人员将应用程序及其所有依赖项打包到一个称为"容器"的独立单元中。这个容器可以在任何支持Docker的环境中运行&#xff0c;无论是开发人员的本地机器、虚拟机还是云服务…

Bert

参考资料&#xff1a; 《机器学习》李宏毅 1 Bert 是怎么运作的&#xff1f; Bert 是一种自监督学习&#xff08;Self-supervised Learning&#xff09;模型。Bert 的目标是 pre-train 出一个能够理解语义的多功能语言模型&#xff0c;使之能够在特定任务上只学习较少的带标…

快速上手 vercel,手把手教你白嫖部署上线你的个人项目

壹 ❀ 关于 vercel Vercel 是一个云服务平台&#xff0c;支持静态网站&#xff08;纯静态页面&#xff0c;比如现在base utils 文档也是基于vercel&#xff09;和动态网站的应用部署、预览和上线。如果你用过 GitHub Pages &#xff0c;那么心里可能不会太陌生&#xff0c;但你…

Web3 在Truffle项目中编写出自己的第一个solidity智能合约

好 上文Web3本地搭建truffle智能合约开发环境我们在本地搭起了一个 Truffle 项目 然后 我们说明项目中文件的用途 然后 我们还是通过ganache模拟一个本地的区块链环境 然后打开我们搭建的Truffle项目 首先 我们第一个要看的肯定是truffle-config.js 肯定要先配好连接的环境 我…

UDP 协议【传输层协议】

文章目录 1. 传输层1.1 TCP 与 UDP 2. 端口号2.1 端口号标识进程2.2 通过IP地址、端口号、协议号进行通信识别2.3 协议号2.4 端口号的范围2.5 常用命令netstatiostatpidof 2.6 存疑 3. UDP 协议3.1 地位3.2 报头的分离和交付3.3 UDP 报文的格式3.4 UDP 数据封装和分用数据封装数…

rk3288中apk串口打开失败,selinux权限问题

apk打开串口失败 报错信息&#xff1a; 07-03 17:05:27.030 4582 4582 W jw.ComAssistant: type1400 audit(0.0:56): avc: denied { read } for name"ttyS2" dev"tmpfs" ino7704 scontextu:r:untrusted_app:s0:c512,c768 tcontextu:object_r:ttyS2_dev…

《YOLOv8魔术师》专栏介绍 CSDN独家改进创新实战专栏目录

&#x1f4a1;&#x1f4a1;&#x1f4a1;Yolov8魔术师&#xff0c;独家首发创新&#xff08;原创&#xff09;&#xff0c;持续更新&#xff0c;适用于Yolov5、Yolov7、Yolov8等各个Yolo系列&#xff0c;专栏文章提供每一步步骤和源码&#xff0c;轻松带你上手魔改网络 &…

xml合并

from xml.etree.ElementTree import ElementTree, Element, parseimport xml.etree.ElementTree as ETimport osimport shutilhole_path ./Annotationsarm_path ./Annotations1out_path ./out# 格式化def __indent(elem, level0):i "\n" level*"\t"if…

UE5.2 LyraDemo源码阅读笔记(三)

进入淘汰模式游戏流程 启动游戏&#xff0c;进入流程&#xff1a; 1、进入Lyra游戏第三个体验入口FrontEnd。 2、来到大厅主界面后&#xff0c;点击&#xff1a; Play Lyra > Start A Game >ELIMINATION就会进入到淘汰模式游戏。 看看蓝图和代码&#xff0c;其中的UI流程…

dubbo-admin下载安装教程

目录 1.下载 2.项目结构 3.后端打包 4.前端打包 4.1.node js环境准备 4.2.依赖安装 4.3.启动、打包 1.下载 下载地址&#xff1a; GitHub - apache/dubbo-admin at develop dubbo-admin项目有多个分支&#xff0c;最新版本的dubbo-admin在使用go语言进行重构&#xf…

解决电脑提示vcruntime140_1.dll无法继续执行代码的问题

vcruntime140_1.dll丢失要怎么办&#xff1f;其实很多人都在头疼这个问题&#xff0c;关于dll文件的丢失这事情是时常发生的&#xff0c;因为电脑的杀毒软件有时候会误杀&#xff0c;然后就会导致你的游戏程序都打开不了&#xff0c;你必须要修复好了才行&#xff0c;今天小编就…

统计文本中的数字出现频次

统计文本中的数字出现频次&#xff1a;磁盘上有多个文本文件&#xff0c;统计数据写入excel。 (本笔记适合初通 Python 的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教…

AttributeError: module ‘PIL.Image‘ has no attribute ‘ANTIALIAS‘

在使用ddddocr进行图片识别时&#xff0c;报错了&#xff1a; AttributeError: module PIL.Image has no attribute ANTIALIAS 我使用的是Python 3.11&#xff0c;查看一下pillow的版本&#xff1a; print(PIL.__version__)10.0.0 到处百度也没找到原因&#xff0c;最后&am…

IDEA解析Maven依赖过慢

查看Maven配置文件&#xff0c;是否更改为阿里源 maven安装目录/conf/setting.xml 搜索mirrors并在其中添加 <mirror><id>alimaven</id><name>aliyun maven</name><url>http://maven.aliyun.com/nexus/content/groups/public/ </url&…

【嘉立创EDA】层次原理图功能使用,或放置复用图块方法

文章路标👉 文章解决问题主题内容小结文章解决问题 1️⃣ 在一些较为复杂的原理图绘制时,常需要使用到复用图块。何为复用图块,笔者摘取ST MB1136设计原理图纸可以较好表述这个功能,如下图所示: [本图摘取自NUCLEO-F103RB设计图纸 sheet 2 of 5] 图中左上角绿色图块为…

探索iPadOS 17的亮点特性:值得关注的新功能揭秘

探索iPadOS 17的亮点特性&#xff1a;值得关注的新功能揭秘 看完在WWDC23上作为久违的“OneMoreThing”亮相的令人兴奋的AppleVisionPro后&#xff0c;是时候看看同样作为重要角色出现在发布会上的iPadOS了。与iOS一样&#xff0c;iPadOS也来到了17时代。除了一年后同步iOS16的…

WinApp自动化测试之WinAppDriver工具简介

前篇文章中&#xff0c;我们讲到了WinApp自动化测试工具的选择&#xff0c;今天我们来简单介绍WinAppDriver工具。 Windows Application Driver (WinAppDriver)是Windows系统上的一个应用程序驱动工具&#xff0c;使用该驱动程序&#xff0c;测试人员能够通过Appium-Python-Cl…

el_table切换行前校验,决定是否可切换

思路&#xff1a;拿到当前点击行并存储比如叫做oldRow&#xff0c;把即将切换行的row与oldRow做对比&#xff0c;校验是否可切换&#xff0c;若校验不可切换&#xff0c;则通过遍历仍选中仍选中oldRow.

python简单实现人脸检测/跟随

import cv2# 加载人脸识别器的模型 face_cascade cv2.CascadeClassifier(cv2.data.haarcascades haarcascade_frontalface_default.xml)# 打开摄像头 cap cv2.VideoCapture(0)# 初始化人脸框位置 prev_faces []# 定义绘制带圆角矩形边框的函数 def draw_rounded_rectangle(…

C语言学习(三十一)---结构体、联合体的在内存中的存储

在上一篇文章中&#xff0c;我们学习了枚举、位段和联合体的相关内容&#xff0c;在文章的末尾&#xff0c;我们还差了关于联合体的存储问题的内容&#xff0c;今天我们将学习该部分的内容&#xff0c;好了&#xff0c;话不多说&#xff0c;开整&#xff01;&#xff01;&#…