Estou tentando listar os nomes de todos os arquivos que existiram em qualquer ponto do histórico de uma ramificação, mas que foram excluídos posteriormente e não existem no commit mais recente dessa ramificação.
As respostas em outras perguntas semelhantes (mas não idênticas) sugerem o seguinte:
git log --all --pretty=format: --name-only --diff-filter=D
mas isso lista todas as operações individuais de exclusão de arquivos de todos os commits no histórico da ramificação, sem considerar se os arquivos foram adicionados novamente.
Eu uso o git regularmente o suficiente para ser perigoso e minha terminologia pode estar um pouco errada, então aqui está um exemplo concreto do que estou tentando fazer:
git init
:: add three files
echo aaa > aaa.txt
echo bbb > bbb.txt
echo ccc > ccc.txt
git add --all
git commit -m "initial commit"
:: delete aaa.txt, bbb.txt
del aaa.txt
del bbb.txt
git add --all
git commit -m "delete aaa.txt, bbb.txt"
:: re-add aaa.txt
echo zzz > aaa.txt
git add --all
git commit -m "re-add aaa.txt"
Estou tentando descobrir qual comando preciso listar bbb.txt
- não me importo que aaa.txt
tenha sido excluído em algum momento porque foi adicionado novamente posteriormente, portanto, atualmente existe na ponta do galho.
Também não estou preocupado com o conteúdo dos arquivos, apenas identificando os nomes/caminhos dos arquivos "ausentes".
Especificamente, gostaria que a saída deste comando hipotético fosse:
bbb.txt
Se a saída também puder listar o commit mais recente do qual os arquivos "ausentes" foram excluídos, isso será um bônus, mas não essencial.
Assumindo um ambiente shell Unix, você pode usar
comm
fromcoreutils
para comparar a lista de arquivos excluídos com uma lista de arquivos na revisão atual:Dividindo isso:
O
comm
comando compara dois arquivos classificados linha por linha. Passar-23
faz com que ele imprima apenas as linhas contidas no primeiro arquivo, mas não no segundo.Os dois "arquivos" para os quais são passados
comm
são substituições de processos (<(...)
).A primeira substituição de processo é uma versão modificada do comando de arquivo excluído da pergunta. A saída é transmitida
sort | uniq
para obter uma lista classificada de caminhos de arquivos exclusivos. A saída também é passadagrep -v '^$'
para remover uma incômoda linha em branco.A segunda substituição de processo usa
git ls-files
para buscar os nomes de todos os arquivos na revisão atual. Eles são classificados usandosort
para mantê-loscomm
felizes.O resultado é uma lista de todos os arquivos que foram excluídos em algum momento do histórico e que também não estão contidos na revisão atual.
Bônus: obter o commit mais recente que excluiu cada arquivo excluído
Depois de ter os caminhos para os arquivos excluídos, você pode determinar em qual commit eles foram excluídos usando
Então, para obter todos os arquivos excluídos e os commits em que foram excluídos, você poderia usar algo como
Se você estiver na infeliz situação em que precisa lidar com novas linhas em nomes de arquivos, verifiquei que essa abordagem ainda funciona se você usar linhas delimitadas por NUL em todos os lugares, passando
-z
paracomm
,git log
,sort
,uniq
egrep
.Eu não queria vincular outras respostas a uma linguagem/plataforma específica, mas estou usando especificamente o PowerShell (Core) 7.3 (para ser executado no Windows e Linux) - adaptei a resposta de @ Brian61354270 e apenas postei aqui para devolva algo...
"Na
git log
saída de status de nome com um cabeçalho apenas de hash, se houver apenas um campo, é o ID do commit, então lembre-se disso, caso contrário, se não vimos o nome do arquivo antes, esta é a última coisa feita para isso, se for uma exclusão, queremos esta linha, sabemos que são todas exclusões, então apenas substitua peloD
ID do commit."