我是Git和VCS的新手,我有一个问题要杀了我好几天了,如果Git不在乎git项目中的未跟踪文件,为什么它在未跟踪文件下显示git repo的状态?您发出git status命令?
工作树是否一定必须在我克隆的git项目中?工作树是一个虚拟的概念吗?
答案 0 :(得分:5)
Git关心未跟踪的文件。它们是Git存储库的新功能。这里的“未跟踪”是重要的status,例如modified
,deleted
等。您可能想要跟踪它们,谁知道。如果您不想在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 ,因此C
是B
的子代。同时,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.py
:D
存储的C
的哈希ID,因此{{1 }}指向D
。 C
是一个新的提交,也获得了一个新的唯一的哈希ID:Git某种程度上带来了一个丑陋的哈希ID(我们不必担心 how ,尤其是因为我们无法更改它:-))。
作为最后的技巧,D
将C
的哈希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