Git未跟踪的文件和“工作目录”

时间:2018-09-17 05:48:59

标签: git working-directory

我是Git和VCS的新手,我有一个问题要杀了我好几天了,如果Git不在乎git项目中的未跟踪文件,为什么它在未跟踪文件下显示git repo的状态?您发出git status命令?

工作树是否一定必须在我克隆的git项目中?工作树是一个虚拟的概念吗?

enter image description here

3 个答案:

答案 0 :(得分:5)

Git关心未跟踪的文件。它们是Git存储库的新功能。这里的“未跟踪”是重要的status,例如modifieddeleted等。您可能想要跟踪它们,谁知道。如果您不想在git status中看到它们,而必须保留它们,gitignore会有所帮助。而且,Github推荐.gitignore files用于许多流行的操作系统,环境和语言。

在大多数情况下,工作树位于存储库中,因为它自然且方便。但是一个.git可以有multiple working trees。这样,多余的工作树就在存储库之外。这是关于git worktree的简短摘要article

答案 1 :(得分:2)

  

工作树是否一定必须在我克隆的git项目中?

正如ElpieKay回答的那样,不是,没有,但这是正常的。每个Git存储库都附带一个-好吧,每个 non-bare Git存储库。 (您不必担心“裸仓库”,但是它只是一个没有工作树的仓库,因此您不能使用它来做任何工作。这看起来很奇怪,而且很奇怪。这就是方法)像GitHub这样的地方存储您的存储库。)

  

工作树是一个虚拟的概念吗?

我不确定您这句话的意思。这是一个版本控制概念,尤其是在现代版本控制系统中。这些通常将事情分为提交/签入的文件和您当前正在使用的文件。提交的文件将进入存储库,在该存储库中它们将永久存在于冻结的快照中,而正在工作的文件则可以在其中使用和更改它们。工作表单文件进入工作树或工作树中(在使用或不使用连字符的情况下,如何拼写此代码有一些变体;可以使用任意一种)。

尤其是Git,您还需要了解另一件事,那就是Git分别称为 index staging区域的东西缓存。这些都是一件事-一个概念-它只有三个名称。将Git与Mercurial(另一个相当现代且非常相似的VCS)以及其他VCS进行比较很有用:Mercurial和其他VCS具有存储库和工作树(或工作树),但是没有没有索引。因此,Git是不寻常的。这是对此的思考方式:

  • 已提交 的文件位于冻结(只读)快照中。为了使它们占用更少的空间,Git以特殊的,仅Git的格式存储它们。这种格式是压缩的,有时压缩得很厉害,其他程序几乎无法读取。

  • 要处理的文件进入工作树,您可以在其中进行处理。在这里,它们具有普通的,未压缩的形式,当然您可以覆盖它们。您还在工作树中存储了Git不会冻结到快照中的文件:这些是未跟踪的文件。

  • Git的 index 是一种特殊的中介,介于提交和工作树之间。索引中的文件已被压缩为仅Git格式,但尚未提交(冻结)。他们已经100%准备好提交,但尚未实际提交。

运行git commit只是冻结索引现在中的所有文件。这就是git commit如此之快的原因:如果您使用了其他VCS,那么在运行它们的“ commit”动词时,它们中的许多都会非常慢,因为它们花费大量时间来扫描目录,压缩文件,获取它们。准备被冻结。在某些VCS中,您实际上可以在等待提交时去喝咖啡。 :-)

如果您认为索引是 Git将提交的内容,如果您现在运行git commit ,则对Git的索引有很好的了解。这自然会导致正确定义跟踪文件未跟踪文件: 跟踪文件现在位于索引中,这样它将在下一次提交中; 未跟踪的文件是当前不在索引中但在工作树中的文件。 (如果文件不在索引或工作树的 中,则根本不是文件。)


上面还有其他重要的事情:请注意,我们还没有提到 branch 一词。这是因为Git对 commits 的关注远大于对分支的关注。这些提交-您使用git commit用Git制作的冻结快照-组成您的分支,因此分支通过具有提交而出现。这使得提交成为最重要的部分:在Git中,分支{em> names master一样,主要用于查找提交。

Git与这里的许多其他VCS也有很大不同。在其他VCS中,分支是非常重要的,因为提交存在是因为它们在分支中。因此,依赖分支进行提交。在Git中,这是另一种方式:首先存在提交,然后才添加分支名称。 Git让我们移动名称,而无需更改任何提交!

任何提交的真实名称是其较大的丑陋哈希ID。运行git log时,将打印出这些哈希ID。提交的哈希ID永远不会更改,因为那是提交的真实名称。 分支名称只是我们在提交时坚持的易于理解的名称,然后在工作时,我们将人类可读的名称​​移动 latest 一。因此,如果我们从一个只有三个提交的小型存储库开始,我们可以使用字母而不是哈希ID来绘制它:

A  <-B  <-C   <--master

名称 master会记住最新提交的哈希ID,请在此处提交C。提交C会记住提交B的ID。 Git将B称为C parent ,因此CB的子代。同时,B会记住其父A的ID。 A是我们的第一个提交,因此它没有父项。我们说名称master 指向 C,而C指向B,后者指向A(和{{ 1}}点无处。

当我们检出A时,实际上是在检出提交master。这会将C的所有冻结快照的副本放入索引(仅Git形式,但现在我们可以覆盖文件) 和工作树(通常形成)。然后,我们在工作树中进行一些工作,完成工作后,我们运行例如:

C

这会将每个文件的工作树版本复制到索引中。如果已经有索引版本git add README.txt newfile.py ,它将替换索引版本。如果README.txt确实是新的,则将其复制到索引中,因此现在它已被跟踪-并且,除了被压缩为仅Git形式外,其newfile.py索引现在与工作树中的索引匹配。

然后我们运行:

newfile.py

(在收集日志消息等之后)根据索引中的内容创建新快照git commit :与D中相同的旧existing_file.txt,更新后的{ {1}},以及新文件C。新的提交README.txt以其已签出的提交作为其父提交,即newfile.pyD存储的C的哈希ID,因此{{1 }}指向DC是一个新的提交,也获得了一个新的唯一的哈希ID:Git某种程度上带来了一个丑陋的哈希ID(我们不必担心 how ,尤其是因为我们无法更改它:-))。

作为最后的技巧,DC的哈希ID写入名称D

git commit

因此,D现在像往常一样指向最新提交。而且,由于Git只是从索引中master到,因此索引和A <-B <-C <-D <--master 是匹配的。只要您从所有工作树文件中更新了所有索引文件,索引和工作树匹配:一切都匹配,并且master说“工作树干净”。 / p>

答案 2 :(得分:0)

如果创建新文件,最初它不会添加到任何分支。因此,它将显示为未跟踪的文件。

如果要添加所有这些更改,请使用

git add -A 

git add path/to/fileName

如果您想删除所有这些更改手段,

git clean -fd