#592610 Clarify when Conflicts + Replaces et al are appropriate

#592610#5
Date:
2010-08-11 12:55:46 UTC
From:
To:
Hi,

in May there was a discussion about the right use of Breaks or
Conflicts as part of Bug#582423, e.g.
http://lists.debian.org/debian-ctte/2010/05/msg00012.html

Since then I've noticed at least 3 people on #debian-devel asking
questions about wether to use Breaks or Conflicts now. Imho the
description of Breaks and Conflicts is unclear and contradictory in
parts and the use of Replaces+Breaks in 7.6.1 is wrong (breaks when an
upgrade is aborted).

I think all the needed info is in policy and the above mentioned
discussion and now a good word smith is needed to write it up all nice
and understandable. Saddly that is not me so consider this a request
for help from those of you good with words.

MfG
	Goswin

#592610#12
Date:
2010-08-18 08:52:50 UTC
From:
To:
Seconded.

Specifically, Policy now allows use Breaks, not Conflicts if two
packages has a file conflict. I consider it as a regression - a
high-level package manager cannot assume anymore that two packages
having Breaks can be installed (temporarily) without a file conflict,
and IMO the whole purpose of Breaks (as opposed to Conflicts) is defeated.

Please not write policy to reflect currently existing problems in some
high-level package managers which do wrong thing seeing
'Conflicts+Replaces'.

#592610#17
Date:
2010-08-18 12:59:28 UTC
From:
To:
"Eugene V. Lyubimkin" <ext-lyubimkin.eugene@nokia.com> writes:

Huh? The presense of Replaces allows the two to be both unpacked. The
Repalces specifically disables the file conflict.

MfG
        Goswin

#592610#22
Date:
2010-08-18 15:09:11 UTC
From:
To:
[ sorry for not proper 'mail-reply', used wrong mail address before ]

Replaces is one-way dependency, Breaks is two-way one. If I unpack two
packages, one having Breaks+Replaces, in the other order, I will have a file
conflict. And a high-level package manager have right to do it, by the
definition of Breaks, because "slave" package is not configured.

#592610#27
Date:
2010-08-18 15:37:05 UTC
From:
To:
Breaks and Replaces are both asymmetric relationships.

No, you won't.  Why would you think so?

#592610#32
Date:
2010-08-18 16:07:35 UTC
From:
To:
Steve Langasek wrote:

and

By logic. I didn't see anything to prevent them. However, as dpkg disagree
with me too, I started to wonder if policy in 'Packages can declare in their
control file that they should overwrite files in certain other packages, or
completely replace other packages' actually means two-way dependency? And is
it obvious to anyone but me?

#592610#37
Date:
2010-08-18 17:12:58 UTC
From:
To:
It's not a "two-way dependency"; the relationship is still asymmetric, the
files from the package /declaring/ Replaces always takes precedence.  But
the Replaces operation is invariant with respect to package unpack order -
perhaps that's what you mean?

I wouldn't say this is obvious.  I would say it's the /correct/ way to
implement it, and I know this is how it's implemented because I remember
back to when dpkg *didn't* do this correctly.  But it's possible that this
should be clarified in Policy.

#592610#42
Date:
2010-08-18 17:18:33 UTC
From:
To:
Steve Langasek wrote:
Yes, that's what I mean.

#592610#47
Date:
2010-08-25 14:10:05 UTC
From:
To:
"Eugene V. Lyubimkin" <jackyf@debian.org> writes:

That was a bug in dpkg that has been fixed a while now I think. Replaces
has to be two-way so that unpacking the replaced package after the
replacing one does not give a file overwrite error.

If you think the issue still exists then please create a unit test in
dpkg and file that as seperate bugreport against dpkg.

MfG
        Goswin

#592610#52
Date:
2013-01-03 08:36:47 UTC
From:
To:
retitle 592610 Clarify when Conflicts + Replaces et al are appropriate
quit

Hi Goswin,

In 2010, Goswin von Brederlow wrote:

Policy §7.6.2 sayeth:

| Second, Replaces allows the packaging system to resolve which package
| should be removed when there is a conflict (see Conflicting binary
| packages - Conflicts, Section 7.4).

One reading of this would be that in the presence of Conflicts,
Replaces represents a partial ordering of packages, indicating which
should be removed in case of conflict.  Seems useful enough.  One
consequence of this definition is that when A conflicts with and
replaces B, B should not conflict with and replace A in turn, since
the symmetric relationships would give no guidance in how to resolve
the conflict.

Then it continues:

| In this situation, the package declared as being replaced can be a
| virtual package, so for example, all mail transport agents (MTAs)
| would have the following fields in their control files:
|
|      Provides: mail-transport-agent
|      Conflicts: mail-transport-agent
|      Replaces: mail-transport-agent
|
| ensuring that only one MTA can be unpacked at any one time.

Here policy is recommending the same symmetrical C+R relationship it
had just seemed to imply defeats the purpose of C+R.

Responding to this confusing passage, Ian Jackson wrote[1]:

| If two packages Replaces/Conflicts/Provides the same virtual
| package you can't just "dpkg -i" to swap between them.  This is
| demonstrated in Eugene's message on the 9th of May, and the test
| case mentioned by Raphael does it.
[...]
| So which of spec or implementation is correct ?  I think the
| implementation is correct and the spec is wrong.

The thread also contains some guidance about particular use cases,
but first I guess we should resolve this question.  Should packages
A and B be allowed to ever both conflict with and replace each other?

I wouldn't mind a policy "should" forbidding mutual C+R on the grounds
that they are confusing, even though they are a widespread practice.

Thanks for filing this.  I think it got forgotten.

Hope that helps,
Jonathan

[1] https://lists.debian.org/debian-ctte/2010/05/msg00010.html

#592610#59
Date:
2013-01-03 16:46:27 UTC
From:
To:
Jonathan Nieder <jrnieder@gmail.com> writes:

Yes, that seems to be Ian's conclusion.

Policy currently treats this as a special case distinguished by the
presence of Provides, but as discussed in that thread, that isn't a very
good assumption, since there are other reasons for wanting to add the
Provides than this case.

Ian proposed a comprehensive replacement for what to use in the different
use cases we have, and I think that's a better approach.  The point is to
make sure that we cover all our different use cases and can usefully
distinguish between them.

The key change is that the virtual package conflict drops Replaces, which
of course isn't what's in the archive right now and would require lots of
people change packages.  Before we go down that path, I'd really like to
get confirmation from the dpkg developers that that's the correct thing to
do.  I think that's the only real change from the current wording; the
rest is (useful) clarification.

Note that the point originally raised is that dpkg -i can't be used to
switch between packages implementing the same virtual package in a
mutually-exclusive fashion.  Does the proposed solution actually fix that
problem?

Maybe someone could propose new language implementing the table discussed
in the above thread and then we could run it past the dpkg folks to make
sure that makes sense?  I think the best wording approach would be to
describe the intent of Breaks, Conflicts, Provides, and Replaces in
isolation in their current sections, but then move all of the text about
how they work in concert to a new section that lays out the specific use
cases discussed and provides guidance for how to implement each one.

#592610#64
Date:
2025-08-13 08:35:44 UTC
From:
To:
Hello,

Note 3 says

    To see why Breaks is normally needed in addition to Replaces,
    consider the case of a file in the package foo being taken over by
    the package foo-data.  Replaces will allow foo-data to be installed
    and take over that file.  However, without Breaks, nothing requires
    foo to be upgraded to a newer version that knows it does not include
    that file and instead depends on foo-data.  Nothing would prevent
    the new foo-data package from being installed and then removed,
    removing the file that it took over from foo.  After that operation,
    the package manager would think the system was in a consistent
    state, but the foo package would be missing one of its files.

This works for the foo/foo-data example in the text because these are
implied to be tightly coupled packages.  But sometimes you do want
Replaces without Breaks, because the cost of Breaks is high.

bin:git-debpush is taking over /usr/bin/git-deborig from devscripts.
So devscripts is getting a "Recommends: git-debpush (>= 13.12)" and
git-debpush is getting a "Replaces: devscripts (<< 2.25.18)".

If we also add a Breaks, git-debpush won't be installable on older
Debian releases.  Currently dgit and git-debpush are installable and
work all the way back to buster.

devscripts doesn't hard-depend on the functionality in git-deborig.
You can't even use it without installing some of devscript's Recommends,
like with other things in devscripts.  Therefore it wouldn't make sense
to give up the high installability of git-debpush and trivial
backportability of src:dgit just so that if someone decides to install
devscripts and then install and remove git-debpush, they will be left
without git-deborig.

Ideally the text would reflect this but it's a significant task to work
it in without adding too much length.

I think many people in Debian mistakenly think you can't ever use
Replaces without Breaks; there is a Salsa CI 'missing-breaks' check that
enforces it that we are now having to disable for src:dgit.

#592610#69
Date:
2025-08-13 19:00:50 UTC
From:
To:
Sean Whitton <spwhitton@spwhitton.name> writes:

My first reaction is that this is a very specific situation that isn't
going to arise much, in part because devscripts is a rather unusual
package: It provides a ton of functionality, most of which is probably not
used by the typical person who installs it, and therefore the risk of a
package inconsistency where part of the package goes missing is not as
high for it.

I think the way to generalize this would be to say that Breaks may not be
desirable if all of the following apply:

1. The replaced functionality is not that important to the original
   package, so the consequences of the described pattern that causes the
   file to disappear won't affect many people.

2. Coinstallation of the two packages is important (in backports, for
   instance).

3. Backporting of the package whose files are being replaced is not
   desirable for some reason, even though backporting of the replacing
   package *is* important.

This seems like an edge case, and the criteria for 1 are rather murky. The
package inconsistency that can be reached without Breaks bothers me, since
it's a sort of silent corruption in the sense that the contents of the
installed packages no longer represent the files present on the system.
That seems worth going to some effort to avoid, and I'm a bit worried
about people accepting that state too readily.

In other words, I agree with your conclusion that not using Breaks is fine
in this situation, and this is why Policy says "should" and not "must,"
but explaining the exception cases to the "should" is a bit tricky.

I think the problem might be more that forgetting the Breaks is a really
common error because nothing in the packaging workflow makes you add it?
If you try to move the file without Replaces, installing the new package
fails and that's immediately obvious, but once you add the Replaces,
nothing makes you add the Breaks and the failure mode is pretty silent. So
I'm not sure it's that people think it's flatly disallowed as much as it's
a common error that's hard to notice.

I'm surprised that there's a special check for this instead of relying on
Lintian, though. I don't *think* it requires cross-package knowledge to
diagnose?

#592610#74
Date:
2025-08-14 10:08:11 UTC
From:
To:
Hello,

Thanks, I agree with everything you've written here.

Yeah, you're probably right.

The check currently actually determines whether there are issues with
file overwriting, by installing the packages and seeing what happens, I
think.  But I don't know much about it.