玩转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 --localgit config --list --globalgit 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.3 添加index.html和logo
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条命令
mvgit addgit 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个祖先提交,如果不指定n,那么默认为1
2. 假设有如下commit提交关系,
那么HEAD~1指向B,HEAD~2指向A
说明:~也可以按如下方式使用
HEAD~~与HEAD~2等价
10.3.2.3 ^的作用
1. ^<n>表示一个提交的第n个父提交,如果不指定n,那么默认为1
2. 假设有如下commit提交关系,即C是由B合并到A中并产生的一个新提交,
那么HEAD^1指向A,HEAD^2指向B
说明:^也可以按如下方式使用
HEAD^^与HEAD~~等价,而与HEAD^2不等价
参考资料:获取git某分支的祖先提交(HEAD^2和HEAD~2)
玩转Git三剑客01:Git基础相关推荐
- 玩转Git三剑客——01. 课程综述
学习视频:玩转Git三剑客(苏玲 携程代码平台负责人)--极客时间 https://time.geekbang.org 1. 版本控制系统(Version Control System, VCS)的演 ...
- git进阶 | 01 - git基础操作进阶
引言 上次写git入门教程还是2019年(Git & Github学习总结),三年期间使用最多的命令不过三条: git add -A git commit -m "" gi ...
- 玩转Git三剑客——04. 创建第一个仓库并配置local用户信息、05. 通过几次commit来认识工作区和暂存区...
学习视频:玩转Git三剑客(苏玲 携程代码平台负责人)--极客时间 https://time.geekbang.org 一.建Git仓库 两种场景 1. 把已有的项目代码纳入Git管理 cd 项目代码 ...
- Git三剑客之基础部分
文章目录 git三剑客 概要 一.Git基础 安装Git 配置信息 创建仓库&&local信息 简单认识工作区.暂存区 1.生成git文件 2.加入style.css 3.加入js文件 ...
- 《玩转git三剑客》笔记
文章目录 Git 基础 .git目录 对象 commit tree blob Git命令 GitHub 三种Pull Request的区别 Git 基础 .gitignore中指定不需要Git管理的文 ...
- 「高效程序员的修炼」代码版本管理工具 Git 用起来 01 Git 基础
如果对你有帮助,点个关注点个赞吧~ 文章目录 1. Git 基础 1.1 使用Git之前的最小配置 1.2 创建仓库 1.3 工作区和暂存区 1.4 Git中重命名文件 1.5 git log 查看版 ...
- 《玩转Git三剑客》
文章目录 3.使用Git之前需要做的最小配置 建Git仓库 往仓库添加文件 git log查看版本演变历史 gitk 通过图形界面工具查看版本历史 探秘 commit tree blob的关系 树一树 ...
- 厉害了!寓教于乐,用玩游戏的方式学习 Git!
作者 | mozlingyu 来源 | 少数派 用游戏的方式来学习,是一种有趣而高效的方式. 从刚接触电脑时的打字练习软件 金山打字通,到程序猿写代码的利器 Vim 都有小游戏(金山打字通游戏.VIM ...
- 《Git篇》01.Git看这一篇就够了
陈老老老板 说明:在整体的复习一遍知识,边复习边总结,基础真的重要,需要注意的地方都标红了,还有资源的分享. 一起加油.关于git的文章之前写过只有指令的这个更多的是扩展知识,比svn好用太多 视频链 ...
最新文章
- python中将一个全部为int的list 转化为str的list
- Geodatabase中基于规则的拓扑关系管理机制
- C语言及程序设计提高例程-10 调试技术:进入函数内部去
- Flink AggOperator 增量聚合函数
- 我究竟为什么要每天埋头写代码?
- php sql 字段不能为空值,关于php:Sudden SQL问题-一般错误:1364字段没有默认值
- Numpy安装+导入出错的解决方法
- 库表操作 - 存储引擎
- [ZOJ 3607] Lazier Salesgirl
- myeclipse安装使用svn
- ue4 基于motion vector粒子优化的一些感悟
- 无损音乐刻录成cd有意义吗_这5个强大免费的无损音乐网站,你收藏了吗?
- 仿网易云PC端项目-vue
- 向量叉乘求三维空间中两直线(或线段)的交点
- 逃不开的安迪-比尔定律,在智能机器人时代该如何破解?
- Android 集成 Agora SDK 快速体验 RTC 版多人视频聊天|掘金技术征文
- 如果给video标签动态写入视频?
- 蚊子凭啥只咬你?科学家用 5 年造出一批“脑子发光”的蚊子,终于搞懂背后机制
- 为什么IT行业这么火?
- python中一切内容都可以称为_创业基础答案黑龙江大学
热门文章
- java puzzlers英文版_java puzzlers [更新至14.04.03]
- 九阴真经 服务器列表文件,《九阴真经》部分服务器互通升级公告
- java jsch shell_仅在JSch shell通道中获取特定命令的输出
- 计算机二级只有前十套简单,计算机二级Access上机十套试题详细解析(经典版).
- 7z 头部错误 数据错误_Vue项目组件数据类型错误处理
- 运行jar中某个类的main方法
- redis入门综合概要介绍
- 反转map的key-value
- 【Jetty】Jetty 的工作原理以及与 Tomcat 的比较
- 修改驱动器重定向显示格式