On a Debian or Ubuntu host, what is the difference between `apt upgrade`, `apt full-upgrade` and `apt-get dist-upgrade`, and which of them is allowed to remove an installed package?
answer
- three permission levels, one job
- kept back means action not permitted
- full-upgrade may remove
- kernel metapackage needs a new package
- dist-upgrade is not a release upgrade
basics
~20 sapt upgrade never removes an installed package; anything whose upgrade would require a removal is kept back. apt full-upgrade and apt-get dist-upgrade are the same command and may remove packages to resolve conflicts. apt-get upgrade is stricter still: it also refuses to add new packages.
solid answer
~40 sAll three upgrade installed packages, and they differ only in what they are permitted to do to satisfy the new dependencies. `apt-get upgrade` is the most conservative: it will neither install a new package nor remove one, so anything needing either is reported as kept back. `apt upgrade` keeps the no-removal guarantee but will pull in new packages when an upgrade requires them — that is why a kernel meta-package upgrade works under `apt upgrade` and stalls under `apt-get upgrade`. `apt full-upgrade`, and its identical older spelling `apt-get dist-upgrade`, additionally allow removals, which is what gets you through a genuine transition where two packages now conflict. In practice that makes `upgrade` the safe unattended default and `full-upgrade` the deliberate, supervised one — and you read the `REMOVED` list before answering yes.
go deeper
Know that upgrade updates installed packages while full-upgrade is allowed to go further, and that neither one moves you to a new release of the distribution. Be able to point at the kept-back line in the output.
Explain the permission ladder precisely: no new packages, new packages but no removals, removals allowed. Use the kernel meta-package as the concrete example of why apt-get upgrade holds packages back.
Show the operational reflex — simulate first, read the REMOVED block, and choose the conservative command for unattended runs while scheduling supervised full-upgrades so kept-back updates do not accumulate into a risky big-bang later.
Own the patching policy across the fleet: what runs unattended, what needs a change window, how the kept-back count is monitored as a signal, and how release upgrades are handled as a separate, tested procedure rather than an apt flag.
## The same job, three permission levels The three commands all mean "bring installed packages up to their candidate versions". What separates them is the set of actions the resolver is allowed to take when the straightforward upgrade does not fit. | Command | May install new packages | May remove packages | |---|---|---| | `apt-get upgrade` | no | no | | `apt upgrade` | yes | no | | `apt full-upgrade` = `apt-get dist-upgrade` | yes | yes | `apt full-upgrade` and `apt-get dist-upgrade` are not two behaviours with a modern and a legacy name for different things — they are the same resolver mode, renamed when the `apt` front end was introduced because "dist-upgrade" misled people into thinking it moved you to the next distribution release. It does not. ## "The following packages have been kept back" This line is the visible edge of the permission model. A package is held back when upgrading it would need an action the command is not allowed to take. The classic case is the kernel. On Ubuntu, `linux-image-generic` is a meta-package that depends on a versioned package such as `linux-image-6.8.0-45-generic`. Upgrading the meta-package therefore requires *installing a package that is not currently on the system*. Under `apt-get upgrade` that is forbidden, so it is kept back and the machine quietly stops taking kernel updates. Under `apt upgrade` the new kernel package is installed and the upgrade completes. `apt-get upgrade --with-new-pkgs` gives the old command the same permission explicitly. The second case is a conflict: the new version of A conflicts with installed package B, or a library transition means B is no longer built. Resolving that needs a removal, so both `upgrade` forms hold it back and only `full-upgrade` can proceed. On Ubuntu there is a third, non-structural cause: phased updates. An update can be released to a growing percentage of machines over several days, and a machine not yet in the phase sees the package as kept back even though nothing depends on anything new. It resolves itself as the phase widens. ## Why the distinction matters operationally ``` apt-get -s full-upgrade ``` Simulating first is the habit worth having, because the difference between the commands is precisely the difference between a routine patch run and one that can take a service away. A `full-upgrade` on a neglected box can propose removing something a colleague installed by hand, or a metapackage whose dependencies changed, and the only warning is the `The following packages will be REMOVED` block in the plan. Read it. In unattended contexts, the conservative `upgrade` is the right default for exactly this reason — the failure mode of a kept-back package is a missed update you can see in monitoring, while the failure mode of an unsupervised removal is an outage. The opposite mistake is never running `full-upgrade` at all. Packages accumulate in the kept-back list, security updates sit unapplied because they arrived in a transition, and the eventual upgrade is far larger and riskier than a series of small supervised ones. The healthy pattern is `upgrade` frequently and unattended, `full-upgrade` deliberately on a schedule with the plan reviewed. ## What none of them do None of these commands move the machine to a new distribution release. On Debian the documented procedure is to edit the sources to the new suite, then run `apt update`, `apt upgrade --without-new-pkgs`, and finally `apt full-upgrade` — the minimal-upgrade step first, deliberately, so the core is consistent before the resolver is allowed to make big changes. On Ubuntu the supported path is `do-release-upgrade`, which handles sources rewriting, third-party repository disabling and a recovery shell that a bare `full-upgrade` does not. Also worth separating: `apt upgrade` never removes, but `apt autoremove` exists specifically to remove packages that were pulled in automatically and are no longer depended on. Some people wire `autoremove` into their patch runs; on a server that is where an unexpected kernel or library removal is most likely to come from, so it deserves the same plan review. ## Reading the summary line Every apt transaction ends with a count: upgraded, newly installed, to remove, not upgraded. The last number is the kept-back count, and on a fleet it is the number worth alerting on. A machine sitting at "12 not upgraded" for weeks is telling you that your conservative patch job has hit something it is not permitted to resolve, and that somebody needs to run the supervised command.
- A server reports the same three packages as "kept back" every night for a month. How do you work out why?Simulate the stricter and looser commands and compare: `apt-get -s upgrade` versus `apt-get -s full-upgrade` shows whether the blocker is a new package or a removal. If only `full-upgrade` clears it, read its `REMOVED` list before running it. On Ubuntu, rule out phased updates first, since those clear themselves within days without intervention.
- Is `apt-get dist-upgrade` how you move a Debian box from one stable release to the next?No. It is the same resolver mode as `apt full-upgrade` within the currently configured suites. A release upgrade means editing the sources to the new suite first; Debian's documented sequence is then `apt update`, `apt upgrade --without-new-pkgs`, and `apt full-upgrade`. Ubuntu's supported path is `do-release-upgrade`, which also handles third-party sources and provides a recovery shell.
- Which of these commands would you put in an unattended nightly job, and why?The conservative `upgrade`, because it cannot remove a package and therefore cannot take a service away while nobody is watching. Its failure mode is a visible kept-back count, which you alert on and clear during a supervised `full-upgrade` window. Wiring `autoremove` into the same unattended job reintroduces exactly the removal risk you avoided.
saying these in an interview costs you the question
- Says dist-upgrade upgrades you to the next distribution release
- Thinks apt upgrade and apt full-upgrade are just old and new names
- Believes kept-back packages are broken or corrupt
- Runs full-upgrade unattended without reading the REMOVED list
- Assumes apt upgrade can never install a package it does not already have