首页 > 其他分享 >Learn Git in 30 days——第 07 天:解析 Git 资料结构 - 索引结构

Learn Git in 30 days——第 07 天:解析 Git 资料结构 - 索引结构

时间:2023-08-28 20:34:00浏览次数:33  
标签:文件 git 07 30 索引 Git commit txt

写的非常好的一个Git系列文章,强烈推荐

原文链接:https://github.com/doggy8088/Learn-Git-in-30-days/tree/master/zh-cn

我们知道在 Git 里两个重要的资料结构,分別是「物件」与「索引」,这篇文章主要用来解说「索引」的细节。使用 Git 版本控制的过程中,或许你可以很轻易的了解 git 指令的用法,不过那很容易流于死记,无法灵活运用,连 Linus Torvalds 都在邮件清单(Mailing List)中提到:「在使用者了解索引的意义之前,是无法完整了解 Git 的能力的」,因此,了解「索引」的用途十分重要。

关于索引

简单来说,「索引」的目的主要用来记录「有哪些文件即将要被提交到下一个 commit 版本中」。

换句话说,「如果你想要提交一个版本到 Git 仓库,那么你一定要先更新索引状态,变更才会被提交出去。」

这里的「索引」其实在国外很多文章里曾经出现过很多別名,但其意思都是相同的,各位以后看到相关单字千万不要被混淆了。

  • Index (索引)
  • Cache (快照)
  • Directory cache (目录快照)
  • Current directory cache (当前目录快照)
  • Staging area (等待被 commit 的地方)
  • Staged files (等待被 commit 的文件)

举个例子来说,指令 git diff --cached 就与 git diff --staged 是完全同义的。

操作索引的指令

由于「索引」对 Git 来说十分重要,在大多数的指令中都会有跟 Git 索引相关的参数可用,不过我们大致列出几个直接与「索引」相关的指令来解说。

在解说指令之前,各位可以先看看以下示意图,这说明了通过指令改变状态的生命周期,事实上,这些改变的过程,都是在更新「索引档」的过程:

image

首先,先介绍四种文件状态:

  • untracked (未追踪的,代表尚未被加入 Git 仓库的文件状态)
  • unmodified (未修改的,代表文件第一次被加入,或是文件内容与 HEAD 内容一致的状态)
  • modified (已修改的,代表文件已经被编辑过,或是文件内容与 HEAD 内容不一致的状态)
  • staged (等待被 commit 的,代表下次执行 git commit 会将这些文件全部送入版本库)

git status

取得 工作目录 (working tree) 下的状态。

由于先前已经讲过仓库、工作目录、物件与索引之间的关系,我们用一句话说明这关系:

Git 仓库的运作,是将工作目录里的变化,通过更新索引的方式,将资料写入成 Git 物件。
 

这里的 git status 指令,目的是显示出 目前最新版 与 索引档 之间的差异,这当中的差异包含了一些微妙的关系,我们用一个例子来解释这层关系。

以下是执行 git status 的结果:

G:\git-demo>git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   c.txt
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   a.txt
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       b.txt
 

这里你会看到有三种不同的分组,分別是:

  • Changes to be committed (准备提交的变更)
    • 这区有个 new file: c.txt 文件,代表 c.txt 是一个新文件,而且已经被标示可提交。
    • 这代表着几件事:
      1. 目前最新版 并没有 c.txt 这个文件
      2. 索引档 已经加入了这个 c.txt 文件
      3. 所以该文件会在执行 git commit 之后被存入下一个版本
  • Changes not staged for commit (尚未准备提交的变更)
    • 这区有个 modified: a.txt 文件,代表 a.txt 已经被变更,但尚未标示可提交。 (not staged)
    • 这代表着几件事:
      1. 目前最新版 也有 a.txt 这个文件
      2. 索引档 尚未加入 a.txt 这个文件
      3. 所以该文件就算执行了 git commit 也不会在下一版中出现
  • Untracked files (未追踪的变更)
    • 这区有个 b.txt 文件,代表 b.txt 尚未被追踪。(untracked)
    • 这代表着几件事:
      1. 目前最新版 没有 b.txt 这个文件
      2. 索引档 也没有 b.txt 这个文件
      3. 所以该文件就算执行了 git commit 也不会在下一版中出现

所以你可以看到,执行 git status 就是为了查出 目前最新版 与 索引档 之间的差异,最终只有 目前最新版 与 索引档 之间有差异的变更,才会真正储存到下一个 commit 物件里。

git add

git add 指令,是为了将目前「工作目录」的变更写入到「索引档」里。

使用 git add -u 则可以仅将「更新」或「删除」的文件变更写入到「索引档」中。

git rm

我们以 git rm 为例,当你直接在文件系统中删除一个文件,这只是从「工作目录」中删除而已,并没有更新到索引档,你可以利用 git status 看到这层改变,不过若要真正把「删除」的状态写进索引档的话,则要靠 git rm filename 更新索引档。

在执行 git rm filename 的时候,除了更新索引档之外,连工作目录下的文件也会一并被删除。若你只想删除索引档中的该档,又要保留工作目录下的实体文件,那么你可以在指令列加上 --cached 参数,就能做到,例如:

git rm --cached a.txt 
 

git mv

使用 git mv oldname newname 可以将文件更名,执行此命令会同时更新索引与变更工作目录下的实体文件。

git commit

这个指令,则是把「索引档」与「目前最新版」中的资料比对出差异,然后把差异部分提交变更成一个 commit 物件。

git ls-files

在索引档之中,预设就包含了 目前最新版 的所有文件,外加你在工作目录中新增文件且通过 git add 更新索引档后的那些文件。通过 git ls-files 命令,可以列出所有目前已经储存在「索引档」中的那些文件路径。

从如下图范例,你应该可以看出这几个指令之间的关系:

image

今日小结

Git 里的「索引」是 Git 版控中最重要的观念,有了这层观念,也自然能得知,为什么每次提交变更都要打一些指令把变更给加进去。当然,也有许多好用的 GUI 工具可以帮你少打许多指令,不过在我们正式开始使用 Git 的 GUI 工具之前,我们还是多靠指令把观念给建立再说吧!

标签:文件,git,07,30,索引,Git,commit,txt
From: https://www.cnblogs.com/songzhenhua/p/17663309.html

相关文章

  • 修改git历史用户名和邮箱
    1、批量修改历史记录中的信息打开一个文本编辑器,粘贴下面代码。然后把 OLD_EMAIL,CORRECT_NAME,CORRECT_EMAIL 改成自己的新旧邮箱用户名。gitfilter-branch-f--env-filter'OLD_EMAIL="原来的邮箱"CORRECT_NAME="现在的名字"CORRECT_EMAIL="现在的邮箱"if["$GIT_COMM......
  • 230722校内赛
    T1CF576D题解我们根据边的出现时间分成\(m\)段对于每一段,设\(f_{T,i}\)表示\(T\)时刻,\(i\)节点能否走到,那么走一步就是个矩阵乘法对于某一段,我们从终点开始bfs可以就可以求出答案,矩阵乘法用bitset优化复杂度\(\mathcal{O}(m^2+\frac{ω}{mn^3}logT)\)#includ......
  • git上传大文件
    目录我尝试使用git上传4GB的文件到gitea上的时候,发现文件会再300MB左右被截断(有文件大小限制)排查发现是git端的问题,不是gitea的问题使用gitlfs解除上传大小限制打开gitbash输入命令gitlfsinstall再输入gitlfstrack"*.mp4"或者gitlfstrack"*"最后gitadd、gitp......
  • 230719校内赛
    T1usaco20febEquilateralTrianglesP题面我就不描述了题解首先我们是不可能暴力计算每一对点距离的我们可以想一想如何将斜着的数个点转换为横着或竖着的数个点,这样会使我们的计算方便许多不难想到的是切比雪夫距离,当然考场上也容易推出这玩意(我就是考场现推的)然后就是如......
  • Steam++加速github,会导致github图床上传失败
    PicGo日志报错信息"message":"unabletoverifythefirstcertificate",原因软件:PIcGO图床:github加速器:Steam++(又称:WattToolkit)由于Steam++安全证书问题,会导致unabletoverifythefirstcertificate,无法验证第一证书问题。关闭加速器即可解决......
  • Git必要命令
    Git安装后必须先配置个人信息,以后的操作都会附带信息1#配置用户名2gitconfig--globaluser.name你的名字34#配置邮箱5gitconfig--globaluser.email你的邮箱查看个人信息可以使用1gitconfig--global--listGit基本理论Git在本地有三个工作区:工作目录(w......
  • Git :团队协作和版本控制的最佳实践
    Git是目前最流行和广泛使用的分布式版本控制系统之一。它不仅能够有效管理代码的版本历史,还提供了强大的团队协作功能。本篇博客将介绍Git的基本概念和常用操作,并详细讲解如何利用Git进行版本控制和团队协作,以提高开发效率和代码管理能力。什么是GitGit是一个分布式版本控制系统......
  • SP13015 CNTPRIME -Counting Primes
    \(CNTPRIME\)-\(Counting\)\(Primes\)题目描述给定初始序列\(A\),然后对原序列有以下操作:操作\(1\):0lrv将区间\([l,r]\)全赋值为\(v\)。操作\(2\):1lr查询区间\([l,r]\)的质数个数。注意:多组测试和特殊的输出。题目分析:就是一道板子题,首先我们先用欧拉筛筛......
  • Git和Gitlab使用
    Git和Gitlab使用前言版本控制概念:记录开发文件的时间机器分类:1.本地版本控制系统、2.集中化的版本控制系统CVS、Subversion(SVN)、3.分布式版本控制系统GIT产品:github、git、gitlabGitlab部署1.介绍git是一个分布式的代码版本管理软件,而gitlab,gierrit,github都是git作......
  • 如何在github或gitlab中将upstream项目中的新分支添加到fork后的origin项目中?
    1、问题:在gitlab或github中,将某项目进行了fork,fork后在自己的项目空间中就有了自己的origin项目,之后如果在源项目(upstream项目)中添加了新的分支,但是在自己的origin项目中不会被同步添加上,这就需要自己去添加这个分支(假如分支名为:new)。2、解决:要将新的分支添加到自己的origin项......