Skip to content

How to roll back a package update

Use this guide when an update has installed a new version of a package that doesn't work for you, and you need the previous version back while you investigate or wait for a fix.

How reliable a rollback is depends on the distribution. Installing an older package is easy everywhere, if you can still get it: point-release distributions usually keep earlier versions in their repositories, while rolling distributions rely on your local package cache or an archive. No package manager reverses what the newer version's installation scripts did, such as migrating a database or a configuration format, so a rollback can leave the older version facing data it doesn't understand.

Back up the package's data first

If the package keeps state (a database server, a mail server, anything with files under /var/lib), stop its service and back up that state before you downgrade. Check the upstream release notes for whether the new version changed its data format; if it did, restore the backup taken before the update rather than pointing the old version at migrated data.

Before you begin

  • You need a shell with sudo on the machine.
  • Replace <PACKAGE> with the name of the package and <VERSION> with the version to go back to, as found in step 1. The examples use jq on Debian and Ubuntu, wget on the RHEL family, tree on Arch and app-text/tree on Gentoo.
  • Downgrading is less tested than upgrading by every distribution. Try it on a test machine first where you can.

Steps

  1. Find which version was installed before, and which versions are available. /var/log/apt/history.log records every change, with the old and new version in brackets:

    $ grep '<PACKAGE>:' /var/log/apt/history.log
    Install: libonig5:amd64 (6.9.9-1+b1, automatic), jq:amd64 (1.7.1-6+deb13u3), libjq1:amd64 (1.7.1-6+deb13u3)
    Upgrade: jq:amd64 (1.7.1-6+deb13u3, 1.7.1-6+deb13u4), libjq1:amd64 (1.7.1-6+deb13u3, 1.7.1-6+deb13u4)
    $ apt-cache policy <PACKAGE>
    jq:
      Installed: 1.7.1-6+deb13u4
      Candidate: 1.7.1-6+deb13u4
      Version table:
     *** 1.7.1-6+deb13u4 500
            500 http://deb.debian.org/debian-security trixie-security/main amd64 Packages
            100 /var/lib/dpkg/status
         1.7.1-6+deb13u3 500
            500 http://deb.debian.org/debian trixie/main amd64 Packages
    

    Older logs are rotated to history.log.1.gz and so on; read them with zgrep.

  2. Check whether the older version can still be installed. It can if apt-cache policy lists it, or if its .deb file is still in /var/cache/apt/archives/:

    ls /var/cache/apt/archives/ | grep '^<PACKAGE>_'
    

    Ubuntu's release pocket (resolute) keeps the version the release shipped with, while Debian's main suite (trixie) is replaced at each point release, as in the example above. Each update suite keeps only its newest version: an intermediate security update is gone once a newer one replaces it. apt doesn't keep the packages it downloads by default, while apt-get keeps them until apt-get clean. For Debian, every version ever published is also available from snapshot.debian.org.

  3. Install the older version, together with any packages that require exactly the same version. jq depends on exactly its own version of libjq1, so both go back together:

    sudo apt-get install -y --allow-downgrades <PACKAGE>=<VERSION> libjq1=<VERSION>
    

    Without -y, apt-get lists the packages it will downgrade and asks for confirmation; check the list. If it wants to remove other packages, stop and find out why.

On Ubuntu 26.04, apt 3.2 also numbers its transactions: apt history-list lists them, and apt history-info <ID> shows the old and new version of each package a transaction changed, which is a quicker way to do step 1. It also has an apt history-undo command, but with apt 3.2.0, undoing an upgrade left the new versions installed, so downgrade with apt-get install as shown. Debian 13's apt 3.0 has none of these commands.

dnf records every transaction with the exact package versions it changed, and the RHEL family's repositories usually keep earlier builds of a package within the current minor release, so you can usually reverse an update directly.

  1. Find the transaction that upgraded the package:

    $ dnf history list <PACKAGE>
    ID     | Command line             | Date and time    | Action(s)      | Altered
    -------------------------------------------------------------------------------
         2 | -y upgrade wget          | 2026-11-07 13:29 | Upgrade        |    1
         1 | -q install -y wget-1.24. | 2026-11-07 13:29 | Install        |    1
    $ dnf history info <TRANSACTION>
    

    Replace <TRANSACTION> with the ID from the first column, here 2. dnf history info lists every package the transaction changed: undoing it reverses all of them.

  2. Undo the transaction:

    sudo dnf history undo -y <TRANSACTION>
    

    dnf downgrades the upgraded packages, removes packages the transaction installed and reinstalls ones it removed, and records the undo as a new transaction.

To go back one version of a single package instead, whatever transaction upgraded it, use dnf downgrade:

sudo dnf downgrade -y <PACKAGE>

dnf list --showduplicates <PACKAGE> lists the versions the repositories offer; sudo dnf downgrade <PACKAGE>-<VERSION> installs a specific one.

If the package is the kernel, don't downgrade it: dnf keeps previous kernels installed (installonly_limit=3 in /etc/dnf/dnf.conf keeps three in total, including the newest), so choose an older one in the boot menu instead, as described in How to boot into rescue mode.

Arch's repositories only carry the current version of each package, so the older version has to come from your package cache or from the Arch Linux Archive.

Partial upgrades aren't supported

Arch packages are built against the current versions of each other. Downgrading one package can break it or packages that depend on it; downgrade its dependencies with it if the update changed them too, and upgrade again as soon as a fixed version is available.

  1. Find the previous version in /var/log/pacman.log:

    $ grep 'upgraded <PACKAGE> ' /var/log/pacman.log
    [2026-11-07T13:31:05+0000] [ALPM] upgraded tree (2.3.1-1 -> 2.3.2-1)
    
  2. Look for that version in the package cache, which keeps every version pacman downloaded until you clean it:

    $ ls /var/cache/pacman/pkg/<PACKAGE>-<VERSION>-*
    /var/cache/pacman/pkg/tree-2.3.1-1-x86_64.pkg.tar.zst
    /var/cache/pacman/pkg/tree-2.3.1-1-x86_64.pkg.tar.zst.sig
    
  3. Install the older package file:

    sudo pacman -U --noconfirm /var/cache/pacman/pkg/<PACKAGE>-<VERSION>-x86_64.pkg.tar.zst
    

    Packages built for every architecture end in -any.pkg.tar.zst instead of -x86_64.pkg.tar.zst.

If the cache no longer has the version (because of pacman -Sc, paccache or a new installation), install it from the Arch Linux Archive, which keeps every package Arch has published, signed as the original was. Packages are under packages/<FIRST_LETTER>/<PACKAGE>/, where <FIRST_LETTER> is the first letter of the package name:

sudo pacman -U --noconfirm https://archive.archlinux.org/packages/<FIRST_LETTER>/<PACKAGE>/<PACKAGE>-<VERSION>-x86_64.pkg.tar.zst

Gentoo keeps several versions of most packages in the ebuild repository, but removes old ones over time. If the version you want is still there, Portage can install it again, from a binary package when one is available and from source otherwise.

  1. Find the version installed before the update with qlop, which reads Portage's merge log (readable only by root and members of the portage group):

    $ sudo qlop -v <PACKAGE>
    2026-11-07T14:14:21 >>> app-text/tree-2.1.1-r1: 1s
    2026-11-07T14:14:24 >>> app-text/tree-2.2.1: 2s
    
  2. Check that the repository still has an ebuild for it:

    $ ls /var/db/repos/gentoo/<PACKAGE>/
    Manifest  metadata.xml  tree-2.1.1-r1.ebuild  tree-2.2.1.ebuild  tree-2.3.2.ebuild
    

    If it doesn't, the ebuild is still in the history of the Gentoo repository, and you can copy it into a local ebuild repository; that's beyond this guide.

  3. Mask the versions newer than the one you want, so that the next @world update doesn't bring the update straight back. <NAME> is the package name without its category, here tree:

    sudo install -d /etc/portage/package.mask
    echo '><PACKAGE>-<VERSION>' | sudo tee /etc/portage/package.mask/rollback-<NAME>
    
  4. Install the older version without adding a version to your @world set:

    sudo emerge --getbinpkg --oneshot =<PACKAGE>-<VERSION>
    

    --getbinpkg uses Gentoo's binary package host when it has the version; binary packages you built yourself are used from /var/cache/binpkgs with --usepkg.

Verify

Check the installed version:

$ dpkg-query -W <PACKAGE> libjq1
jq      1.7.1-6+deb13u3
libjq1:amd64    1.7.1-6+deb13u3
$ rpm -q <PACKAGE>
wget-1.24.5-5.el10.x86_64
$ pacman -Q <PACKAGE>
tree 2.3.1-1
$ qlist -Iv <PACKAGE>
app-text/tree-2.1.1-r1

Then test the program, and restart any service that uses it.

Keep the update from coming back

Except on Gentoo, where the mask from step 3 already does this, the next upgrade installs the newer version again. Hold the package at the version you rolled back to, as described in How to hold a package at its current version, and release the hold once a fixed version is available.

Troubleshooting

E: Version '…' for '…' was not found from apt-get
No configured repository offers that version any more, and it isn't in /var/cache/apt/archives/. On Debian, download the .deb files from snapshot.debian.org and install them with sudo apt-get install ./<FILE>.deb, where <FILE>.deb is the name of each downloaded file; on Ubuntu, older builds are listed on the package's Launchpad page.
Packages were downgraded and -y was used without --allow-downgrades from apt-get
apt-get refuses to downgrade unattended unless you say so. Add --allow-downgrades, after checking the list of packages without -y.
dnf history undo reports Cannot find rpm nevra or No package … available
One of the versions the transaction replaced is no longer in any enabled repository. Undo fewer packages with dnf downgrade <PACKAGE>-<VERSION>, or find the old package in the distribution's vault (AlmaLinux and Rocky Linux publish older minor releases there).
pacman -U reports signature from "…" is unknown trust or invalid or corrupted package
The package keyring has changed since the old package was signed. Update archlinux-keyring first (sudo pacman -Sy archlinux-keyring followed by a full sudo pacman -Su), then try again.
emerge reports there are no ebuilds to satisfy the version
The ebuild has been removed from the Gentoo repository. Recover it from the repository's Git history into a local ebuild repository, or accept a version that's still available.