关山难越,谁悲失路之人;萍水相逢,尽是他乡之客。
百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程教程 > 技术文章 > 正文

Git 进阶之基本原理——文件状态转换

guanshanw 2023-10-07 11:53 16 浏览 0 评论

前言

最近在读《Pro Git》这本书,虽然距离第二版已经过去了好几年,Git 也在不断更新,但由于 Git 核心团队一直保持着良好的向后兼容性,所以书中关于 Git 的核心概念和命令依然有效。

本篇为我对 Git 文件状态及其状态转换的理解。

基本原理

上一篇文章讲过 Git 的分支与引用的原理,还有标签的引用方式。本篇文章将讲述的 Git 文件状态也是其核心内容。学习文件状态转换过程,会让你对使用 add、commit、checkout 等上层命令有更好的理解。

Git 文件状态

Git 的文件状态也是其核心内容,学习其文件状态转换过程,会让你对使用 add、commit、checkout 等上层命令时有着更好的理解。

对于 Git 来说,你工作目录下的每一个文件都可以被划分为两类:已跟踪或未跟踪。已跟踪的文件是指那些已加入版本控制的文件,在上一次的快照中有它们的记录,它们的状态可能处于未修改、已修改或已放入暂存区。除已跟踪文件以外的所有文件都是未跟踪文件,它们既没有存在于快照中,也没有被放入暂存区。如果在已有文件的目录中初始化 Git 仓库,则工作目录下所有的文件都会属于未跟踪文件。而通过 clone 拉取某个仓库的时候,工作目录中的所有文件都属于已跟踪文件,并处于未修改状态。

如果修改已提交的文件,Git 会将它们标记为已修改文件。我们可以通过 git add 等命令将修改过的文件放入暂存区,然后在某一时刻统一提交所有暂存的修改。如此反复,就是 Git 中文件的生命周期:


暂存区(Index)

Git 的暂存区是一个很重要的概念,前面曾多次提到,也使用过 update-index 命令将文件放入到暂存区中。一般说法是叫“暂存区(Staging Area)”,不过 Git 本身称之为“索引(Index)”。现在总结一下个人对暂存区的理解。

原子性提交

前面提到过,Git 基于快照实现的版本控制,通过我们的每一次提交(commit)而生成快照,形成了快照流。

Git 中的提交是原子性的。原子性提交指的是,由多个内容变动信息组合成提交后,每一个提交都被视为一个不可分割的最简整体,要么在同一次提交中保存全部修改,要么全部失败。Git 使用原子性提交所带来的好处就是,我们可以很方便的将工作目录中的文件内容切换至提交所生成的快照中,可能是某个阶段的内容,也可能是某个时间点的内容。

基于 Git 原子性提交的特性,我们的文件内容(例如:代码)也需要在提交中保持原子性。即,当代码变动需要提交时,这次的提交应该尽可能的小量并且是一个不可分割的整体,可以是特性(feature)、修复(fix)或是优化(improved)等等。更明确的说就是:一次提交只做一件事。

原子性提交是非常简单的,持续保持原子性提交的习惯,很对你的工作流很有好处;code review 会更加简单,代码更容易回滚,易于追踪变化等等,并且后续的开发者也会非常感谢你的。

暂存区的作用

暂存区就是为了原子性提交这个特性服务的。它可以随机的将各种文件的修改放进去,这样我们就可以用多个指令精确的挑选出我们需要提交的所有修改,从而更好的进行原子性提交。

暂存区原理

Git 将暂存区的内容存储于 .git/index 文件中,存储格式很复杂,具体可以看 Git 仓库的文档 index-format.txt。如果有需要,可以通过 git ls-files 命令查看暂存区中的文件列表信息。


三棵树

在 Git 中,文件在改变状态的同时,其所处位置也在变化。Git 管理着三棵不同的树,无论文件处于何种状态,都会位于某棵树中。“树”在这里的实际意思是“文件的集合”,而不是特指某种数据结构。

HEAD

HEAD 作为一个引用指针,它总是指向你的上一次提交,无论你是不是在一个分支上。最简单的理解,就是将它看做你的上一次提交的快照。这就表示它会是下一次提交的父节点。

使用 cat-file 及 ls-tree 命令可以查看快照信息及其文件目录列表:

$ git cat-file -p HEAD
tree a7b2c0a2a336f4c262ef7cc53e896ddab396edcd
author cnbailian <594647004@qq.com> 1590710985 +0800
committer cnbailian <594647004@qq.com> 1590710985 +0800
?
initial commit
$ git ls-tree -r HEAD
100644 blob e845566c06f9bf557d35e8292c37cf05d97a9769  README.md
100644 blob 8e695ec83aa8b1d596183b26206a514576570fff  doc/doc.md
100644 blob 06ab7d0f9a35a7d1070711496d6ca1cb892a258f  main.go
Index

Index 也就是暂存区,它是你的预期的下一次提交。当你提交时,它的文件内容就是你提交后生成的快照。

使用 ls-files 命令查看 Index 当前的样子:

$ git ls-files -s
100644 e845566c06f9bf557d35e8292c37cf05d97a9769 0 README.md
100644 8e695ec83aa8b1d596183b26206a514576570fff 0 doc/doc.md
100644 06ab7d0f9a35a7d1070711496d6ca1cb892a258f 0 main.go
工作目录

最后一棵树,就是你的工作目录。另外两颗树以一种高效但并不直观的方式将文件内容存储至 .git 目录中。工作目录会将它们解码为实际的文件以便编辑。

你可以将工作目录当作沙盒,在你将修改内容存储至暂存区并提交之前,可以随意更改。但这也意味着在沙盒中的修改,可能会被其他两颗树中检出的内容所覆盖,要注意提交自己想要保存的内容。

$ tree
.
├── README.md
├── doc
│   └── doc.md
└── main.go
?
1 directory, 3 files
工作流程

Git 主要的目的是通过操纵这三棵树来以更加连续的状态记录项目的快照。

总结

本篇为 Git 基本原理的第三篇,目的为理解 Git 文件状态及其转换流程。

至此基本原理篇已结束,下一步将是结合基础命令,讲解 Git 的使用实践。

相关推荐

七条简单命令让您玩转Git
七条简单命令让您玩转Git

凭借着出色的协作能力、快速部署效果与代码构建辅助作用,Git已经得到越来越多企业用户的青睐。除了用于开发商业及消费级应用之外,众多科学及政府机构也开始尝试使用这...

2023-10-07 12:14 guanshanw

基本完整的关于Git分支branch的操作
基本完整的关于Git分支branch的操作

Git使用背景项目中要用到dev或者其他分支开发完代码,需要将该分支合并到master的需求操作步骤下面以dev名称为lex为分支名为例来操作一遍客户端操作:...

2023-10-07 12:14 guanshanw

Git 进阶(合并与变基)
Git 进阶(合并与变基)

在Git中整合来自不同分支的修改主要有两种方法:合并(merge)以及变基(rebase)合并(merge)merge流程图merge的原理是找到这两个分...

2023-10-07 12:13 guanshanw

Git学习笔记 003 Git进阶功能 part5 合并(第一部分)

合并(merge)是很常用的操作。尤其是一个庞大的很多人参与开发的企业级应用。一般会设定一个主分支,和多个副分支。在副分支开发完成后,合并到主分支中。始终保持主分支是一个完整的,稳定的最新状态的分支。...

非标题党,三张图帮你理解git merge和git rebase的区别
非标题党,三张图帮你理解git merge和git rebase的区别

初始场景:基于正常的开发分支修改几个小bug,然后在合并到开发分支上。gitmergegitcheckoutfeaturegitmergeho...

2023-10-07 12:13 guanshanw

git 初次使用(01)
git 初次使用(01)

先从github上克隆代码下来:使用vscode克隆代码如下图,填写上github仓库地址:vscode有时候克隆代码速度比较慢,可以用命令行方式克隆gitc...

2023-10-07 12:12 guanshanw

Git 远程操作

4.Git远程操作命令说明gitremote远程版本库操作gitfetch从远程获取版本库gitpull下载远程代码并合并gitpush上传远程代码并合并4.1远程版本库操作gitre...

Git常用命令-总结
Git常用命令-总结

创建git用户$gitconfig--globaluser.name"YourName"$gitconfig--globaluser.em...

2023-10-07 12:12 guanshanw

git中删除从别人clone下来项目的git信息,并修改为自己的分支

如果你从别人的Git存储库中克隆了一个项目,并想要删除与该存储库相关的Git信息,并将其修改为你自己的分支,则可以执行以下步骤:使用gitclone命令克隆存储库:gitclone<u...

git系列-回滚和放弃本地修改

回滚历史提交就是reset的功能。这种情况是已经提交远程仓库,需要回滚到之前的提交。gitreset--hardcommitId//注:强制提交后,当前版本后面的提交版本将会删掉!gi...

GIT使用小技巧大全
GIT使用小技巧大全

在大型软件工程的开发过程中,版本控制是无法绕过去的;目前来说,最火的版本控制软件就是GIT了。早两年SVN比较火,不过被大神linus喷了几次后,就日落西山了,...

2023-10-07 12:11 guanshanw

git相关命令-上
git相关命令-上

这些命令都是看了文档后,个人觉得比较有用的一些,展示给大家。回到远程仓库的状态抛弃本地所有的修改,回到远程仓库的状态。gitfetch--all&...

2023-10-07 12:10 guanshanw

Git命令行接口:掌握Git的必备技能
Git命令行接口:掌握Git的必备技能

Git是一款强大的分布式版本控制工具,它支持命令行界面操作。熟练掌握Git命令行接口,是开发者使用Git的必备技能之一。在这篇文章中,我们将介绍Git命令行接口...

2023-10-07 12:10 guanshanw

Git命令详解
Git命令详解

相信各位小伙伴们应该都对git有一些了解,毕竟作为代码管理的神器,就算不是IT行业的小伙伴肯定也或多或少的听说过一些。今天就来和小伙伴们分享一下自己总结的常用命...

2023-10-07 12:10 guanshanw

工作7年收集到的git命令
工作7年收集到的git命令

概念git中的术语解释:仓库也叫版本库(repository)stage:暂存区,add后会存到暂存区,commit后提交到版本库git安装linux...

2023-10-07 12:10 guanshanw

取消回复欢迎 发表评论: