您现在的位置是:首页 > 智能机电

深入理解:git 文件管理与索引的工作原理

智慧创新站 2025-05-22【智能机电】93人已围观

简介前言这一夜,注定是个不眠之夜,小白和cangls的对话已然进入了白热化。小白孜孜不倦地咨询关于git方面的知识,对索引越来越感兴趣。小白以前存的小电影文件可以进行版本的对比,探索哪个版本画质更好。小白:cangls,我最近有点疑惑。cangls:具体是哪些方面呢?小白:最近有些需求,我需要对文件进行...


前言

这一夜,注定是个不眠之夜,小白和cangls的对话已然进入了白热化。小白孜孜不倦地咨询关于git方面的知识,对索引越来越感兴趣。小白以前存的小电影文件可以进行版本的对比,探索哪个版本画质更好。

小白:cangls,我最近有点疑惑。

cangls:具体是哪些方面呢?

小白:最近有些需求,我需要对文件进行版本管理控制,但是有些问题百思不得其解。

cangls:版本管理啊,这个我可熟悉呢,最近也在总结系列文章。看了之后,相信会对你有所帮助。

LinusTorvalds在Git邮件列表里曾说如果不先了解索引的目的,你就不能完全领会Git的强大之处。

本文为个人Git系列文章第二弹,git进阶内容之不得不了解的文件管理与索引。Git的索引不包含任何文件内容,它仅仅追踪你想要提交的那些内容。当执行gitcommit命令的时候,Git会通过检查索引而不是工作目录来找到提交的内容。虽然git在底层为了我们处理了很多事情,但记住索引和它的状态也很重要。在任何时候都可以通过gitstatus命令来查询索引的状态。

正文

VCS的经典问题之一就是文件重命名会导致它们丢失对文件历史记录的追踪。而Git即使经过重命名,也仍然能保留历史信息。在实际的工作使用中,貌似Git系统处理文件重命名的方式更优越一点点。因为啊,git有多种方式处理重命名一个文件(比如:使用gitrm配合gitadd、gitmv),而以往的程度还不足以确保SVN知道所有的情况。但是,还没有能完美处理重命名的文件系统。

一、git文件分类1、git文件分类

git将所有文件分为3类:已追踪的、被忽略的和未追踪的,如下图所示。

git中的文件分类

已追踪的Tracked

被忽略的Ignored

未追踪的Untracked

1.1、已追踪的(Tracked)

已追踪的文件是指已经在版本库中的文件,或者是已经暂存到索引中的文件。如果想将新文件newfile添加到为已追踪(Tracked)的文件,执行gitaddnewfile命令即可。例如暂存文件。

复制代码
1.2、被忽略的(Ignored)

被忽略的文件必须在版本库中被明确申明为不可见或被忽略,即使它可能会在你的工作目录中出现。一个软件项目通常会有很多倍忽略的文件(使用过SVN开发Java的小伙伴就很熟悉了,通过提交时我们可以选择忽略哪些固定的文件不提交)。普通被忽略的文件包含临时文件、个人笔记、编译器输出文件以及构建项目过程中自动生成的大多数文件等等。Git维护一个默认忽略文件列表,也可以配置版本库来识别其它文件。

1.3、未追踪的(Untracked)

未追踪的文件是指那些不在前两类中的文件。Git把工作目录下的所有文件当成一个集合,减去已追踪的文件和被忽略的文件,剩余部分最为未被追踪的文件(Untracked)。

这里测试,初始化了一个名为test目录的仓库,原本包含了一个文件。但是我没有将其暂存或者是添加到版本库中,就是如下你看到的显示未追踪的文件(Untrackedfiles)。

$gitstatusHEADdetachedatbd156abUntrackedfiles:(use"gitaddfile"toincludeinwhatwillbecommitted)(use"gitadd"totrack)

为了演示说明,重新初始化了一个sky工作目录。通过创建一个全新的工作目录和版本库并处理一些文件来测试验证这些不同类别的文件。

查看状态$gitstatusOnbranchmasterNocommitsyetnothingtocommit(create/copyfilesanduse"gitadd"totrack)再次查看状态,显示一个未被追踪的文件sky$gitstatusOnbranchmasterNocommitsyetUntrackedfiles:(use"gitaddfile"toincludeinwhatwillbecommitted)skynothingaddedtocommitbutuntrackedfilespresent(use"gitadd"totrack)

起初,目录里没有文件,已经追踪的文件和被忽略的文件都是空的,因此未追踪的文件也是空的。一旦创建了一个sky文件,gitstatus就会报告一个未追踪的文件。

编辑器和构建环境常常会在源码文件周围遗留一些临时文件。在版本库中这些文件通常是不应该被当做源文件追踪的。为了让Git忽略目录中的文件,只需要将该文件名添加到一个特殊的文件.gitignore中即可。手动创建一个测试的垃圾文件,然后放入.gitignore文件中进行维护。如下是演示过程中的示例:

查看状态,此时未添加到忽略文件中进行维护$gitstatusOnbranchmasterNocommitsyetUntrackedfiles:(use"gitaddfile"toincludeinwhatwillbecommitted)(use"gitadd"totrack)新增一个工作目录test$mkdirtest暂存文件

注意:在暂存的过程中,你会发现gitdiff这个命令非常的有用。这条命令可以显示出两组不同的差异,gitdiff显示仍然留在工作目录中且未暂存的变更;gitdiff--cached显示已经暂存且因此需要有助于下次提交的变更。

1、gitadd用法,探寻原理

gitadd命令的意义是将暂存一个文件。以Git文件分类而言,如果一个文件是未追踪的,那么gitadd会将文件的状态转化为已追踪状态。如果gitadd作用一个目录,那么该目录下的所有文件都会被递归为已追踪状态暂存起来。接着之前的例子,继续进行讲解。

$gitstatusOnbranchmasterNocommitsyetUntrackedfiles:(use"gitaddfile"toincludeinwhatwillbecommitted).gitignoreskynothingaddedtocommitbutuntrackedfilespresent(use"gitadd"totrack)通过vim修改,新增了addnewsomedatanow$catskynewdataaddnewsomedatanow删除文件
1、gitrm命令的用法

Git可以从索引或者同时从索引和工作目录中删除一个文件。Git不会只从工作目录中删除一个文件,普通的rm命令可用于这一目的。

从工作目录和索引中同时删除一个文件,并不会删除该文件在版本库中的历史记录。文件的任何版本,只要是提交到版本库中的历史记录中的一部分,就会留在对象库里并保存历史记录。继续上述的例子,引入一个不应该暂存的意外文件,看如何将其删除。

提示:无法对Git认为是other的文件执行gitrm意外暂存rdms文件$gitaddrdms$gitstatusOnbranchmasterNocommitsyetChangestobecommitted:(use"gitrm--cachedfile"tounstage)newfile:.gitignorenewfile:rdmsnewfile:sky

如果要将一个文件由已暂存的转化为未暂存的,可以使用gitrm--cached命令。

删除$gitrm--cachedrdmsrm'rdms'可以看出,加上--cached参数并不会删除工作目录中的文件$

gitrm--cached会删除索引中的文件并将其保留在工作目录中,而gitrm则会将文件从索引和工作目录中同时删除。所以,我额外的加了注意事项在文末,并予以说明。

如果想要移除一个已经提交的文件,通过简单的gitrmfilename命令来暂存这一请求。

将之前暂存的文件sky移除暂存$gitrmskyrm'sky'或者提交后采取如下命令找到对应的散列值,进行恢复,rev-list命令很实用,请拿起小本本记住她$gitrev-listmaster82e23d40959116ae55ca82ced231e0069d8fc229$gitcheckout82e23d40959116ae55ca82ced231e0069d8fc229Warning:youareleaving1commitbehind,notconnectedtoanyofyourbranches:40eac09deletesomefilesIfyouwanttokeepitbycreatinganewbranch,thismaybeagoodtimetodosowith:gitbranchnew-branch-name40eac09HEADisnowat82e23d4addsomefiles

注意:rev-list命令很实用,请拿起小本本记住她。

此处只是顺带的提一下。当我们删除了一个文件,此时想回退到历史版本,可以使用gitcheckout接上master分支的ID(SHA1)。如何找到ID值呢?这里仅仅是简单的介绍了一下gitrev-list的用法,相信你会爱上她的。当然还可以加上参数--before,接指定的日期去查询分支。

检出历史版本,根散列值恢复到上一个版本$gitcheckoutbd156ab27fc96e78e5515c39c05d4ecd6c36b9f0

版本系统擅长恢复文件的旧的版本。关于gitrm命令就演示这么多。

四、gitmv命令1、简单描述使用

例如,使用gitmv命令将文件重命名为,如下命令所示。

移动一个文件的位置gitmv/github//gitee/
2、gitmv详细用法介绍

假设你需要移动或者重命名文件。可以对旧的文件使用gitrm命令,然后使用gitadd命令添加新文件,或者直接使用gitmv命令。给定一个版本库,其中有一个test文件,你想要将重命名为newtest。下面一系列的命令就是等价的Git操作。

$mvtestnewtest$gitrmtest$gitaddnewtest)开头的行可以用于注释。然而,如果未指定参数gitcommit-m"注释"或者提交全部(注意事项:导致暂存和未暂存以及未追踪的文件发生变化)gitcommit-a-m"提交全部"

这里补充一个git常用的命令gitdiff,查看提交差异。使用之前提交的两个全ID名并执行gitdiff,通过gitlog命令查看ID值。

$gitdiff988df9ddbeb6b30d0bf5138f36219a8593df75e0bd156ab27fc96e78e5515c39c05d4ecd6c36b9f0diff--gita//.2b64487---/dev/null+++b/@@-0,0+1@@+初始化
1.2、注意事项

以前只是用来写作,也没多想,最多就写个注释就直接提交(commit)和推送(push)到远程仓库了。原本我思考过这样一个问题,当我提交的时候不加参数也不指定提交的文件,会有什么影响。起初也是好奇,才翻阅了一些书籍发现有很多门道的。

后来,注意到了关于gitcommit--all注意事项。commit-a或者-all参数会导致执行之前自动暂存所有未暂存的和未追踪的文件变化,包括从工作副本中删除已追踪的文件。

注意:如果不通过命令行直接提供日志消息,Git会启动编辑器,并提示你写一个。

2、gitrm--cached注意事项2.1、回顾删除命令
递归删除test目录gitrm-rtest#将文件标记为未追踪的,却在工作目录中仍然保留着一份副本(慎重使用)
2.2、注意事项

gitadd是加一个文件暂存起来,与之相反的就是gitrm是将一个文件由暂存状态移除暂存,并且rm会将文件从索引和工作目录中都删除。使用gitrm--cached命令会将文件标记为未追踪的,却在工作目录中仍然保留着一份副本,这是很危险的。因为你也许会忘记之前自己做过了哪些操作,换句话来说是会忘记这个文件是不再被追踪的。Git需要检查工作文件中的内容是最新的,使用这种方法则无视了这个检查,从而增加了隐患。所用要慎重使用gitrm--cached命令。

总结

以上就是此次文章的所有内容的,希望能对你的工作有所帮助。感觉写的好,就拿出你的一键三连。如果感觉总结的不到位,也希望能留下您宝贵的意见,我会在文章中进行调整优化。

很赞哦!(79)