- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
是否可以将基于git行或diff的粒度增加到字/字母分辨率?每行多条语句或使用git编写纯文本都是值得的。
最佳答案
在根据评论重新阅读问题时,我想我明白了您的初衷,因此我将给出一个真实的答案(与Ismail Badawi's one line comment相对)。
Git作为简单的存储
Git有很多作品,其中一些作品比其他作品更好玩。在最低级别上,Git充当纯粹的基于内容的数据存储:具有键/值对的数据库,其中键本身只是(并且始终是)值的哈希值。也就是说,您无法选择密钥,在您提供值之后会为您提供密钥。
在这个非常低级的键/值数据存储区的正上方是一个类似的低级接口,其中存储的值具有类型。四种类型的对象是“斑点”,用于保存您的实际文件。 “树”,允许Git将真实,有用的文件名(例如file.py
或image.jpg
之类)映射到诸如b02f09aabdd957329476837f406588710142aebd
的不可读的哈希中; “提交”,从无法理解的哈希转换为有关提交的元数据,包括表示提交时文件的树;和带注释标签的对象,在这里我们可以忽略它们。
在这些之上,Git提供了参考。引用是一种既包含分支又包含标签的通用形式,包括更多的内容(远程跟踪分支,Git的“注释”,“隐藏”等)。这些将诸如master
之类的人类可读名称转换为不可读的哈希,Git然后使用该哈希获取提交,Git使用该提交获取树的哈希,Git使用该提交获取文件的哈希。
这是Git首先真正有用的级别。此时,Git可以存储所有任意数据:它不必由行甚至字组成;二进制格式(包括JPEG图像)在这里起作用。唯一的约束是,每个文件都必须哈希到其自己的唯一值,除非它与该文件的先前版本相同。 (举个例子,即使hash("a file\nwith two lines\n")
和hash("a file\nwith two lines\n")
中的file1.txt
匹配file2.txt
也可以;如果hash("a file\nwith two lines!\n")
的值相同,那是不可以的,因为我们只是添加了一个字节:第二行的感叹号。无论文件名如何,我们都必须为此文件的内容获取一个新的,不同的哈希值。)
当您进行新的提交时,Git只关心内容。具体来说,在git commit
时,Git根据文件的暂存版本(索引中的内容)打包所有跟踪文件的内容。文件名(包括带有子目录的路径名,如果需要的话)全部进入一堆树对象,文件内容本身进入blob对象,或在数据库中已有的blob对象重用。
(对于大多数提交来说,后者是很常见的,因为通常每个提交中有数十个,数百个甚至数万个文件,但是每个新提交都会使大多数文件与上一个提交保持不变。索引/分段-area对于未更改的文件Shakespeare-Sonnet-107.txt
具有与最近50次提交相同的blob哈希,因此我们在新提交中再次使用相同的blob。)
Git作为压缩方案
如果您要使用Git做的就是存储一堆文件树的一堆版本(换句话说,比源控制系统更多的是备份系统),那么在进行一些更改后,Git压缩文件的效率如何( s),变得有趣。
对象存储的基本形式完美地压缩了相同的文件:如上所述,无论有多少提交包含名为Shakespeare-Sonnet-107.txt
的文件,只要内容逐字节相同,我们就只需重复使用其ID的blob是该文件内容的哈希值。2
相同的基本存储方法(所谓的“松散对象”)使用Zlib压缩数据。这对于文本来说效果很好,在这种情况下,大文本文件可能会压缩到其原始大小的10%,但对二进制文件则效果不佳(压缩差异很大,我见过原始大小的1/3至1/2),并且对于已经压缩的任何东西都非常差。但是,对于文本文件和编程语言源文件,我们通常可以做得更好。
大多数版本控制系统都提供所谓的delta compression,其最简单的形式就是“区分旧的和新的,并将将一个更改为另一个的指令转换为文件的存储形式”。也就是说,我们在两个文件(通常是上一版本和下一个版本,以线性提交链)上运行string-to-string correction algorithm,而不是存储整个新文件,而是说“删除第3行,添加新的第47行”或其他内容。
Git至少以一种版本控制系统的独特方式执行增量压缩。它永远不会简单地说:“哦,好吧,这是blah.py
的新版本,我将针对最新的blah.py
进行压缩。”取而代之的是,它在游戏后期压缩对象,从单个对象(以及重新打包,其他已打包的对象,尽管规则变得复杂4)中制作“打包文件”,并通过各种试探法选择彼此打包的对象。
此特定代码基础上的算法是xdelta的修改版本。这适用于任意二进制数据,并且不依赖于换行符。
Git作为版本控制
但是,如果我们想使用Git进行真正的版本控制-毕竟它是专为它而设计的-我们必须更进一步。我们将有许多特定于版本控制的任务,但是有两个非常大的任务正在研究发生了什么变化,并合并来自不同开发路径的变化。
为了了解发生了什么变化,Git为我们提供了git diff
,git show
和git log
。所有这些都使用相同的基本差异引擎:给定两次提交,它匹配那些提交中的文件,然后匹配匹配文件中的行(啊哈,这里是“行”的所在!)。git diff
的输出,因此也是git show
和git log -p
的输出,都是非常面向行的。如果更改一行中的单词,它将显示更改后的整行。您可以为git diff
提供标记(因此,为git show
和git log
提供标记),在Git找到这些面向行的更改后,它们将指示它们显示行中哪些单词是实际上不同。从Git 2.9版开始,行内显示得到了进一步的改进:有一个new diff-highlight
script可以准确显示更改的内容。 (所有这些都在下面的面向行的diff之上工作:例如,当您忽略空格更改时,这会显示出来,在这里您将看到空的diff块,而不是根本没有diff。)
请注意,使用单词或字符显示对包中的提交blob(完整存储)或带修饰符的对象的内部格式没有影响(xdelta不面向行)。这些纯粹是显示选项。
三向合并
除了上述所有考虑因素之外,如果您要使用Git的合并功能,则不必;例如,一些使用Perforce的人使用p4merge而不是Git的内置合并-您需要知道它们是通过运行两个常规的,因此是面向行的git diff
开头的。
特别是,当您运行git merge <other>
时,Git会将<other>
解析为提交ID,然后在当前(HEAD
)提交与其他提交之间找到合并基础。此合并基础commit5作为起点。 Git进行两个比较:一个从基本到HEAD
,另一个从相同的基本到<other>
。然后,Git组合两个差异,将组合的更改应用于基本提交中的文件。
由于这些差异是面向行的,因此,如果您构建更改以使其与行相对应,则合并过程通常会更加顺利。因此,与git diff
本身一样,在这里您可能希望文件非常面向行。
如上所述,尽管编写合并脚本有点棘手,但您不必使用Git的内部合并,并且那些使用外部合并的人总是在various rough edges上绊脚石。
1这意味着只有一个索引/临时区域。实际上,有一个主索引,通常只看到一个索引,但是有很多极端的情况,例如git commit -a
,其中的其他索引会临时存在,并弄乱了该模型。
2技术上,ID为hash("blob %d\0%s" % (len(bytes), bytes))
,以Python形式书写。也就是说,文件内容的哈希ID以单词“ blob”,一个空格,内容长度的十进制表示形式,ASCII NUL字节以及最后的实际内容开头。这样可以保证您不能仅仅通过编写一个内容与某些现有提交3相同的文件来破坏Git。这里的问题是,可以测试每个对象的类型,而不是从上下文中假设其类型,因此,如果提交和常规文件具有相同的哈希,这将迫使单个基础Git存储库对象同时具有类型commit和键入blob,这是不允许的。
3例如,您可以使用git rev-parse HEAD
查看当前提交的内容,其ID是git cat-file -p HEAD
打印的内容。将git cat-file
的输出写入常规文件,然后将此新文件写入git add
,您将获得与git rev-parse HEAD
所显示内容不匹配的新ID,这都是因为内部每个对象都以其类型名称作为前缀,再加上该空间大小和NUL序列。
4要使它们沸腾很多,一个包对象只能引用同一包内的其他对象,所谓的“瘦”包除外,后者用于在网络上进行传输。
5假设有一个合并基础。如果有多个,则默认递归策略通过合并基于合并的候选对象构造一个。通常,只有一个合并基础,我们不必为此担心。有时根本没有合并基础。在这种情况下,Git 2.9已将默认值更改为抱怨并失败,而不是从空树中合并。
关于git - Git粒度—解决一行中的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37906514/
@Cacheable在同一类中方法调用无效 上述图片中,同一个类中genLiveBullets()方法调用同类中的queryLiveByRoom()方法,这样即便标识了Cacheable标签,
目录 @Transaction注解导致动态切换更改数据库失效 使用场景 遇到问题 解决 @Transaction
@RequestBody不能class类型匹配 在首次第一次尝试使用@RequestBody注解 开始加载字符串使用post提交(貌似只能post),加Json数据格式传输的时候,
目录 @Autowired注入static接口问题 @Autowired自动注入普通service很方便 但是如果注入static修饰的serv
目录 @RequestBody部分属性丢失 问题描述 JavaBean实现 Controller实现
目录 解决@PathVariable参数接收不完整的问题 今天遇到的问题是: 解决办法: @PathVariable接受的参
这几天在项目里面发现我使用@Transactional注解事务之后,抛了异常居然不回滚。后来终于找到了原因。 如果你也出现了这种情况,可以从下面开始排查。 1、特性 先来了解一下@Trans
概述: ? 1
场景: 在处理定时任务时,由于这几个方法都是静态方法,在aop的切面中使用@Around注解,进行监控方法调用是否有异常。 发现aop没有生效。 代码如下:
最近做项目的时候 用户提出要上传大图片 一张图片有可能十几兆 本来用的第三方的上传控件 有限制图片上传大小的设置 以前设置的是2M&nb
我已经实现了这个SCIM reference code在我们的应用程序中。 我实现的代码确实通过了此postman link中存在的所有用户测试集合。 。我的 SCIM Api 也被 Azure 接受
我一直对“然后”不被等待的行为感到困扰,我明白其原因。然而,我仍然需要绕过它。这是我的用例。 doWork(family) { return doWork1(family)
我正在尝试查找 channel 中的消息是否仍然存在,但是,我不确定如何解决 promise ,查看其他答案和文档,我可以看到它可能是通过函数实现的,但我是不完全确定如何去做。我希望能在这方面获得一些
我有以下情况: 同一工作区中的 2 个 Eclipse 项目:Apa 和 Bepa(为简洁起见,使用化名)。 Apa 项目引用(包括)Bepa 项目。 我在 Bepa 有一个类 X,具有公共(publ
这个问题已经有答案了: Why am I getting a NoClassDefFoundError in Java? (31 个回答) 已关闭 6 年前。 我正在努力学习 spring。所以我输入
我正在写一个小游戏,屏幕上有许多圆圈在移动。 我在两个线程中管理圈子,如下所示: public void run() { int stepCount = 0; int dx;
我在使用 Sympy 求解方程时遇到问题。当我运行代码时,例如: 打印(校正(10)) 我希望它打印一个数字 f。相反,它给我错误:执行中止。 def correction(r): from
好吧,我制作的每个页面都有这个问题。我不确定我做错了什么,但我所有的页面都不适用于所有分辨率。可能是因为我使用的是宽屏?大声笑我不确定,但在小于宽屏分辨率的情况下,它永远不会看起来正确。它的某些部分你
我正在尝试像这样进行一个非常简单的文化 srting 检查 if(culture.ToUpper() == "ES-ES" || "IT-IT") { //do something } else
Closed. This question is off-topic. It is not currently accepting answers. Learn more。 想改进这个问题吗?Upda
我是一名优秀的程序员,十分优秀!