请记住,Git 存储库包含提交,而不是文件。(然后提交包含文件,但我们是逐个提交,而不是逐个文件。)
您存储的现有存储库docs/child
(作为.git
其中的目录)包含一系列提交。每个提交都有每个文件的完整快照。1 例如,这些提交中的文件是file-a
和file-b
。
您现在希望同一存储库添加新提交,其中提交中的文件名为child1/file-a
,child1/file-b
和child2/file-c
例如。这很容易做到:进入存储库工作树,创建child1
和child2
子目录,并且——<strong>为了方便2——使用git mv
重命名file-a
为 namechild1/file-a
并重命名file-b
为child1/file-b
. 创建新文件child2/file-c
,git add
在其上使用并运行git commit
,然后向现有存储库添加一个新提交;在这个新的提交中,内容存储在这些新名称下,而在所有现有提交中,快照将文件存储在它们的旧名称下。
请注意,Git 不存储目录:它只存储名称可能包含或不包含嵌入(正向)斜杠的文件。Git 将根据需要创建一个您的操作系统需要的目录,因为您的操作系统坚持不存在名为 的文件child1/file-a
:这是一个名为的目录,child1
其中包含一个名为file-a
. Git 坚持认为,不,这是一个名为child1/file-a
;的文件。Git 完全管理3 Git 的文件概念与您的操作系统之间的这种不匹配。
请记住:Git 存储库保存提交。 Git 不是关于文件或分支,而是关于提交。提交保存文件(我们需要完成工作),分支名称帮助我们(和 Git)找到我们想要的包含我们需要的文件的提交。但是在存储库级别,Git 是关于提交的。当您考虑存储在 Git 存储库中的内容时,请考虑提交。每个都包含所有文件的快照,以及一些元数据。
1提交中的文件被压缩和 Git 化,因此只有 Git 可以读取它们,而实际上没有任何东西可以写入它们。它们也被重复删除(在提交内和提交之间),因此每次提交每次都保存每个文件这一事实不会导致存储库膨胀到荒谬的大小(尽管一些二进制文件会破坏这个技巧,然后存储库会膨胀到荒谬的大小,这就是为什么在 Git 中存储大型二进制文件是不明智的)。
2就 Git 而言,删除某个名为的文件file-a
并创建一个包含相同内容的全新child1/file-a
文件与将现有文件重命名file-a
为child1/file-a
. 最终的提交只是保存内容;如果child1/file-a
新提交中的内容与旧提交中的内容逐字节匹配,则会对file-a
它们进行重复数据删除。尽管如此,在这里使用起来还是要方便得多git mv
,除非您已经使用过普通mv
的或您的操作系统使用的任何重命名或重组命令。如果是这样,请随意使用git rm
和/或git add
更新 Git 对文件名称和内容的看法。Git 不会关心你是如何从旧设置到新设置的:它包含的只是commits,这些提交只保存文件的快照(加上元数据,但元数据不包含重命名信息)。
3对于“完全”的某些值:Git 中的目录/文件冲突代码有偶尔出现小错误的历史。总而言之,考虑到 Git 的思维方式和操作系统之间的这种不匹配有多复杂,这非常好。尽管如此,在某些复杂的事后检测重命名跨提交导致文件移动到新目录的情况下,某些版本的 Git 比其他版本更好。