Faça o índice refletir arquivos em determinados caminhos na árvore de trabalho, incluindo sua presença

Faça o índice refletir arquivos em determinados caminhos na árvore de trabalho, incluindo sua presença

Eu tenho um script que atualiza um repositório e adiciona/exclui arquivos em alguns caminhos específicos. Como posso confirmar essas alterações conhecendo os caminhos? Ou seja,

  • Se um arquivo especificado estiver na árvore de trabalho, copie-o para o índice
  • Se um arquivo especificado estiver no índice, mas não na árvore de trabalho, remova-o do índice
  • Se um arquivo especificado não estiver na árvore de trabalho nem no índice, não faça nada.

git addfalha no último caso - se algum dos caminhos em sua linha de comando não existir, ele sai com um erro e não faz nada.

Eu considerei:

  • git add --ignore-errors, infelizmente não considera a inexistência do arquivo como o tipo de erro que ele ignora.

  • git add --ignore-missingexiste frustrantemente, mas só funciona com --dry-run.

  • Uma git addinvocação por caminho, ignorando erros, funcionaria, mas é lenta e não permite discernir erros devido à inexistência do arquivo (nem no índice nem na árvore de trabalho) de outros erros.

  • Uma git add --allinvocação não permite preparar apenas arquivos em determinados caminhos.

Responder1

A melhor solução que encontrei até agora é construir uma lista de caminhos para passar git addinspecionando explicitamente o índice git e a árvore de trabalho.

Dado o repositório:

git init .
echo $RANDOM > ignore-edited
echo $RANDOM > ignore-deleted
echo $RANDOM > add-edited
echo $RANDOM > add-deleted
git add .
git commit -m 'Initial commit'

echo $RANDOM > ignore-new
echo $RANDOM > ignore-edited
rm             ignore-deleted
echo $RANDOM > add-new
echo $RANDOM > add-edited
rm             add-deleted

e a lista de arquivos a serem atualizados:

printf '%s\n' add-new add-edited add-deleted add-nonexistent | sort \
    > /tmp/filelist.txt

Podemos construir a lista de arquivos obtendo a união entre a interseção dos nossos arquivos a serem adicionados e o índice, e a interseção dos nossos arquivos a serem adicionados e os existentes na árvore de trabalho:

comm -12 /tmp/filelist.txt <(git ls-files) \
    > /tmp/files-in-index.txt
while read -r line ; do test -e "$line" && printf -- '%s\n' "$line" ; done < /tmp/filelist.txt \
    > /tmp/files-in-worktree.txt
sort -um /tmp/files-in-index.txt /tmp/files-in-worktree.txt \
    > /tmp/files-to-add.txt
< /tmp/files-to-add.txt xargs git add

Ou, em uma invocação:

sort -um \
    <(comm -12 /tmp/filelist.txt <(git ls-files)) \
    <(while read -r line ; do test -e "$line" && printf -- '%s\n' "$line" ; done < /tmp/filelist.txt) |
    xargs git add

informação relacionada