社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Git

了解git重置对索引的影响

Zizou • 5 年前 • 1406 次点击  

我在阅读有关git reset的文档/教程时遇到了一个小冲突:for git reset --mixed 例如,文件上说:

reset接下来要做的是用任何快照的内容更新索引 HEAD 现在指向

引起我冲突的是我期待的事实 清除索引 而不是 更新索引 是的。索引是否被清除或用任何快照更新 头部 现在指向?

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/48400
 
1406 次点击  
文章 [ 1 ]  |  最新文章 5 年前
torek
Reply   •   1 楼
torek    6 年前

TL;博士

索引总是更新的。指数保持不变 下一次你打算做出的承诺 ,所以它永远不会是空的。(什么,从来没有?好吧,几乎从来没有:里面是空的 新的 您刚刚创建的存储库没有文件,如果您运行 git commit 马上。它也是空的如果你 git rm 一切 (第三章)

你在这里的困惑几乎肯定与 the comment PetSerAl made 是的。那些对Git不熟悉的人经常被告知或展示,或者至少让他们相信提交和/或Git的索引包含 变化 ,但这是假的一旦你摆脱了这种不正确的信念,git的一些奥秘就开始变得更有意义了。(不是 全部的 对任何人都有意义,甚至对我。所以不用担心如果需要很长时间 grok 吉特。)

在吉特,a 犯罪 包含 所有文件的完整快照 是的。它还包含一些元数据信息 关于 提交本身,如您的姓名、电子邮件地址和时间戳。元数据中包含提交的 起源 提交,或者,对于合并提交,多个父级,复数形式 比较 向他们的父母承诺git会向您显示更改。每个提交都有自己唯一的散列ID,例如 8858448bb49332d353febc078ce4a3abcc962efe (这是git存储库中git的提交的id)。该提交是快照,但该提交有父级(在本例中, 67f673aa4a... ),所以Git可以 显示 8858448bb4... 通过提取 二者都 较早的 67f673aa4a 8858448bb4 ,然后比较两者这个 git show 命令就是这么做的,所以你看到的就是 改变 在里面 8858448bb4号 ,而不是什么 在里面 8858448BB4号 是的。

(这就像告诉你今天比昨天暖和或凉爽5度,风或多或少,而不是把天气当成一堆数字数据库存储绝对值,但我们主要想知道它是否更好。)

索引存储下一次可以执行的提交

您可以通过各种方式看到git的提交,当然也可以按照它们的hash id命名它们,正如我在上面所做的那样。你可以看到你的 工作树 这就是git允许您直接查看和编辑文件的地方:在您的计算机上,它们以正常的日常形式存在。但你不能 看见 指数很好。有点看不见这是个问题,因为它也很关键。

大多数版本控制系统根本没有索引,或者如果有类似的索引,就保留它 好隐蔽 你不必知道但是吉特做了一件奇怪的事 强迫 你要了解git的索引,同时还要把它隐藏起来。

如果您真的想查看索引中的文件列表,可以使用 git ls-files :

$ git ls-files | head
.clang-format
.editorconfig
.gitattributes
.github/CONTRIBUTING.md
.github/PULL_REQUEST_TEMPLATE.md
.gitignore
.gitmodules
.mailmap
.travis.yml
.tsan-suppressions
$ git ls-files | wc -l
    3454

在这个Git的Git存储库中,索引中有将近3500个文件那是很多文件这是 为什么 Git把它隐藏起来:里面有太多东西无法理解。

但这也是 为什么 Git通过将他们与他们的父母进行比较来显示我们的承诺显示 全部内容 8858448bb4号 太多了,所以 git show 8858448bb4 告诉我们什么 改变 在里面 8858448bb4号 ,与其父对象的比较git对索引采取了相同的策略,向我们展示了我们所拥有的 改变 而不是把整件事都扔了。

我认为,这正是人们认为Git正在存储更改的原因吉特 显示 更改,因此git必须 储存 他们但不是Git存储所有快照吉特 算出 每次你让Git给你看东西的时候都会有变化。

考虑到这一点,让我们看看 看见 索引。

索引位于 之间 当前提交和工作树

我们现在知道,每个提交都是一个完整的快照。如果Git在我们每次提交文件时都为每个文件创建一个新副本,那么存储库将很快变得非常大所以它不会这么做,而且 方式 但这并不简单。每次提交时 完整的快照,文件 里面 每次提交都是完全、完全、100%只读的。他们谁也不能 曾经 改变。这意味着每次提交都可以 分享 它的一些或所有文件与一些早期提交!

Git只需要确保每次我们运行 git提交 ,它 冻结 所有的文件内容,如果不是永远的话,至少只要这个新的承诺继续存在。所以每次提交中的文件都会被冻结他们也是 压缩的 变成一种特殊的git-only格式(对于文本文件非常有效,但对于像图像这样的二进制文件通常不太好)。这种压缩需要时间,有时需要很多时间,但它使存储库保持较小。

显然,冻结的git-only文件只对git本身有用,因此我们需要 现在的 提交取出,解冻,解压缩,并使有用这些有用的拷贝 工作树 ,我们工作的地方。

其他版本控制系统也做同样的事情。在假设的XYZ版本控制系统中,运行 xyz checkout commit 它从deep freeze warehouse中复制提交,解冻,解压缩,并将其存储在您的工作树中你做了一些工作,最后你跑了 xyz commit 是的。现在它会扫描整个工作树,重新压缩每个文件,冻结它,并检查仓库中是否已经有了冻结的版本,或者还需要将这个版本放入其中当你去喝咖啡或其他什么的时候,每一个步骤都需要几秒钟或几分钟。

git使用它的索引所做的是非常聪明的:索引是 中转区 ,介于deep freeze warehouse(包含提交的存储库)和有用表单(工作树中解冻的文件)之间。最初,它包含 相同的 文件在深度冻结它们已经解冻(有点),但仍然是特殊的git-only形式,并且它们与工作树中完全解冻的解压版本配对。

就像你一样 改变 工作树中的文件,或添加和/或删除文件,索引副本将与工作树不同步现在吉特可以 比较 索引副本到工作树副本,并告诉您 已更改但尚未上演 是的。

一旦你有了你想要的文件,你就可以运行 git add file 是的。这个 重新压缩文件 ,并将该副本放入索引中现在,索引副本(这是一个完整的副本,只是压缩的)与 工作树 复制,但与 坚信的 收到。

在任何时候,你都可以让Git比较 坚信的 ( HEAD )将每个文件的副本复制到 指数 副本:

git diff --cached

对于相同的文件,Git什么也不说对于不同的文件,Git列出了文件并显示了不同之处。

类似地,在任何时候,您都可以让git比较 指数 将每个文件的副本复制到 工作树 副本:

git diff

对于相同的文件,Git什么也不说对于不同的文件,Git列出了文件并显示了不同之处。

(注:增加 --name-status git diff 显示文件名,前缀为 M 对于修改过的,如果修改过的话Git使用 A 对于新添加的文件, D 对于已删除的文件,等等。文件是 删除 在索引中,只需将其从索引中完全删除文件是 补充 在索引中,如果它在索引中,但不在 头部 .)

这个 git status 命令运行 这两种比较 ,和 --名称状态 限制器对于不同于 头部 索引,这些是 准备提交 是的。对于索引和工作树不同的文件,它们是 不准备提交 .


形象地说:

   HEAD         index        work-tree
----------    ----------    ----------
README.txt    README.txt    README.txt
main.py       main.py       main.py

这个 头部 副本被冻结,因为它处于提交状态索引和工作树副本可以更改,但最初, 三个都匹配 . 更改工作树副本并使用 git add 复制回来 进入之内 索引,压缩并生成它(如果“en Git ing”是一个单词,则不是)如果你根本不想在索引中更改它,你可以使用 git reset (违约 --mixed 操作,或它在任何单个文件上的工作方式)将冻结的文件复制回索引中。

这也是为什么 Git提交 是如此之快,相比之下 XYZ提交

当你跑的时候 Git提交 ,git已经拥有了所有将以正确形式提交到新提交中的文件。它不必重新压缩所有的工作树文件,看看它们是否与冻结的提交版本匹配这个 指数 所有这些都准备好了:它所要做的就是冻结索引副本,如果这与之前的提交相同, 分享 上次提交的文件。

此外,由于索引“知道”哪些文件与工作树匹配,哪些不匹配, 还有关于存储库中内容的额外信息,这使得 git checkout 速度也更快假设你在 master 有大约3500个文件,而你 git签出 另一个分支大约有3300个文件都是完全相同的两次提交之间大约有200个文件不同(可能有一些是新的或删除的)。Git可以使用 指数 要知道它可能需要在 工作树 ,并且完全避免接触那些大约3300个文件。

因此,代替xyz系统扫描,可能接触3500个文件,git扫描,可能接触200个文件,节省了超过94%的工作。


这通常需要扫描工作树索引保存( 缓存 )数据 关于 工作树,以便加快速度。这就是为什么索引有时被称为 隐藏物 . 其他vcse,比如Mercurial,有一个工作树缓存(Mercurial称之为 dirstate公司 ,但与git的索引不同,它被正确地隐藏了:您不必知道它。