O que aconteceria se dois Git commits tivessem o mesmo hash SHA-1?
- O Compromisso teria sucesso?
- mais tarde poderia ser verificado como um cabeça separada?
- seria possível um compromisso posterior?
2 answers
ComoTarek mencionanos comentários , o git pensa em tudo como "objectos", cada um com o seu próprio SHA1.
(imagem de Git Internals-Git References capítulo do ProGit Book v2)
Embora o commit provavelmente não tenha sucesso (há um par de controlos git-commit-tree.c
), Você também tem que considerar o caso em que dois commits com o mesmo SHA1 (e de alguma forma conteúdo diferente) são criados em repos A E B... e o repo A Vai buscar o repo B!
Commit 8685da4 (March 2007, git 1.5.1) took care of that, and the fetch would fail.
Commit 0e8189e (Oct. 2008, git 1.6.1) refere que, com índice V2:
As probabilidades de uma referência SHA1 ser corrompida para que realmente corresponda o SHA1 de outro objeto com o mesmo tamanho (o cabeçalho delta armazena o tamanho esperado do objeto de base para aplicar) são praticamente zero.
Ele ainda implementa uma verificação de CRC de objetos embalados ao desempacotar objetos.
O código Git abaixo mencionado é o finalize_object_file()
function , and a blame shows no recent modification, most of the code dating back from the very beginning of Git (2005): no new commit is created.
De acordo com o código-fonte (presente no git v2.17), se um commit levar a um sha1 já existente, isto é o que aconteceria no Linux (para outros sistemas operacionais pode ser diferente).
O Compromisso teria sucesso?
Sim e não: o comando git commit
voltaria como se tivesse sucesso, mas o novo objecto commit não seria criado.
Pode ser verificado mais tarde como uma cabeça separada?Não.
Referência :
arquivo sha1-file.c (persistência fc1395f4a491a7da46a446233531005634eb979d
)
int finalize_object_file(const char *tmpfile, const char *filename)
{
int ret = 0;
if (object_creation_mode == OBJECT_CREATION_USES_RENAMES)
goto try_rename;
else if (link(tmpfile, filename))
ret = errno;
/*
* Coda hack - coda doesn't like cross-directory links,
* ...
*/
if (ret && ret != EEXIST) {
try_rename:
if (!rename(tmpfile, filename))
goto out;
ret = errno;
}
unlink_or_warn(tmpfile);
if (ret) {
if (ret != EEXIST) {
return error_errno("unable to write sha1 filename %s", filename);
}
/* FIXME!!! Collision check here ? */
}
out:
if (adjust_shared_perm(filename))
return error("unable to set permission to '%s'", filename);
return 0;
}
O link falha com o EEXIST, o arquivo temporário é removido, e o código continua até o return 0
(através do FIXME, e o adjust_shared_perm()
que não tem razão para falhar).