我如何知道GIT承诺是否已更改? [英] How do I know if a git commit has been changed?
问题描述
几个月前有人犯了什么罪。在那之后,已经完成了多个其他提交。是否可以通过修改或更改基数来查看是否有人更改了该特定承诺的内容?如果是,如何?
推荐答案
永不更改提交。请勿更改基本或git commit --amend
任何提交,因为这是不可能的。1
我告诉您的明确方式是给您散列ID,例如9b7cbb315923e61bb0c4297c701089f30e116750
。这是一个特定提交的真实名称:
$ git cat-file -p 9b7cbb315923e61bb0c4297c701089f30e116750 | sed 's/@/ /'
tree 4ba58c32960dcecc1fedede9c9362f5c10158f08
parent 77933f4449b8d6aa7529d627f3c7b55336f491db
author Junio C Hamano <gitster pobox.com> 1418845774 -0800
committer Junio C Hamano <gitster pobox.com> 1418845774 -0800
Git 2.2.1
Signed-off-by: Junio C Hamano <gitster pobox.com>
此名称将永久附加到此特定提交。不过,这肯定是一个笨拙而难听的名字。有一个更短、更漂亮、wieldy的名字不是很好吗?还有一个:我可以将您指向v2.2.1
:
$ git rev-parse v2.2.1^{commit}
9b7cbb315923e61bb0c4297c701089f30e116750
但实际上,v2.2.1
根本不是提交,它是标记。具体地说,它是一个标记名(在refs/tags/v2.2.1
或packed-refs
文件中的v2.2.1
下),指向注释标记对象,2而不是直接指向提交:
$ git rev-parse v2.2.1
7c56b20857837de401f79db236651a1bd886fbbb
标记对象内部有提交ID,外加一大堆额外的goop,包括"PGP签名":
$ git cat-file -p v2.2.1 | sed 's/@/ /'
object 9b7cbb315923e61bb0c4297c701089f30e116750
type commit
tag v2.2.1
tagger Junio C Hamano <gitster pobox.com> 1418851265 -0800
Git 2.2.1
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQIcBAABAgAGBQJUkfPBAAoJELC16IaWr+bLjfgP/iA78fk3NkTEROoyIVq6kPDH
pZAlm4ObsKXAdl6sFqWe7xFxGExHYzJ5L3qGXs3VM+9Z3iDe2WZN3WbK3aFtYqfU
AYRSTpnPzDf4L0vfyqiFS7//+LoeM2TogAV7SLdehMlodsL5HR6FiSz1zffSq8D0
Ci4XpGWHkqXLhfvUPC7foCgGpf7l38gsbJPbdkyKLK9/wtLSfkk45vK+wY6o3CCv
JKBFr468958fvw+j73nxiT+Vne7TeL1Bq1kCq9M65dAjOpFjZiD408NaF7jTcNcx
TMjdKoVlDNFHcUPMv9B5C308sRVUylmeUzb8XrQNji0+1NA5ivVgDfZsudWUtlTj
jo9xku0Np4IdXPwxJNlO5tC2rnof4gdD4jWPJj/DvellNKCDXuLuXDZSKZDI9GSr
OzLsad8uFX3MySPe+evIVF6qGS2KzI8PGNrohqWaPkX8cug22EW7lKJFpjYJb5gP
3nJUJvbsrMeyoH/GqxPzA5clqMGtsirnTiapMILNRmlC+3rzc0DkLw90BM6vKNOC
eDTOI9Xj1JS9qbD6fEkxVNrXRDz0TFbtpFbFTtKk4zfAc/jTOqE9fqpV7afoQfON
e1NwrjR5Kcts7ev23Y0G1WH3t2L0N2/q27kcjrulCEH1vtXlmaZFU6o+WKUVV7iH
/YQnjNUOgRxQ1zBGof7h
=yJ4Q
-----END PGP SIGNATURE-----
PGP签名让我们决定是否相信Junio C Hamano真的制作并签署了这个标签。它使用比SHA-1更强大的加密数字签名形式(这很好,因为SHA-1至少在理论上是可破解的),它还支持分布式验证和撤销签名的能力(而SHA-1本身不支持)。
归根结底,只有当我们信任和/或可以验证的人已经创建了这样的PGP签名标记,或者已经PGP签名提交时,这才能帮助我们。从理论上讲,对每个提交进行签名可能会更强一些,因为那时提交上直接有一个数字签名;但在实践中,签署标记要方便得多,也同样好,因为我们不经常去违反SHA-1(而且,至少使用当前的暴力方法,如果我们这样做了,它会留下明显的痕迹,尽管这远远超出了这个答案的范围,而且我也不能正确地描述--密码学不是我的专业)。
1如果可以break the SHA-1 hash,理论上是可能的。但是,如果您想出一个新的、不同的对象,但它仍然生成相同的散列,那么Git的行为方式意味着,如果您已经拥有了旧对象,那么您将永远不会使用这个新对象。此规则适用于所有Git对象(提交、树、带注释的标记和Blob),所有这些对象都按其哈希命名。
git rebase
和git commit --amend
要使看起来像更改了提交,所做的是创建现有提交的新副本,然后在之间更改名称。新提交具有新的、不同的散列,并且由于之后的(子孙)提交从字面上包含其直接祖先(父)提交的散列,所以"更改"一个提交的散列(即,将提交对象复制到新的、不同的提交对象)会迫使更改在其余提交中向下冒泡。然后,我们将现有(短、分支或标记)名称重新指向新链的顶端。
这就是为什么在给定我们认为可信任的端点的情况下,我们可以将该信任扩展到链或树中的每个先前对象。这方面的专业术语是Merkle tree。
2这使它成为Git所称的"带注释的标记":一个指向存储在Git存储库中的带注释的标记对象的标记名称(本身就是一个"轻量级标记"),而标记对象指向某个其他Git对象--通常是提交,但也可能是另一个标记,甚至是树或BLOB。然而,即使是"另一个标签"也有些罕见--在Git存储库中只有三个标签--另外两个几乎是闻所未闻的。
这篇关于我如何知道GIT承诺是否已更改?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!