在开始之前,这里有一些有用的背景知识需要了解:
-
仅限Git商店
,而不是文件夹。
-
每个Git commit存储一个
完整快照
属于
全部的
坚信的
未跟踪的文件
进来吧。
-
指数
或者你的
中转区
隐藏物
. 这三个名字都差不多。)
提交
. Git实际上就是提交。每个提交都是数字形式的,但不是一个简单的顺序“提交1,提交2,…”方式。相反,每个提交都得到一个唯一的
,哈希ID完全随机,与以前的提交无关。这些散列ID是由字母和数字组成的难看的大字符串,如
83232e38648b51abbcbdb56c94632b6906cc85a6
git log
吐出来。
自从
每一个
每一个
提交,对于Git来说,重要的是以一种不会立即耗尽整个磁盘驱动器的方式保存它们。所以保存的文件被压缩,而且,
共享
跨越不同的承诺。Git可以做到这一点,因为它使用一种特殊的、仅限Git的、冻干格式来存储文件。此表单中的文件
,但可以共享。这意味着
不能更改现有提交
.
存储库中的提交或多或少是永久存档的。
1个
认为承诺是永久的
是)并且是不变的。他们
是
1个
可以删除提交,但有点困难,Git通常不会立即执行,即使您
一个承诺已经没有了,现在找不到,可能还在里面。
现在,这对于归档来说是很好的,但是这些只读的冻干文件对于实际的
工作
工作树
. 那只是你工作的地方。
在工作树中,Git从一些commit中提取冻干的文件,对它们进行再水化,使它们具有正常的日常形式。现在您可以查看和处理这些文件。你只需选择一个承诺,即
最后的
承诺一些
分支
给我那个承诺
,Git就这么做了。它查找冻结提交并枚举其中的所有文件:
-
main-folder/sub1/file1
:
吉特说,
这个工作树没有
main-folder
,我们来做一个。它没有
sub1
在
主文件夹
主文件夹/sub1/file1
.
-
main-folder/sub1/file2
:
吉特说,
已经有一个主文件夹/sub1,我可以创建新文件
file2
在里面。
文件夹
,如提交中所列,它必须重新构造。完成后,如果工作树
是
文件夹
已经储存了,但没有必要储存。
如果你现在从
那个
提交到另一个提交,Git将
去除
它为该提交创建的所有文件,并用其他不同提交的文件替换它们。如果它移除
全部的
文件来自
main-folder/sub1
主文件夹/sub1
. 如果最后把里面的东西都拿走了
,它也会删除。然后从提交文件中提取所有文件,
创建
任何需要的目录/文件夹。
a123456...
承诺
b789abc...
,两次提交中99%的文件是
,好吧,毕竟没必要在工作树上和他们混在一起,对吧?在这种特殊的形式下
git checkout
,Git在切换提交之前添加安全检查:
如果文件是“干净的”,则可以安全地删除或替换它。如果它是“脏的”,如果您在Git提取它之后更改了它,并且您可能希望保留您的更改,那么切换会使clobberGit对此发出警告,并且在默认情况下拒绝切换提交。
在这个过程中有一个巨大的鸣音皱纹。通读以上,你会想:
但是Git有第三个实体
之间
与提交本身一样,索引基本上是不可见的。实际上只是一个普通的文件,
.git/index
在大多数情况下,这最终会变得更复杂,但它开始只是一个普通的文件。文件中的内容实质上是您提取的提交的副本所有冻结的文件,仅使用散列ID(如提交散列ID)来标识它们。不过,与提交中实际冻结的文件不同,索引中的副本
被改变。
这就是
git add
它会把文件冻干然后粘起来
索引中的版本。如果文件
不是
在以前的索引中,现在是。如果它
在之前的索引中,这将踢出以前的版本。
无论哪种情况,新的冻干文件都可以提交。
当你跑的时候
git commit
,Git只是将所有准备就绪的文件从索引打包到新的提交中。那是
git提交
path/to/file1
有
这些
path/to/file2
有
冷冻干燥内容物等。但不管怎样,文件的存在
在里面
跟踪
. 一个
文件在索引中,所以
一个
文件只是工作树中的任何文件,而不是索引中的任何文件。
自从
git提交
指数
跟踪
提交文件。
这里棘手的部分是,将一个新文件放入索引实际上是冻结干燥文件并将其存储在
存储库
,如果新内容确实是新的,则创建新的哈希ID;如果冻结的内容与任何现有文件匹配,则共享某些现有哈希ID。现在,这个被认为是新文件的文件被简化为一个散列ID,它与旧文件所占的索引位置相同!
这样一来,答案就很简单了
进行新的提交,在该提交中存储
只有
某些文件,只要设置好
里面只有那些文件。要做到这一点,
去除
从索引中删除所有完全不需要的文件,这也将删除工作树副本:
git rm ...
相对于工作树顶部的路径
,您将希望保存所有要保存的文件。最简单的方法就是
它们都在工作树上
和
git mv main-folder/sub1 sub1
它将(在本例中,通过重命名)创建
第1款
如果需要,请将文件夹重命名为
索引中的文件记住
git mv
主文件夹/sub1/file1
等有路可走
sub1/file1
重命名
git rm
命令,然后拖动工作树文件。
(当
就地重命名文件夹,也可以重命名任何
里面的文件。因为Git的其他部分对未跟踪的文件并不感兴趣,稍后
git签出
姓名
提交必须存储全名和散列ID,并且
不能轻易在这里分享,因为它们是不同的
但实际内容与其他提交中具有不同名称的文件共享。
注意,当您在这个提交之间来回切换时
sub1/文件1
键入名称,以执行任何具有
主文件夹/sub1/file1
键入名称,Git可能不得不在工作树上使劲搅拌,删除所有
先命名,然后创建新的空
主文件夹
和
主文件夹/sub1
要保存的目录(最后相同!)以前的文件
sub1/文件1
重命名
工作树中的那些文件,Git可能会这样做,但是Git通常以一种简单而愚蠢的方式开始,就是删除并重新创建它们。这将显示在操作系统级的文件时间戳中:如果Git删除一个文件并重新创建它,它将“现在”作为其磁盘上的工作树文件时间戳。
三
在commits内部而不是indexGit中,可以直接返回到树结构的命名方案。所以如果
第1款
在这个新提交的顶层中,与
那是在
主文件夹/sub1
在其他一些提交中,Git实际上将共享底层
对象
新提交的根目录树的子目录树。当然,根树的名称会有所不同
第1款
作为它的一个子树,而不是名字
作为它的一个子树。但所有这些都只是实现细节:没有一个显示在索引和工作树中。