
Tengo un script que actualiza un repositorio y agrega/elimina archivos en algunas rutas determinadas. ¿Cómo puedo cometer estos cambios conociendo las rutas? Es decir,
- Si un archivo específico está en el árbol de trabajo, cópielo al índice
- Si un archivo específico está en el índice pero no en el árbol de trabajo, elimínelo del índice
- Si un archivo específico no está en el árbol de trabajo ni en el índice, no haga nada.
git add
falla en el último caso de la esquina: si alguna de las rutas en su línea de comando no existe, sale con un error y no hace nada.
Yo considere:
git add --ignore-errors
, desafortunadamente no considera que el archivo no exista como el tipo de error que ignora.git add --ignore-missing
Existe de manera frustrante pero solo funciona con--dry-run
.Una
git add
invocación por ruta, ignorando los errores, funcionaría, pero es lenta y no permite discernir los errores debidos a que el archivo no existe (ni en el índice ni en el árbol de trabajo) de otros errores.Una
git add --all
invocación no permite almacenar solo archivos en determinadas rutas.
Respuesta1
La mejor solución que encontré hasta ahora es construir una lista de rutas a las que pasar git add
inspeccionando explícitamente el índice de git y el árbol de trabajo.
Dado el repositorio:
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
y la lista de archivos para actualizar:
printf '%s\n' add-new add-edited add-deleted add-nonexistent | sort \
> /tmp/filelist.txt
Podemos construir la lista de archivos obteniendo la unión entre la intersección de nuestros archivos a agregar y el índice, y la intersección de nuestros archivos a agregar y los existentes en el árbol de trabajo:
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
O, en una invocación:
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