O que aconteceria se dois Git commits tivessem o mesmo hash SHA-1?

Deixe-me prefixar isto dizendo que estou ciente das probabilidades extremamente minúsculas de isto acontecer. Eu sei que seria mais ou menos impossível de fabricar, e Extremamente improvável de acontecer "na natureza."Esta é simplesmente uma pergunta sobre os internos do Git.

Então, aqui está a minha pergunta: O que aconteceria se dois commit hashs fossem idênticos? Para começar:

  • O Compromisso teria sucesso?
  • mais tarde poderia ser verificado como um cabeça separada?
  • seria possível um compromisso posterior?
 11
git
Author: Ben, 2015-09-17

2 answers

Como é que o git lidaria com uma colisão SHA-1 numa bolha? " ainda se aplicaria, mesmo para um commit e não para um blob.
ComoTarek mencionanos comentários , o git pensa em tudo como "objectos", cada um com o seu próprio SHA1.

https://git-scm.com/book/en/v2/book/10-git-internals/images/data-model-4.png

(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.

 4
Author: VonC, 2018-05-11 22:31:14

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).

 1
Author: user803422, 2018-05-03 20:57:31