Конфликты файлов с официальным репо: что делать
Если коротко: конфликт файлов возникает, когда pacman хочет записать файл, а на диске уже лежит файл с тем же путём, принадлежащий другому пакету. Установка прерывается с ошибкой failed to commit transaction (conflicting files). Лечится это не слепым --overwrite, а разбором: кто владеет файлом, зачем он там и какой пакет должен его отдать.
Что такое конфликт файлов в pacman
Pacman ведёт базу установленных файлов: каждый пакет владеет своим списком путей. Когда ты ставишь новый пакет, pacman сверяет его файлы с базой. Если путь уже занят другим пакетом, возникает конфликт.
Ошибка выглядит так:
error: failed to commit transaction (conflicting files)
package: /usr/bin/foo exists in filesystem
Тут два разных случая. Первый: файл принадлежит другому пакету из базы. Второй: файл лежит на диске, но не принадлежит ни одному пакету, так называемый exists on filesystem. Это разные ситуации, и лечатся они по-разному. Про второй случай есть отдельная статья «Файл существует в файловой системе».
Раньше конфликты обходили флагом --force, но в pacman 6 его убрали. Остался только --overwrite, и он требует явного указания путей. Это сделано специально: случайная перезапись чужих файлов ломает систему, и pacman теперь заставляет тебя думать.
Почему пакет из AUR конфликтует с официальным
Самая частая причина: пакет из AUR собирает тот же бинарник или кладёт файл по тому же пути, что и пакет из официальных репозиториев. Например, AUR-версия программы с другими флагами сборки ставит /usr/bin/foo, а официальный пакет foo уже владеет этим путём.
Вторая причина: пакет из AUR тянет зависимости, которые конфликтуют с уже установленными. Скажем, AUR-пакет требует bar-git, а у тебя стоит официальный bar.
Третья: два AUR-пакета дают один и тот же файл. Оба собирают один бинарник или кладут файлы в один каталог под разными именами. Такое бывает с форками и с пакетами, которые собирают общие ресурсы вроде иконок или тем.
Как понять, кто владеет файлом
Первый шаг: узнать, кому принадлежит конфликтующий путь.
pacman -Qo /usr/bin/foo
Если пакет найден, вывод покажет имя и версию. Если файл не принадлежит никому, pacman ответит No package owns .... Тогда это случай exists on filesystem, и разбирать его нужно отдельно.
Дальше проверь, установлен ли пакет-владелец и не сирота ли он:
pacman -Q foo
Если пакет не установлен, а файл на месте, возможно, ты удалял пакет вручную или файл остался от старой версии. Посмотреть, какие файлы числятся за пакетом, можно так:
pacman -Ql foo | grep /usr/bin/foo
Так ты увидишь, действительно ли пакет заявляет этот путь или файл попал на диск мимо базы.
Как работают conflicts, provides и replaces в PKGBUILD
В PKGBUILD есть три поля, которые управляют конфликтами.
conflicts=(...) перечисляет пакеты, с которыми этот пакет не может сосуществовать. При установке pacman предложит удалить конфликтующий пакет.
provides=(...) перечисляет виртуальные имена, которые пакет предоставляет. Например, provides=('foo') говорит pacman: этот пакет закрывает зависимость на foo.
replaces=(...) означает, что пакет заменяет другой, и pacman при установке заменит его файлы.
Разница между conflicts и replaces тонкая. conflicts запрещает сосуществование: pacman спросит, что удалить. replaces говорит «этот пакет теперь вместо того», и pacman заменит файлы без вопросов.
Посмотреть, что заявляет пакет, можно прямо из PKGBUILD:
grep -E '^(conflicts|provides|replaces)' PKGBUILD
Что делать при конфликте с официальным пакетом
Порядок действий простой: сначала пойми, нужен ли пакет, потом проверь, ожидаемая ли это замена, и только потом решай, как ставить.
Сначала пойми, нужен ли тебе этот пакет
Если AUR-пакет дублирует официальный, возможно, он тебе не нужен. Официальный пакет обновляется вместе с системой, а AUR-версию придётся пересобирать вручную. Проверь, чем они отличаются: может, разница только в свежести версии, и официальный вариант закрывает твою задачу.
Проверь, не заявляет ли пакет замену
Иногда конфликт ожидаемый: AUR-пакет специально заменяет официальный. В PKGBUILD тогда стоит replaces=('official-package'). В этом случае pacman сам предложит замену при установке, и конфликта не будет. Если replaces нет, а пакет по смыслу должен заменять официальный, это ошибка в PKGBUILD, и стоит написать о ней мейнтейнеру.
Собери с правильными conflicts
Если ты собираешь пакет сам и знаешь, что он несовместим с официальным, добавь в PKGBUILD:
conflicts=('official-package')
Тогда pacman при установке предложит удалить официальный пакет, и конфликт файлов не возникнет. Это правильный путь для своей сборки. Подробно про написание PKGBUILD читай в статье «Свой PKGBUILD: полный гайд».
Выбери альтернативный вариант пакета
Многие программы в AUR живут в нескольких вариантах: -git (сборка из исходников), -bin (готовый бинарник), обычный (сборка из релизного архива). Если один вариант конфликтует с официальным пакетом, попробуй другой. Например, вместо сборки из исходников поставь -bin, если он есть. Бинарный вариант часто кладёт файлы по другим путям или не тянет лишние зависимости, и конфликт уходит.
Когда –overwrite оправдан
--overwrite разрешает pacman перезаписать файлы, принадлежащие другим пакетам:
pacman -S --overwrite '/usr/lib/*' пакет
Он нужен в редких случаях: когда пакет в репозитории переехал на новый путь, а старый файл остался в базе, или когда официальный пакет меняет структуру каталогов. Например, при переходе библиотеки на новую версию с изменением путей.
Но использовать --overwrite бездумно нельзя. Он перезаписывает файлы чужого пакета, не трогая его базу. В результате пакет-владелец остаётся в базе, а его файлы уже не его. При следующем обновлении pacman снова попытается поставить эти файлы, и конфликт вернётся. Хуже того, перезаписанный пакет может сломаться: конфиги, библиотеки, скрипты, всё, что лежало по этим путям.
Правило простое: --overwrite только когда ты осознанно заменяешь один пакет другим и уверен, что файлы совместимы. Например, при переходе с одного пакета на его форк с теми же путями. И после такой замены удали старый пакет, чтобы база не врала:
pacman -R old-package
Как безопасно провести замену официального пакета
Если ты решил заменить официальный пакет на AUR-версию осознанно, делай это по шагам.
Сначала посмотри, что заявляет новый пакет:
grep -E '^(conflicts|provides|replaces)' PKGBUILD
Потом проверь, кто зависит от старого пакета:
pacman -Qi old-package
Вывод покажет, какие пакеты требуют его. Если зависимые пакеты есть, убедись, что новый пакет закрывает их через provides. Иначе после замены получишь сломанные зависимости. Про это читай статью «Зависимости AUR ломаются после обновления».
Затем установи новый пакет с --overwrite только на те пути, которые реально заменяешь:
pacman -S --overwrite '/usr/bin/foo' aur-package
И сразу удали старый:
pacman -R old-package
Затем проверь целостность системы:
pacman -Qk
Если pacman ругается на пропавшие файлы, верни старый пакет и подумай ещё раз.
Частые вопросы
Что значит «file exists in filesystem»?
Это значит, что файл лежит на диске, но не принадлежит ни одному пакету. Обычно он остаётся после ручного удаления пакета, распаковки архивов или старых версий. Разберись, нужен ли файл, и удали его или перенеси.
Можно ли просто добавить –overwrite и забыть?
Можно, но это отложенная мина. Файлы чужого пакета будут перезаписаны, а база pacman об этом не узнает. При следующем обновлении конфликт вернётся, а пакет-владелец может сломаться. --overwrite инструмент для осознанной замены, а не для обхода ошибок.
Чем conflicts отличается от replaces?
conflicts запрещает сосуществование: pacman предложит удалить один из пакетов. replaces говорит, что новый пакет заменяет старый, и pacman заменит его файлы сам. Если пакет по смыслу заменяет официальный, в PKGBUILD должен стоять replaces, а не только conflicts.
Конфликт двух AUR-пакетов: что делать?
Посмотри, кто владеет файлом (pacman -Qo), и реши, какой пакет тебе нужен. Если нужны оба, проверь, не заявляют ли они conflicts друг на друга, и выбери один. Держать два пакета, которые кладут файлы в одно место, нельзя: они будут ломать друг друга при каждом обновлении.
Конфликт возвращается после каждого обновления: почему?
Потому что причина не устранена. Ты перезаписал файлы через --overwrite, но пакет-владелец так и живёт в базе со своим списком путей. При обновлении pacman снова пытается поставить его файлы, и конфликт возвращается. Лечится это удалением старого пакета после замены и чисткой базы, а не повторным --overwrite.
Полезные ресурсы
- PKGBUILD (ArchWiki): документация по полям conflicts, provides и replaces.
- Pacman (ArchWiki): полный список флагов, включая –overwrite.
- Pacman от А до Я: команды: шпаргалка по командам pacman.
- Установка пакетов из AUR: как правильно ставить пакеты из AUR.
Заключение
Конфликт файлов при установке из AUR решается не флагом --overwrite, а пониманием ситуации. Сначала узнай, кто владеет файлом (pacman -Qo), потом посмотри, что заявляет пакет в PKGBUILD (conflicts, provides, replaces). Если конфликт ожидаемый, добавь conflicts в свою сборку или выбери другой вариант пакета. --overwrite оставь для осознанной замены, когда ты точно знаешь, что файлы совместимы. Так база pacman останется честной, а система целой.
Не получилось? Поможем настроить
Задай вопрос в чате — отвечаем быстро, по делу и без воды.

Комментарии