有人能告诉我头,工作树和索引的区别吗?
据我所知,它们都是不同分支的名称。我的假设正确吗?
编辑
我找到这个了
A single git repository can track an arbitrary number of branches, but your working tree is associated with just one of them (the"current" or"checked out" branch), and HEAD points to that branch.
号
这是否意味着头部和工作树总是相同的?
- 关于你的编辑:绝对不是。HEAD是当前分支尖端的提交。如果您刚刚签出了分支,即没有修改过的文件,那么它的内容与工作树相匹配。一旦你修改了任何东西,它就不再匹配了。
- 我想你必须读这个:像-a-git.net一样思考
- 我也会在这个列表中添加一个Staging Area。什么是HEAD、Working Tree、Index和Staging Area。
- @jefromi's的最后一句话会更清楚,因为:>一旦修改任何内容,工作树就不再与head commit匹配。
- 对于将来阅读这篇文章的人来说,真正理解其中一些答案的最好方法就是看到、感受和直观地概念化正在发生的事情:这是学习Git的最好工具:仅限于ei.github.io/explain-git-with-d3/fetchrebase
- @绿色:集结区和索引是一样的。(见下面批准的答案)
- @所有链接都不起作用。
- @Dreval尝试点击刷新按钮,图形应该被加载。
关于这些主题的其他一些很好的参考资料:
氧化镁
I use the index as a checkpoint.
When I'm about to make a change that might go awry — when I want to explore some direction that I'm not sure if I can follow through on or even whether it's a good idea, such as a conceptually demanding refactoring or changing a representation type — I checkpoint my work into the index.
If this is the first change I've made since my last commit, then I can use the local repository as a checkpoint, but often I've got one conceptual change that I'm implementing as a set of little steps. I want to checkpoint after each step, but save the commit until I've gotten back to working, tested code.
Notes:
the workspace is the directory tree of (source) files that you see and edit.
The index is a single, large, binary file in /.git/index, which lists all files in the current branch, their sha1 checksums, time stamps and the file name -- it is not another directory with a copy of files in it.
The local repository is a hidden directory (.git) including an objects directory containing all versions of every file in the repo (local branches and copies of remote branches) as a compressed"blob" file.
Don't think of the four 'disks' represented in the image above as separate copies of the repo files.
号
氧化镁
They are basically named references for Git commits. There are two major types of refs: tags and heads.
-
Tags are fixed references that mark a specific point in history, for example v2.6.29.
-
On the contrary, heads are always moved to reflect the current position of project development.
号
氧化镁
(注:正如Timo Huovinen所评论的那样,这些箭头不是提交所指向的,而是工作流顺序,基本上显示箭头为1 -> 2 -> 3 -> 4,其中1是第一个提交,4是最后一个提交)
Now we know what is happening in the project.
But to know what is happening right here, right now there is a special reference called HEAD. It serves two major purposes:
-
it tells Git which commit to take files from when you checkout, and
-
it tells Git where to put new commits when you commit.
When you run git checkout ref it points HEAD to the ref you’ve designated and extracts files from it. When you run git commit it creates a new commit object, which becomes a child of current HEAD. Normally HEAD points to one of the heads, so everything works out just fine.
号
氧化镁
- 在读了很多次关于Git的文章后,我从来没有完全理解它,我真的很沮丧,我想用f字,但我在社区!你提到过头部,但在上面的图片中,总是有一个头部,R是剩下的头。通常头部指向其中一个头部,所以一切正常。"我请求你解释一下,你的陈述。
- @necktwi head是您正在使用的当前提交(stackoverflow.com/a/964927/6309)。它通常是一个"分支头"(分支引用的一个提交,表示所述分支的尖端)。但您可以签出(并处理)任何提交。如果签出的提交不是(分支)头之一,则处于"分离头"模式:stackoverflow.com/a/3965714/6309
- 这些箭不是朝后的吗?每个提交都应该指向它之前的提交吗?我觉得这样更正确
- @我同意,但这就是我5年前发现这些照片的方式(hades.name/blog/2010/01/28/…)
- 这些箭头不是提交指向的,而是工作流顺序,基本上显示箭头为1 -> 2 -> 3 -> 4,其中1是第一次提交,4是最后一次提交。
- @Timohuovinen非常真实。我已经把你的评论包括在回答中,以提高可见度。
- 关于索引,我认为最有用的一句话是"索引只是临时区域的另一个名称",如@ashraf alam所说。我觉得在讨论的大部分时间里,它被称为临时区域,这就是为什么我没有自动建立连接,因为它和索引是一样的。
- @皮特,我同意。有关缓存和索引之间差异的更多信息,请参阅我的其他答案stackoverflow.com/a/6718135/6309
- 对我来说,把索引看作是集结地是很麻烦的。git rm的手册页说明它用于"从工作树和索引中删除文件"。在这种情况下,索引不是准备提交的,而是存储库中所有文件的索引。你怎么认为?
- 很好的答案,但是有些链接已经死了;是时候回顾和刷新了。:)
- @古柯德,谢谢。我已经审阅并刷新了链接。
- 我认为在local repository和index之间加上git diff --cached也是值得的。
- 在image git数据传输命令中,checkout和checkout HEAD不适用于我。我认为他们错了。其他事情都可以。为了从"阶段性"状态恢复到"非阶段性"状态,使用了git reset HEAD,而不是checkout。
- @但是,对于一个文件来说,git checkout HEAD -- afile和git reset afile是相似的,不是吗?两者都将从本地repo中恢复文件,删除任何已分段的内容:stackoverflow.com/a/45018564/6309、stackoverflow.com/a/33849726/6309。而简单的签出(没有头部)确实会删除本地更改,恢复索引内容(意味着恢复索引中当前阶段的内容)
- 那么"工作区"、"工作目录"和"工作树"都是一样的对吗?
- @Alexandermills是的。工作树用于git-scm.com/docs/git-worktree手册页。工作区是一个更通用的术语。
- git checkout和git checkout HEAD做了同样的事情,我认为这部分图像是不正确的。在链接之后,它注意到末尾有一个.,使git checkout .成为正确的命令。
- @尼可拉平酮是的。我相信在这两个箭头前面的"revert"标签表明git checkout--。确实更有意义。stackoverflow.com/a/38165714/6309也是有指导意义的。
- @nic尤其是:"记住Git有一个叫做索引或临时区域(有时也叫缓存)的东西:当你Git添加文件时,你将它们复制到索引中,当你Git提交时,Git会获取索引内容的快照,这就变成了新的提交。这里的一个含义,我认为Git文档所强调的不够,就是索引总是包含下一次提交中的每个文件。(在提交之后,索引并不是"空的",正如一些命令和文档所暗示的那样:相反,它充满了您刚刚提交的所有内容。)
头(当前分支或当前分支上的最后提交状态)、索引(aka)之间的差异。临时区域)和工作树(签出中的文件状态)在Scott Chacon(Creative Commons Licensed)的Pro Git Book"1.3 Git基础知识"一章的"三个状态"部分中进行了描述。
以下是本章中的图示:
。
在上图中,"工作目录"与"工作树"相同,"临时区域"是git"index"的备用名称,head指向当前签出的分支,tip指向"git目录(存储库)"中的最后一次提交。
注意,git commit -a将分阶段进行更改,并在一个步骤中提交。
- "一幅画胜过千言万语"。谢谢杰克……谢谢你的链接。
- 注:目前,working tree比working directory更受欢迎。请参见github.com/git/git/commit/…
- 此图片不完全准确,因为临时区域包含在一个名为"index"的文件中,而该索引文件恰好位于.git目录的根目录中。因此,如果您将repo定义为.git目录,那么从技术上讲,临时区域在repo中。第三列最好标记为"head的根目录树对象",以指示签出的文件来自一个提交对象,并且提交会将一个新的目录树写入一个提交对象——两个提交对象都由head指向。
- @Jazimov你可能是对的,但正如他所写,他从著名的pro-git图书中拍摄了这张照片,并提供了一个链接。因此,如果图片可以改进,甚至是错误的话,应该有人告诉这本书的作者…总的来说,我愿意这样做,但老实说,我还是个Git初学者,还没有理解你说的话,所以在这种情况下我绝对是个错误的人。
- @比那勒斯:像这样大规模复制图片的危险在于,它传播了一位作者/一本书所作的"误传"。我认为这是一个字面解释与功能解释的案例:从字面意义上讲,如果您将repo定义为.git文件夹下的所有内容,那么索引实际上包含在repo中。然而,从功能上讲,该指数有助于Git在回购中维持DAG,可以认为它是外部的。
- Jonathan Waldman在2017年8月的Git Internals的msdn文章中详细解释了索引:msdn.microsoft.com/en-us/magazine/mt493250.aspx
- @贾兹莫夫,你是对的,但最终还是有一个误会。我不想回答你对技术水平的评论(我无论如何都不能回答,因为我还是一个Git初学者)。相反,我只是想说,你(或其他人)可能应该把这个错误引起作者的注意(除了在这里纠正它)。因为pro-git书籍是任何想学习git的人都会阅读的第一件事,而且由于这个图像将继续大规模复制,让git-pro作者更正它将为未来的许多人服务。
- @我认为这是一个语义问题,而不是一个"错误"。该图似乎表明".git directory"和"repo"是同义的,并且临时区域是独立的。我希望看到一个跨越临时区域和repo的".git directory"标签——但我也希望repo标签更改为"dag"。这些变化可能会压倒初学者,但它们更准确地描述了实际情况。让我们希望持怀疑态度的读者能够在这里进行讨论!:)谢谢你的评论和想法——你的想法是正确的。
- 这个答案应该被认为是最好的答案。
您的工作树实际上是您当前正在处理的文件中的内容。
HEAD是指向上次签出的分支或提交的指针,如果执行了新提交,则该分支或提交将成为新提交的父级。例如,如果您在master分支上,那么HEAD将指向master,当您提交时,新提交将是master所指向的修订的后代,并且master将更新为指向新提交。
索引是准备新提交的临时区域。从本质上讲,索引的内容就是新提交的内容(不过,如果您执行git commit -a,这将在提交之前自动将Git知道的所有更改添加到索引中,因此它将提交工作树的当前内容)。git add将工作树中的文件添加或更新到索引中。
- 谢谢你的解释,布莱恩。因此,工作树包含所有未提交的更改。如果我使用git commit-a提交更改,那么在那个特定的时间,我的工作树和索引将是相同的。当我推动中央回购时,这三个都是一样的。我说的对吗?
- @维诺德差不多。您的工作树中可以有Git不知道的文件,并且这些文件不会与git commit -a一起提交(您需要将它们与git add一起添加),因此您的工作树可能有索引、本地回购或远程回购没有的额外文件。
- @vinod:工作树和索引可以在不提交的情况下变为相同的(git add从工作树更新索引,git checkoutupdates working tree from index)。HEAD指的是最新的提交,所以当您提交时,您正在将HEAD更新为与索引匹配的新提交。推和它没有太多关系——它使远程分支与本地回购中的分支匹配。
工作树
您的工作树是您当前正在处理的文件。
Git指数
git"index"是放置要提交到git存储库的文件的位置。
索引也称为缓存、目录缓存、当前目录缓存、临时区域、临时文件。
在将文件"提交"(签入)到Git存储库之前,需要首先将文件放在Git"索引"中。
索引不是工作目录:您可以键入一个命令,如git status,git将告诉您工作目录中的哪些文件已添加到git索引中(例如,使用git add filename命令)。
索引不是git存储库:git索引中的文件是git在使用git commit命令时将提交给git存储库的文件。
- 请注意,Git2.5将带来多个工作树(stackoverflow.com/a/30185564/6309)。+ 1
- 我不确定"索引不是工作目录"是否100%正确。它应该是"索引不是工作目录,但它包含了整个工作目录+下一步要提交的更改"。证据?转到Git存储库,reset --hard HEAD以确保您的索引==您的工作树。an then:mkdir history && git checkout-index --prefix history/ -a结果是在history/目录中复制了整个工作树。ergo git index>=git工作目录
- 索引不是工作目录,不必包括工作目录。索引只是git存储库中的一个文件,用于存储您想要提交的信息。
- "index"保存工作树内容的快照,正是这个快照作为下一次提交的内容。因此,在对工作目录进行任何更改之后,在运行commit命令之前,必须使用add命令将任何新的或修改过的文件添加到索引中"(git scm.com/docs/git add)
- 所有分支是否都有一个索引区域来存储下一次提交的内容?我在索引中添加了一个文件,然后移动到其他分支,比如master。我甚至在转移到另一个分支并提交更改之后,也看到了相同的文件在该分支中添加了这些文件。
- @Adamkurkiewicz:如果你先用echo untracked-data > untracked-file,在git reset --HARD和git checkout-index步骤之前或之后,证明失败。您会发现未跟踪的文件不在history目录中。您也可以单独修改索引和工作树,尽管在不首先接触工作树的情况下修改索引很困难(需要使用git update-index --index-info)。
- @托雷克,你说得对,一个很好的反例。