栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

玩转Git三剑客01:Git基础

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

玩转Git三剑客01:Git基础

目录

1 版本管理演变

1.1 VCS出现之前

1.2 集中式VCS

1.3 分布式VCS

2 Git的安装与配置

2.1 安装Git

2.2 使用Git的最小配置

2.3 Git配置作用域

2.3.1 git config --local

2.3.2 git config --global

2.3.3 git config --system

3 创建第一个git仓库

3.1 已有项目代码

3.2 尚无项目代码

3.3 设置local作用域配置项

4 提交commit

4.1 Git工作方式概述

4.2 提交commit实例

4.2.1 实验中使用的命令

4.2.2 添加readme文件

4.2.3 添加index.html和logo

4.2.4 添加style.css

4.2.5 添加script.js

4.2.6 修改index.html & style.css

5 文件重命名

5.1 在工作目录重命名文件

5.1.1 在工作目录重命名文件

5.1.2 更新文件管理状态

5.2 使用git mv命令重命名文件

6 Git分支操作

6.1 创建分支

6.2 查看分支信息

6.2.1 git branch

6.2.2 git branch -v

6.2.3 git branch -a

7 通过git log查看版本历史

7.1 git log

7.2 git log --oneline

7.3 git log -nx

7.4 git log --all

7.5 git log --graph

8 通过图形界面工具查看版本历史

8.1 gitk基本布局

8.2 在gitk中显示所有分支

8.3 创建tag

9 Git工作原理分析

9.1 .git目录分析

9.1.1 config文件

9.1.2 HEAD文件

9.1.3 ref目录

9.1.4 objects目录

9.2 Git对象间的关系

9.2.1 Git对象关系实例

9.2.2 Git对象关系图示

9.2.3 实验:Git对象的创建

10 分离头指针

10.1 造成分离头指针状态

10.2 分离头指针状态下变更实例

10.2.1 修改文件并创建commit

10.2.2 切换分支

10.2.3 创建分支保存修改

10.3 HEAD的本质与指代

10.3.1 HEAD的本质

10.3.2 通过HEAD指向祖先提交


1 版本管理演变

VCS(Version Control System):版本控制系统,是一种记录一个或若干个文件内容变化,以便将来查阅特定修订情况的系统

1.1 VCS出现之前

1. 使用目录拷贝区分不同版本

2. 开发过程中,公共文件容易被覆盖

3. 成员沟通成本高,代码集成效率低下

1.2 集中式VCS

1. 具有集中的版本管理服务器

2. 具备文件版本管理和分支管理能力

3. 集成效率明显提高

4. 因为客户端不具备完整的版本历史,因此客户端需要时刻和服务器相连

说明:典型的集中式VCS有CVS(Concurrent Versions System)和SVN(subversion)

1.3 分布式VCS

1. 服务端和客户端都有完整的版本库

2. 脱离服务器,客户端依然可以管理版本

3. 查看历史和版本比较等多数操作,都不需要访问服务器。相较于集中式VCS,更能提高版本管理效率

说明1:典型的分布式VCS有Git和BitKeeper

说明2:Git的特点

① 最优的存储能力

② 非凡的性能

③ 开源

④ 很容易做备份

⑤ 支持离线操作

⑥ 很容易定制工作流程

2 Git的安装与配置

2.1 安装Git

1. 我们的实验环境为Ubuntu 20.04,可以使用如下命令安装Git

sudo apt-get install git-all

2. 安装完成后,可以使用如下命令查看版本信息,以验证安装是否成功

git --version

说明:在其他操作系统上安装Git,可参考安装Git

2.2 使用Git的最小配置

1. 在使用Git之前,至少要配置用户的name和email信息。如果不加配置,后续在生成commit信息时,系统仍会提示需要配置

2. 使用如下命令设置用户的name和email信息

git config --global user.name 'cheng.chen'

git config --global user.email 'cheng.chen@horizon.ai'

3. 配置完成后,可以使用如下命令查看配置是否成功

git config --list

2.3 Git配置作用域

在上面的最小配置示例中,使用了--global参数,该参数用于指定当前配置项的作用域。Git共支持3个作用域

需要注意的是,所有配置最终都要落实到对应的配置文件才能生效

2.3.1 git config --local

1. 只对当前仓库有效

2. 该命令只能在已经建立的git仓库中使用

3. 对应的配置文件为git仓库/.git/config

2.3.2 git config --global

1. 对登录用户的所有仓库有效,是最常用的配置作用域

2. 对应的配置文件为~/.gitconfig

说明:我们可以查看~/.gitconfig文件,验证之前的最小配置是否记录在其中

2.3.3 git config --system

1. 对登录系统的所有用户生效

2. 对应的配置文件为/etc/gitconfig

说明1:从不同作用域配置项的存储文件位置,可以很容易不同作用域的生效范围

说明2:配置作用域的优先级

local > global > system

说明3:不同作用域配置项的查看

git config --list --local

git config --list --global

git config --list --system



# 查看所有作用域的配置项

# 这里其实隐含了一个条件,就是要有读取各配置文件的权限

git config --list

3 创建第一个git仓库

创建Git仓库有2种方法

3.1 已有项目代码
cd 项目代码目录

git init

说明:命令执行后,会在项目代码目录创建.git目录,该目录就是Git实现版本管理的关键

3.2 尚无项目代码
git init project_name # 会在当前路径下创建和项目名称同名的目录

说明:在生成的git_learning目录中,也会创建.git目录

3.3 设置local作用域配置项

之前在global作用域设置了user.name & user.email,现在再以local作用域设置这2个配置项,目的是用于后续验证local作用域的优先级是否高于global作用域

为作区别,local作用域设置不同的user.name & user.email

git config --local user.name 'maidou'

git config --local user.email 'maidoumaizi@sina.com'

说明1:在当前git仓库中查看配置项

说明2:当前git仓库配置文件内容

4 提交commit

4.1 Git工作方式概述

1. 在工作目录修改的文件需要先通过git add操作提交到暂存区

2. 暂存区中的修改记录通过git commit操作生成一次版本提交历史

说明:暂存区使用场景示例

假设实现一个功能有多种方案,

① 在工作目录实现方案1,并将其提交到暂存区

② 在工作目录继续实现方案2,如果验证后方案2更好,则将方案2提交到暂存区;如果方案1更好,则使用暂存区中的内容覆盖工作目录(从另一个角度看,就是撤销当前工作目录的修改)

4.2 提交commit实例

下面通过5次提交来演示单分支开发流程,实验中使用到的文件如下

4.2.1 实验中使用的命令
# 查看当前工作目录和暂存区的状态

git status



# 将工作目录中的内容提交到暂存区

# git add之后可指定多个文件和目录

git add



# 将暂存区的内容提交为版本记录

git commit



# 查看版本记录

git log

4.2.2 添加readme文件

说明:在当前git仓库提交commit,可见生效的是local作用域的配置,即local作用域的配置项优先级高于global作用域

4.2.4 添加style.css

4.2.5 添加script.js

4.2.6 修改index.html & style.css

说明:此处使用git add -u更新工作目录中所有已经被Git管理的文件

5 文件重命名

说明:该实例实现将工程中的readme文件重命名为readme.md

5.1 在工作目录重命名文件

5.1.1 在工作目录重命名文件

在工作目录重命名文件后,git status将显示readme文件被删除,同时新增未被Git管理的readme.md文件

5.1.2 更新文件管理状态

根据上一步git status中的提示,使用git add / rm命令更新文件管理状态

说明1:更新文件管理状态后,Git会识别出此次操作实现了文件的重命名,后续只要通过git commit提交,即可生成新的版本信息

说明2:使用当前方法,重命名文件需要执行3条命令

mv

git add

git rm

说明3:撤销本次修改

为了进行后续实验,此处需要撤销本次修改,可以使用如下命令清理当前的暂存区和工作目录

git reset --hard

需要注意的是,此时的重命名修改尚未commit,只是提交到暂存区

tips:由于git reset --hard命令会清空当前暂存区和工作目录中的修改,所以需要谨慎使用

5.2 使用git mv命令重命名文件

使用一条git mv命令可以实现同样的效果

需要注意的是,git mv命令的修改直接体现在暂存区,而不是在工作目录,不需要通过git add命令提交到暂存区

说明:使用git mv命令可以实现和之前相同的功能,但是只需要执行一条命令。此时将文件名修改提交,由于更改文件名的操作已经被加入暂存区,只需要commit即可

6 Git分支操作

6.1 创建分支

为了更好地说明git log查看版本历史的方法,此处先建立一个分支

我们以Add style.css的commit为基础创建分支,命令如下,

git checkout -b 新分支名称 对应commit编号

说明1:也可以基于已有分支创建新分支,命令如下,

git checkout -b 新分支名称 已有旧分支名称

说明2:git checkout -b命令在创建分支的同时也会切换到该分支,我们在新建的temp分支上进行修改并创建commit

说明3:使用如下命令可以基于当前commit创建新分支,但此时不会切换到新创建的分支,需要使用git checkout命令进行切换

git branch 分支名称

说明4:使用如下命令可以在已有分支之间进行切换

git checkout 分支名

6.2 查看分支信息

6.2.1 git branch

通过git branch命令可以查看当前仓库的所有分支,其中当前分支前会加星号(*)

6.2.2 git branch -v

通过git branche -v命令可以查看当前仓库的所有分支及其HEAD指向的commit信息

在当前测试环境中,各分支的HEAD指向最后一次提交的commit信息

6.2.3 git branch -a

通过git branch -a命令可以同时查看本地分支和远程分支

由于当前并未建立远程分支,所以git branch -a命令与git branch命令显示的内容相同

说明:下面给出一个拥有远程分支的仓库实例,其中红色的是远程分支

7 通过git log查看版本历史

7.1 git log

git log命令可以查看当前分支版本历史,之前已有多个实例

说明:可以在git log之后指定要查看的分支名称

在示例中,temp为当前分支,但是可以指定查看master分支的版本历史

7.2 git log --oneline

git log --oneline命令可以查看当前分支简洁的commit信息

7.3 git log -nx

此处的x是一个数字,用于指定要查看的commit个数,可以指定查看当前分支最新的x次commit信息

7.4 git log --all

git log --all命令可以查看所有分支的commit信息

7.5 git log --graph

git log --all命令会按提交顺序显示所有分支的commit信息,难以看出不同分支的源流关系,此时可以添加--graph选项,以图形化方式显示源流关系

说明:上面介绍的命令行选项可以组合使用

可见此时-n4显示的是所有分支的最近4个commit信息,而不是每个分支的最近4个

8 通过图形界面工具查看版本历史

8.1 gitk基本布局

在git仓库中运行gitk命令后,版本历史将会以图形界面的方式呈现

说明1:在Ubuntu系统中,默认并未安装gitk工具,需要用户自行安装

说明2:对于文件信息,当选择Patch时,显示的是本次commit的文件变更信息;当选择Tree时,显示的是本次commit后的文件内容

说明3:gitk commit信息说明

① Branches信息

包含该commit的所有分支

② Author & Commiter不一致的场景

当通过cherrypick操作挑选某一次的提交到指定分支时,为了尊重版权,Author & Commiter就是不同的,Author将保留原作者信息

8.2 在gitk中显示所有分支

有2种方式可以在gitk中显示所有分支信息

1. 在git仓库中使用gitk --all信息启动gitk

2. 在view选项中显示所有分支

由于本地分支(local branches)、标签(tags)和远程分支(remote branches)都是reference,所以此处选择All refs,就包含了所有这些信息

说明:使用gitk --all命令启动gitk时,view选项中指定的就是All refs

8.3 创建tag

在要创建tag的commit上点击鼠标右键,可见gitk提供了多种功能选择项

我们选择Create tag选项,并输入Tag的名称与信息,即可创建Tag

可见Tag已经创建完成,点击该Tag的标签,即可显示相应的Tag信息

9 Git工作原理分析

9.1 .git目录分析

9.1.1 config文件

如上文所述,该文件为local作用域配置文件,内容如下

9.1.2 HEAD文件

1. HEAD文件表示git仓库当前正在工作的分支

2. HEAD文件内容如下,

可见HEAD文件指向refs目录中的一个引用

说明:将git仓库切换到master分支,HEAD文件指向的引用也将随之变化

9.1.3 ref目录

ref目录中包含了heads和tags两个子目录,其中,

1. heads目录对应分支,分支是一个独立的开发空间,不同分支之间互不影响

2. tags目录对应标签,标签是项目开发到一定程度的一个里程碑(e.g. 在开发到版本v1.0对应的commit上创建标签)

说明:从目录结构可以看出,分支和标签都属于引用

9.1.3.1 heads/master文件

1. 文件内容

2. 对象类型

可见master文件指向的是一个commit

说明:git cat-file命令

git cat-file命令可用于查看git仓库对象的类型、内容和大小信息,其中,

① -t选项查看对象类型(show the object type)

② -p选项查看对象内容(pretty-print the content of object based on its type)

③ -s选项查看对象大小(show the object size)

3. 对象内容

可见对象的内容,就是该commit对应的信息,即master指向maser分支的最后一个commit

9.1.3.2 heads/temp文件

1. 文件内容

2. 对象类型

3. 对象内容

可见temp指向temp分支的最后一个commit

9.1.3.3 tags/tag01文件

1. 文件内容

2. 对象类型

3. 对象内容

可见tag01指向对应标签的信息

说明:由于tag也是基于commit创建的,所以查看对应的commit类型与内容

可见对应的正是创建tag的commit

9.1.4 objects目录

1. objects目录是Git文件系统的核心内容

2. objects目录中的目录名 + 文件名构成对象的哈希值

以上图为例,目录名(00)+ 文件名(1975b3b等)就构成了所存储的Git对象的哈希值

3. Git在使用过程中,会对存储的文件进行梳理与压缩,如果有压缩文件产生,则会存储在pack目录中(这也是为何Git可以取得最优的存储性能)

9.2 Git对象间的关系

9.2.1 Git对象关系实例

Git中的三个核心对象为commit、tree、blob,下面以.git/objects目录下存储的文件系统实例,来展示Git对象间的关系

1. commit对象

① objects/00目录下存储的对象为commit

② 该commit中存储了一个tree对象

2. tree对象

① tree对象中存储了一系列tree对象和blob对象

② tree对象中存储的对象关系,与相应的git仓库目录树对应

3. blob对象

此处显示的是index.html对应的blob对象的内容,可见就是index.html文件的内容

9.2.2 Git对象关系图示

1. 每次执行git commit命令,都会创建一个commit对象

2. 一个commit对象会对应且只对应一个tree对象,该tree对象表示的是该commit对应的git仓库中所有目录和文件的快照(状态)

3. tree对象对应的是目录

4. blob对象对应的是具体的某个文件

说明:在Git中,blob对象和文件名没有关系。任何文件只要内容相同,就使用同一个blob存储,从而可以提升Git的存储性能

9.2.3 实验:Git对象的创建

实验内容:新建一个git仓库,仅包含doc/readme文件,之后创建commit。在此过程中,查看Git对象的创建过程

9.2.3.1 新建git仓库

9.2.3.2 创建目录

说明:新建的空目录不会被Git管理

9.2.3.3 创建文件

说明:此时创建的文件尚未提交到暂存区,Git不会为其创建对象

9.2.3.4 将修改提交到暂存区

说明:将修改提交到暂存区后,Git会为其创建对象

我们来查看该对象的类型与内容

可见该对象的类型为blob,内容就是readme文件的内容

9.2.3.5 创建commit

说明:创建commit后,Git创建的对象状态如下

可见共创建了4个对象,下面逐一查看这些对象的类型与内容

可见共生成了1个commit对象、2个tree对象和1个blob对象,他们的关系如下图所示

10 分离头指针

10.1 造成分离头指针状态

基于指定的commit执行checkout命令,可以不创建分支,而是造成分离头指针的状态

1. 分离头指针(detached HEAD state)的本质含义,就是目前工作在没有关联分支的状态下

2. 分离头指针状态注意事项如下,

① 可以在分离头指针状态下继续开发(e.g. 进行变更并创建commit),且不会影响其他分支

② 当切换分支时,在分离头指针状态下进行的变更会被丢弃

③ 可以新建分支,保存在分离头指针状态下进行的变更

说明1:当前分支状态

可见当前没有关联到任何分支

说明2:当前HEAD状态

由于HEAD就是指向分支的,所以当前HEAD也体现为没有关联到任何分支。作为对比,正常情况下HEAD会指向某个分支

10.2 分离头指针状态下变更实例

10.2.1 修改文件并创建commit

修改style.css文件,并创建commit

说明1:使用-am选项创建commit时,是根据工作目录中的修改直接创建,省略了将修改提交到暂存区的步骤(但是不推荐)

说明2:创建commit后,HEAD指向新创建的commit,且仍处于分离头指针状态

10.2.2 切换分支

1. 可以从分离头指针状态切换到指定分支

2. 切换时会提示需要创建新分支保存在分离头指针状态下的变更,否则修改会被丢弃

说明:通过git log命令可发现在分离头指针状态下的变更并未被Git管理

10.2.3 创建分支保存修改

可见在创建新分支后,之前在分离头指针状态下的变更已被Git管理

说明:分离头指针状态的使用场景

基于某个commit进行尝试性的变更,如果需要保存,则新建分支;如果无需保存,则直接切换到其他分支

10.3 HEAD的本质与指代

10.3.1 HEAD的本质

HEAD本质上会指向一个commit,

1. 在正常状态下,HEAD会指向分支的最后一个commit,这点在chapter 9.1.3已有验证

2. 在分离头指针状态下,HEAD会指向某个指定的commit

10.3.2 通过HEAD指向祖先提交

10.3.2.1 实验场景

假设要比较如下2个commit之间的差异,

1. 通过commit的哈希值进行比较

2. 通过HEAD的指代进行比较

之所以可以通过HEAD进行指代,就是因为HEAD本质上就是指向一个commit

10.3.2.2 ~的作用

1. ~表示一个提交的第n个祖先提交,如果不指定n,那么默认为1

2. 假设有如下commit提交关系,

那么HEAD~1指向B,HEAD~2指向A

说明:~也可以按如下方式使用

HEAD~~与HEAD~2等价

10.3.2.3 ^的作用

1. ^表示一个提交的第n个父提交,如果不指定n,那么默认为1

2. 假设有如下commit提交关系,即C是由B合并到A中并产生的一个新提交,

那么HEAD^1指向A,HEAD^2指向B

说明:^也可以按如下方式使用

HEAD^^与HEAD~~等价,而与HEAD^2不等价

参考资料:获取git某分支的祖先提交(HEAD^2和HEAD~2)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/730140.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号