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 add
falha 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-missing
existe frustrantemente, mas só funciona com--dry-run
.Uma
git add
invocaçã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 --all
invocaçã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 add
inspecionando 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