Você deve conseguir recuperar todos os arquivos adicionados ao índice (por exemplo, como na sua situação, com git add .), embora possa ser um pouco trabalhoso. Para adicionar um arquivo ao índice, git o adiciona ao banco de dados de objetos, o que significa que ele pode ser recuperado desde que a coleta de lixo ainda não tenha acontecido. Há um exemplo de como fazer isso dado na resposta de Jakub Narębski aqui:
No entanto, tentei fazer isso em um repositório de teste e houve alguns problemas - --cacheddeveria haver --cache, e descobri que ele não criou o .git/lost-founddiretório. No entanto, as seguintes etapas funcionaram para mim:
git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)")
Isso deve gerar todos os objetos no banco de dados de objetos que não podem ser acessados por nenhum ref, no índice ou por meio do reflog. A saída será semelhante a esta:
unreachable blob 907b308167f0880fb2a5c0e1614bb0c7620f9dc3
unreachable blob 72663d3adcf67548b9e0f0b2eeef62bce3d53e03
... e para cada um desses blobs, você pode fazer:
git show 907b308
Para produzir o conteúdo do arquivo.
Muita produção?
Atualização em resposta a sehe 's comentário abaixo:
Se você achar que tem muitos commits e árvores listados na saída daquele comando, você pode querer remover da saída quaisquer objetos que são referenciados de commits não referenciados. (Normalmente você pode voltar a esses commits por meio do reflog de qualquer maneira - estamos apenas interessados em objetos que foram adicionados ao índice, mas nunca podem ser encontrados por meio de um commit.)
Primeiro, salve a saída do comando, com:
git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") > all
Agora, os nomes de objeto desses commits inacessíveis podem ser encontrados com:
egrep commit all | cut -d ' ' -f 3
Assim, você pode encontrar apenas as árvores e objetos que foram adicionados ao índice, mas não confirmados em nenhum ponto, com:
git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") \
$(egrep commit all | cut -d ' ' -f 3)
Isso reduz enormemente o número de objetos que você terá que considerar.
Atualização: Philip Oakley abaixo sugere outra maneira de reduzir o número de objetos a serem considerados, que é apenas considerar os arquivos modificados mais recentemente em .git/objects. Você pode encontrá-los com:
find .git/objects/ -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort
(Encontrei essa findinvocação aqui .) O final dessa lista pode ser assim:
2011-08-22 11:43:43.0234896770 .git/objects/b2/1700b09c0bc0fc848f67dd751a9e4ea5b4133b
2011-09-13 07:36:37.5868133260 .git/objects/de/629830603289ef159268f443da79968360913a
Nesse caso, você pode ver esses objetos com:
git show b21700b09c0bc0fc848f67dd751a9e4ea5b4133b
git show de629830603289ef159268f443da79968360913a
(Observe que você deve remover o /no final do caminho para obter o nome do objeto.)