checkout)似乎假定提交是工作树的快照或状态。rebase)似乎假定提交是更改:可以应用于工作树的一种运算符。那么,什么是Git提交呢?
Von*_*onC 10
虽然可以解释为两者,但 GitHub 工程团队很明确(2020 年 12 月):
\n\n\n提交是快照,而不是差异
\n
德里克·斯托利开始于
\n\n\n对象ID
\n了解 Git 对象最重要的部分是,Git 通过对象 ID(简称 OID)引用每个对象,为对象提供唯一的名称。
\n
\n我们将使用该git rev-parse <ref>命令来发现这些 OID。
\n每个对象本质上都是一个纯文本文件,我们可以使用git cat-file -p <oid>。
\n\nBlob(文件内容)
\n要发现当前版本的文件的 OID,请运行
\ngit rev-parse HEAD:<path>.
\n然后,使用git cat-file -p <oid>来查找其内容。
\n\n树(目录列表)
\n请注意,blob 包含文件内容,但不包含文件名!
\n
\n名称来自 Git\xe2\x80\x99s 目录表示:树。
\n树是路径条目的有序列表,与该路径上的对象类型、文件模式和 OID 配对。
\n子目录也表示为树,因此树可以指向其他树!
\n\n最后:
\n
\n\n提交:及时快照
\n提交是时间的快照。每次提交都包含一个指向其根树的指针,代表当时工作目录的状态。
\n\n
\n该提交具有与先前快照相对应的父提交列表。
\n没有父项的提交是根提交,有多个父项的提交是合并提交。
\n提交还包含描述快照的元数据,例如作者和提交者(包括姓名、电子邮件地址和日期)以及提交消息。
\n提交消息是提交作者向父级描述该提交目的的机会。尽管提交是快照,但我们经常在历史视图或 GitHub 上将提交视为差异。事实上,提交消息经常提到这个差异。
\n差异是通过比较提交及其父级的根树从快照数据动态生成的。Git 可以及时比较任意两个快照,而不仅仅是相邻的提交。
\n计算差异是启用
\ngit cherry-pick或git rebase的原因。
而且由于提交没有差异...
\n\n\nGit 不\xe2\x80\x99t 跟踪重命名。Git 内部没有数据结构来存储提交与其父提交之间发生重命名的记录。
\n
\n相反,Git 会尝试在动态差异计算期间检测重命名。此重命名检测分为两个阶段:精确重命名和编辑重命名。首次计算差异后,Git 检查该差异的内部模型以发现添加或删除了哪些路径。
\n
\n自然地,从一个位置移动到另一个位置的文件将显示为从第一个位置删除并在第二个位置添加。Git 尝试匹配这些添加和删除以创建一组推断的重命名。
简短的回答: 都。
中等答案: 这取决于。
长答案: Git有点像量子现象:两种观点都不能单独解释所有观察结果。继续阅读。
在内部,Git将使用这两种表示形式,(在概念上)取决于它在给定提交的存储空间和执行时间方面认为哪种表示效率更高。快照表示是主要的。
但是,从用户的角度来看,这取决于您的操作:
实际上,当您将提交视为工作树的快照时,某些命令根本没有任何意义。这是最明显的checkout,但也适用于
stash和至少一半的fetch和reset。
对于其他命令,当您尝试以这种方式考虑提交时,可能会产生疯狂。 对于那些其他命令,提交清楚地视为变化,
show,diff)apply,cherry-pick,pull)rebase)merge,cherry-pick)双重性1的副作用可能会震惊习惯于其他版本控制系统的Git新手。这是事实,Git似乎甚至没有承诺自己的承诺。
??
假设您已经创建了一个分支X,其中包含您想作为commit A和想到的东西B。但是master进步了一点,所以你rebaseX到master。
当你想到的A和B为变化,但master作为一个快照
(哎,粒子和波在一次实验),这并不是一个问题:只要应用更改A和B快照master。
这种想法很自然,您几乎不会注意到Git现在已经重写了您的提交,A并且B:它们现在具有不同的快照内容,因此具有不同的SHA-1 ID。在Git中,您认为作为开发人员的概念性承诺不是千篇一律的事情,而是一些因使用存储库而发生变化的可变对象。
相反,如果您将所有三个(A,B和master)视为快照,或者将所有三个(,和)视为更改,则大脑会受伤并且无处可去。
上面是非常简化的描述。在Git现实中,
并且不要对Pro Git本书的Git的第一个特征(在“ Git基础知识 ”部分中)是“快照,而不是差异”感到困惑。
Git 毕竟很复杂。
| 归档时间: |
|
| 查看次数: |
402 次 |
| 最近记录: |