Как узнать, был ли изменен коммит git?

Кто-то совершил что-то несколько месяцев назад. После этого было сделано несколько других коммитов. Можно ли увидеть, изменил ли кто-то содержимое этого определенного коммита, изменив или перебазировав его? Если да, то как?


person Stefan Schouten    schedule 09.11.2016    source источник
comment
Что вы хотите сделать с информацией?   -  person NiVeR    schedule 09.11.2016
comment
У меня такое ощущение, что произошел саботаж, и я хотел бы знать, так ли это.   -  person Stefan Schouten    schedule 09.11.2016
comment
Если у вас все еще есть клон того же репозитория в старом состоянии, просто сравните хэш-коды двух коммитов.   -  person choroba    schedule 09.11.2016
comment
К сожалению, нет. Однако хорошо знать, что хэш-код меняется после такого изменения.   -  person Stefan Schouten    schedule 09.11.2016
comment
Я думаю, что вы слишком поздно, чтобы обнаружить это. Если вы хотите следить за принудительными нажатиями (необходимыми после изменения коммитов), вы можете настроить что-то вроде описания здесь stackoverflow.com/a /17503259/904465   -  person wrdevos    schedule 09.11.2016
comment
Если у вас где-то есть журнал развертывания, в котором отслеживаются коммиты релизов, вы также можете найти что-то там.   -  person wrdevos    schedule 09.11.2016


Ответы (1)


Коммит в Git никогда не изменяется. Ни rebase, ни git commit --amend никогда не изменяют какой-либо коммит, так как это невозможно.1

Хитрость здесь заключается в определении «фиксации». Как узнать, какая фиксация какая? Если я скажу «коммит в репозитории Git для Git», там более 40 000 коммитов. Какой я имею в виду?

Однозначный и определенный способ сообщить вам — дать вам хэш-идентификатор, например, 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>

Это имя навсегда привязано к этому конкретному коммиту. Хотя, конечно, это громоздкое и уродливое имя. Было бы неплохо иметь более короткую, красивую, чтобы-быть-несуществующим-вором">владеть именем? И есть один: я могу указать вам на 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

Внутри объекта тега находится идентификатор коммита, а также куча дополнительной информации, включая «подпись 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Ну, теоретически это возможно, если вы можете сломать хэш SHA-1. То, как ведет себя Git, если вы придумали новый, другой объект, который, тем не менее, производит тот же самый хеш, означает, что вы никогда не подберете этот новый объект, если у вас уже есть старый. Это правило применяется ко всем объектам Git (фиксациям, деревьям, аннотированным тегам и BLOB-объектам), все из которых названы по их хэшам.

Что делают git rebase и git commit --amend, чтобы похоже, что они изменили коммиты, так это создают новые копии существующих коммитов, а затем перетасовывают имена. Новые коммиты имеют новые, разные хэши, а поскольку более поздний (потомковый) коммит буквально содержит хэш своего непосредственного предка (родительского) коммита, «изменение» хэша одного коммита (т. е. копирование объекта фиксации к новому, другому объекту фиксации) заставляет изменение всплывать через остальные коммиты. Затем мы повторно указываем существующее (короткое, ответвление или тег) имя на вершину новой цепочки.

Вот почему, учитывая конечную точку, которую мы считаем заслуживающей доверия, мы можем распространить это доверие на каждый предыдущий объект в цепочке или дереве. Техническим термином для этого является дерево Меркла.

2Это делает его тем, что Git называет "аннотированным тегом": имя тега (которое само по себе является "облегченным тегом"), указывающее на объект аннотированного тега, хранящийся в репозитории Git, с объект тега, указывающий на какой-либо другой объект Git — обычно коммит, но может быть и другой тег, или даже дерево, или большой двоичный объект. Однако даже «другой тег» встречается довольно редко — в репозитории Git их всего три, а о двух других практически ничего не слышно.

person torek    schedule 09.11.2016
comment
Удивительное объяснение. Спасибо. - person Stefan Schouten; 10.11.2016