Идемпотентные миграции на Битрикс: чтобы повторный прогон не затирал картинки
Повторный прогон миграции на Битрикс однажды затёр картинки. С тех пор: XML_ID, не трогать медиа без нужды, лог create/update/skip, сначала staging.

Скрипт переноса разделов или свойств запускают не один раз: поправили маппинг, прогнали снова. Если миграция каждый раз «создаёт заново» или затирает поля — прощайте картинки и ручные правки редакторов.
Закулисье: цена одного «ещё раз прогоним»
На одном из прогонов (контекст проектов вроде Квартала Полёт) повторный запуск перезаписал медиа-поля, хотя контент текста уже был верный. Откат из бэкапа спас, но утро понедельника было нервным. После этого в чеклисте миграции первым пунктом идемпотентность, а не «успел за час».
Правила
- искать сущность по внешнему ключу / XML_ID, не плодить дубли;
- не трогать медиа, если файл уже на месте и хеш совпал;
- логировать, что создано / обновлено / пропущено;
- сначала staging, потом прод.
Скучно, но дешевле отката из бэкапа. Связанный контекст — в заметке про local/templates и LIST_MODE.