Conda revisions: letting you ‘rollback’ to a previous version of your environment
I now use Anaconda as my primary Python distribution – and my company have also adopted it for use on all of their developer machines as well as their servers – so I like to think I’m a relatively knowledgeable user. However, the other day I came across a wonderful feature that I’d never known about before…revisions!
The best way to explain is by a quick example. If you run conda list --revisions
, you’ll get an output like this:
2016-06-10 20:20:37 (rev 10) - +affine-2.0.0.post1 - +click-6.6 - +click-plugins-1.0.3 - +cligj-0.4.0 - +rasterio-0.35.1 - +snuggs-1.3.1 2016-06-10 20:22:19 (rev 11) - libpng {1.6.17 -> 1.6.22} 2016-06-10 20:25:49 (rev 12) - -gdal-2.1.0
In this output you can see a number of specific versions (or revisions) of this environment (in this case the default conda environment), along with the date/time they were created, and the differences (installed packages shown as +
, uninstalled shown as -
and upgrades shown as ->
). If you want to revert to a previous revision you can simply run conda install --revision N
(where N is the revision number). This will ask you to confirm the relevant package uninstallation/installation – and get you back to exactly where you were before!
So, I think that’s pretty awesome – and really handy if you screw things up and want to go back to a previously working environment. I’ve got a few other hints for you though…
Firstly, if you ‘revert’ to a previous revision then you will find that an ‘inverse’ revision is created, simply doing the opposite of what the previous revision did. For example, if your revision list looks like this:
2016-06-14 21:12:34 (rev 1) +mkl-11.3.3 +numpy-1.11.0 +pandas-0.18.1 +python-dateutil-2.5.3 +pytz-2016.4 +six-1.10.0 2016-06-14 21:13:08 (rev 2) +cycler-0.10.0 +freetype-2.6.3 +libpng-1.6.22 +matplotlib-1.5.1 +pyparsing-2.1.4
and you revert to revision 1 by running conda install --revision 1
, and then run conda list --revisions
again, you’ll get this:
2016-06-14 21:13:08 (rev 2) +cycler-0.10.0 +freetype-2.6.3 +libpng-1.6.22 +matplotlib-1.5.1 +pyparsing-2.1.4 2016-06-14 21:15:45 (rev 3) -cycler-0.10.0 -freetype-2.6.3 -libpng-1.6.22 -matplotlib-1.5.1 -pyparsing-2.1.4
You can see that the changes for revision 3 are just the inverse of revision 2.
One more thing is that I’ve found out that all of this data is stored in the history file in the conda-meta directory of your environment (CONDA_ROOT/conda-meta
for your default environment and CONDA_ROOT/envs/ENV_NAME/conda-meta
for any other environment). You don’t want to know why I went searching for this file (it’s a long story involving some stupidity on my part), but it’s got some really useful contents:
==> 2016-06-07 22:41:06 <== # cmd: /Users/robin/anaconda3/bin/conda create --name hotbar python=2.7 openssl-1.0.2h-1 pip-8.1.2-py27_0 python-2.7.11-0 readline-6.2-2 setuptools-22.0.5-py27_0 sqlite-3.13.0-0 tk-8.5.19-0 wheel-0.29.0-py27_0 zlib-1.2.8-3 # create specs: ['python 2.7*'] ==> 2016-06-07 22:46:28 <== # cmd: /Users/robin/anaconda3/envs/hotbar/bin/conda install matplotlib numpy scipy ipython jupyter mahotas statsmodels scikit-image pandas gdal tqdm -sqlite-3.13.0-0 +appnope-0.1.0-py27_0 +backports-1.0-py27_0 ...
Specifically, it doesn’t just give you the list of what was installed, uninstalled or upgraded – but it also gives you the commands you ran! If you want, you can extract these commands with a bit of command-line magic:
cat ~/anaconda3/envs/hotbar/conda-meta/history | grep '# cmd' | cut -d" " -f3-
/Users/robin/anaconda3/bin/conda create --name hotbar python=2.7 /Users/robin/anaconda3/envs/hotbar/bin/conda install matplotlib numpy scipy ipython jupyter mahotas statsmodels scikit-image pandas gdal tqdm /Users/robin/anaconda3/envs/hotbar/bin/conda install -c conda-forge rasterio
(For reference, the command-line magic gets the content of the history
file, searches for all lines starting with # cmd
, and then splits the line by spaces and extracts everything from the 3rd group onwards)
I find environment.yml
files to be a bit of a pain sometimes (they’re not always cross-platform compatible – see this issue), so this is quite useful as it actually gives me the commands that I ran to create the environment.
If you found this post useful, please consider buying me a coffee.
This post originally appeared on Robin's Blog.
Categorised as: Programming, Python
nice feature! I use Anaconda as well and am happy to see that there is an efficient method to view the changelog and an undo option.
This is a great feature, but beware of the potential of removing the current ~/anaconda3/bin/conda without replacing it. If the most recent install changed conda and there is not a conda change in the revision that you are rolling back to, this will happen. Look through your revisions to find the previous conda. This seems to be a common issue and happened to me w/ conda 4.3.21-py36_1 and an installation in my home directory (not site install w/ administrator permissions. It would be good to know how conda computes the list. revisions. https://github.com/conda/conda/issues/1733
Be careful — currently rolling back to an earlier revision (via install –revision #) often only removes packages without installing older ones.
conda list -revisions
conda install -revision N
That worked pretty good for me. I was in revision 6 and had to try back to revision 2. Luckly this was a fairly complete revision.
Thank mate
conda revisions don’t show modifications made after a change to the environment that was made by pip..
perhaps pip changes can’t also be rolled back?
Heads up that conda was hanging there for a while after I entered the revision command. But it ultimately worked!
Hey! Thanks for the article. I am trying to revert to an older version of my environment, but I get the following error “PackagesNotFoundError: The following packages are missing from the target environment:” with a list of packages. I am not sure how what to do about it.
Thanks this was really helpful. Just incase others run into the PackagesNofFoundError mentioned in one of the comments, you can and -c channel to the command e.g. -c conda-forge if you have used non-default channels for previous packages.