У меня есть скрипт, который обновляет репозиторий и добавляет/удаляет файлы по некоторым заданным путям. Как я могу зафиксировать эти изменения, зная пути? Т.е.
- Если указанный файл находится в рабочем дереве, скопировать его в индекс
- Если указанный файл есть в индексе, но отсутствует в рабочем дереве, удалить его из индекса.
- Если указанного файла нет ни в рабочем дереве, ни в индексе, ничего не делать.
git add
происходит сбой в последнем граничном случае — если какой-либо из путей в командной строке не существует, он завершается с ошибкой и ничего не делает.
Я считал:
git add --ignore-errors
, к сожалению, не считает отсутствие файла ошибкой, которую игнорирует.git add --ignore-missing
к сожалению существует, но работает только с--dry-run
.Один
git add
вызов на путь, игнорирующий ошибки, может работать, но это медленно и не позволяет отличить ошибки, связанные с отсутствием файла (ни в индексе, ни в рабочем дереве), от других ошибок.Один
git add --all
вызов не позволяет размещать только файлы по определенным путям.
решение1
Лучшее решение, которое я нашел на данный момент, — это создание списка путей для перехода git add
путем явного просмотра индекса git и рабочего дерева.
Учитывая репозиторий:
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
и список файлов для обновления:
printf '%s\n' add-new add-edited add-deleted add-nonexistent | sort \
> /tmp/filelist.txt
Мы можем построить список файлов, получив объединение между пересечением наших файлов для добавления и индекса, а также пересечением наших файлов для добавления и файлов, существующих в рабочем дереве:
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
Или, в одном призыве:
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