72

I have too many files in .m2 folder where maven stores downloaded dependencies. Is there a way to clean all old dependencies? For example, if there is a dependency with 3 different versions: 1, 2 and 3, after cleaning there must be only 3rd. How I can do it for all dependencies in .m2 folder?

anuj pradhan
  • 2,419
  • 4
  • 23
  • 30
Cherry
  • 25,428
  • 40
  • 160
  • 286
  • 3
    Simply delete the `.m2repository` folder. It will get created automatically once you compile the project. – user2339071 Oct 11 '13 at 05:17
  • 3
    or buy bigger hard drive and dont care :) – smajlo Oct 11 '13 at 05:20
  • 9
    May be there is more elegant solution than wait for compilation and spent money to hard drive? :) **But seriously**, I work remotely on virtual machine, so disk space (small) and compilation time (long) are significant. That's why I can not simply change HDD or processor. So I need a way to use it more effectively. – Cherry Oct 11 '13 at 05:31
  • If you have the IDE opened as well as ALL your recent projects, the filesystem locks will prevent you from deleting the jars in use – digital illusion Sep 11 '14 at 15:41
  • How can cleaning of dependencies be achieved through pom file? – Tushar Banne Apr 21 '16 at 05:11
  • where does .m2repository folder located? – S Gaber Sep 28 '18 at 10:02

10 Answers10

41

If you are on Unix, you could use the access time of the files in there. Just enable access time for your filesystem, then run a clean build of all your projects you would like to keep dependencies for and then do something like this (UNTESTED!):

find ~/.m2 -amin +5 -iname '*.pom' | while read pom; do parent=`dirname "$pom"`; rm -Rf "$parent"; done

This will find all *.pom files which have last been accessed more than 5 minutes ago (assuming you started your builds max 5 minutes ago) and delete their directories.

Add "echo " before the rm to do a 'dry-run'.

Florian
  • 2,803
  • 1
  • 24
  • 26
  • 19
    On OSX (could work on GNU tools too) `find ~/.m2/repository/ -atime +30 -iname '*.pom' -print0 | while read -d '' -r pom; do echo rm -rf "$(dirname $pom)"; done` where `atime` is in days (compared to `amin` in minutes) – Brice May 27 '15 at 16:28
  • 2
    I use `find ~/.m2 -atime +1w -iname '*.pom' | while read pom; do parent=$(dirname "$pom"); rm -rf "$parent"; done` which works for me on OSX. Should work fine on other unixes as well :) – Meeh May 22 '17 at 12:14
  • I just fell in love with "find" – Jonas Eicher May 23 '19 at 13:49
31

Short answer - Deleted .m2 folder in {user.home}. E.g. in windows 10 user home is C:\Users\user1. Re-build your project using mvn clean package. Only those dependencies would remain, which are required by the projects.

Long Answer - .m2 folder is just like a normal folder and the content of the folder is built from different projects. I think there is no way to figure out automatically that which library is "old". In fact old is a vague word. There could be so many reasons when a previous version of a library is used in a project, hence determining which one is unused is not possible.

All you could do, is to delete the .m2 folder and re-build all of your projects and then the folder would automatically build with all the required library.

If you are concern about only a particular version of a library to be used in all the projects; it is important that the project's pom should also update to latest version. i.e. if different POMs refer different versions of the library, all will get downloaded in .m2.

Gyanendra Dwivedi
  • 5,105
  • 1
  • 23
  • 49
  • "hence determining which one is unused is not possible'. I need not this determination I need to leave only new versions. – Cherry Oct 14 '13 at 10:48
  • 2
    Then delete .m2 folder and then make sure that all the projects are having only new versions of jar entry in pom.xml. Re-build the project. The .m2 folder will remain with only latest version. – Gyanendra Dwivedi Oct 15 '13 at 04:10
  • 1
    `delete .m2` it leads to delete all dependencies and to download new ones from repository which is extremelly slow. – Cherry Jan 09 '15 at 08:51
  • For the stated problem - one solution fit for all - we could go with above way. For the problem of slowness, I would recommend that the project should consult to a local repo (kind of a prod repository setup in organization); if not available download from public repository. At some point of time, it is recommended that the artifact is eventually uploaded to local repository - if it is so widely used in all the projects. – Gyanendra Dwivedi Jan 12 '15 at 20:13
20

Given a POM file for a maven project you can remove all its dependencies in the local repository (by default ~/.m2/respository) using the Apache Maven Dependency Plugin.

It includes the dependency:purge-local-repository functionality that removes the project dependencies from the local repository, and optionally re-resolve them.

To clean the local dependencies you just have to used the optional parameter reResolve and set it to false since it is set to true by default.

This command line call should work:

mvn dependency:purge-local-repository -DreResolve=false
NoobEditor
  • 14,239
  • 13
  • 66
  • 102
Juanjo Marron
  • 251
  • 2
  • 5
  • 3
    Good :) But this cleanup dependecies only for current project, not all repository. – Cherry Nov 13 '14 at 02:21
  • 3
    That's true! To cleanup the whole repository I would go manually and remove directories from ./m2/repository as was commented before or in newer versions of Nexus (after 2.6.4-02.) they provide the Scheduled task [link](http://blog.sonatype.com/2009/09/nexus-scheduled-tasks/#.VGUD52NGWdA) Remove Releases From Repository capability out of the box. It could be also useful – Juanjo Marron Nov 13 '14 at 19:26
6
  1. Download all actual dependencies of your projects

    find your-projects-dir -name pom.xml -exec mvn -f '{}' dependency:resolve
    
  2. Move your local maven repository to temporary location

    mv ~/.m2 ~/saved-m2
    
  3. Rename all files maven-metadata-central.xml* from saved repository into maven-metadata.xml*

    find . -type f -name "maven-metadata-central.xml*" -exec rename -v -- 's/-central//' '{}' \;
    
  4. To setup the modified copy of the local repository as a mirror, create the directory ~/.m2 and the file ~/.m2/settings.xml with the following content (replacing user with your username):

    <settings>
     <mirrors>
      <mirror>
       <id>mycentral</id>
       <name>My Central</name>
       <url>file:/home/user/saved-m2/</url>
       <mirrorOf>central</mirrorOf>
      </mirror>
     </mirrors>
    </settings>
    
  5. Resolve your projects dependencies again:

    find your-projects-dir -name pom.xml -exec mvn -f '{}' dependency:resolve
    
  6. Now you have local maven repository with minimal of necessary artifacts. Remove local mirror from config file and from file system.

thibr
  • 577
  • 5
  • 13
Sergey B.
  • 93
  • 1
  • 7
  • Tried this, still got: "No plugin found for prefix 'dependency' in the current project and in the plugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the repositories [local (/home/user/.m2/repository), mycentral (file:/home/user/saved-m2/)]" – Robert Mikes Feb 20 '17 at 12:44
5

I came up with a utility and hosted on GitHub to clean old versions of libraries in the local Maven repository. The utility, on its default execution removes all older versions of artifacts leaving only the latest ones. Optionally, it can remove all snapshots, sources, javadocs, and also groups or artifacts can be forced / excluded in this process. This cross platform also supports date based removal based on last access / download dates.

https://github.com/techpavan/mvn-repo-cleaner

Pavan Kumar
  • 3,041
  • 22
  • 39
4

It's been more than 6 years since the question was asked, but I didn't find any tool to clean up my repository. So I wrote one myself in python to get rid of old jars. Maybe it will be useful for someone:

from os.path import isdir
from os import listdir
import re
import shutil

dry_run = False #  change to True to get a log of what will be removed
m2_path = '/home/jb/.m2/repository/' #  here comes your repo path
version_regex = '^\d[.\d]*$'


def check_and_clean(path):
    files = listdir(path)
    for file in files:
        if not isdir('/'.join([path, file])):
            return
    last = check_if_versions(files)
    if last is None:
        for file in files:
            check_and_clean('/'.join([path, file]))
    elif len(files) == 1:
        return
    else:
        print('update ' + path.split(m2_path)[1])
        for file in files:
            if file == last:
                continue
            print(file + ' (newer version: ' + last + ')')
            if not dry_run:
                shutil.rmtree('/'.join([path, file]))


def check_if_versions(files):
    if len(files) == 0:
        return None
    last = ''
    for file in files:
        if re.match(version_regex, file):
            if last == '':
                last = file
            if len(last.split('.')) == len(file.split('.')):
                for (current, new) in zip(last.split('.'), file.split('.')):
                    if int(new) > int(current):
                        last = file
                        break
                    elif int(new) < int(current):
                        break
            else:
                return None
        else:
            return None
    return last


check_and_clean(m2_path)

It recursively searches within the .m2 repository and if it finds a catalog where different versions reside it removes all of them but the newest.

Say you have the following tree somewhere in your .m2 repo:

.
└── antlr
    ├── 2.7.2
    │   ├── antlr-2.7.2.jar
    │   ├── antlr-2.7.2.jar.sha1
    │   ├── antlr-2.7.2.pom
    │   ├── antlr-2.7.2.pom.sha1
    │   └── _remote.repositories
    └── 2.7.7
        ├── antlr-2.7.7.jar
        ├── antlr-2.7.7.jar.sha1
        ├── antlr-2.7.7.pom
        ├── antlr-2.7.7.pom.sha1
        └── _remote.repositories

Then the script removes version 2.7.2 of antlr and what is left is:

.
└── antlr
    └── 2.7.7
        ├── antlr-2.7.7.jar
        ├── antlr-2.7.7.jar.sha1
        ├── antlr-2.7.7.pom
        ├── antlr-2.7.7.pom.sha1
        └── _remote.repositories

If any old version, that you actively use, will be removed. It can easily be restored with maven (or other tools that manage dependencies).

You can get a log of what is going to be removed without actually removing it by setting dry_run = False. The output will go like this:

update /org/projectlombok/lombok
1.18.2 (newer version: 1.18.6)
1.16.20 (newer version: 1.18.6)

This means, that versions 1.16.20 and 1.18.2 of lombok will be removed and 1.18.6 will be left untouched.

The file can be found on my github (the latest version).

Andronicus
  • 23,098
  • 14
  • 38
  • 73
  • 1
    Nice Script, Thank you so much, that was exactly what i was looking for. Best answer in my opinion. – Tobi Feb 09 '21 at 13:37
1

I wanted to remove old dependencies from my Maven repository as well. I thought about just running Florian's answer, but I wanted something that I could run over and over without remembering a long linux snippet, and I wanted something with a little bit of configurability -- more of a program, less of a chain of unix commands, so I took the base idea and made it into a (relatively small) Ruby program, which removes old dependencies based on their last access time.

It doesn't remove "old versions" but since you might actually have two different active projects with two different versions of a dependency, that wouldn't have done what I wanted anyway. Instead, like Florian's answer, it removes dependencies that haven't been accessed recently.

If you want to try it out, you can:

  1. Visit the GitHub repository
  2. Clone the repository, or download the source
  3. Optionally inspect the code to make sure it's not malicious
  4. Run bin/mvnclean

There are options to override the default Maven repository, ignore files, set the threshold date, but you can read those in the README on GitHub.

I'll probably package it as a Ruby gem at some point after I've done a little more work on it, which will simplify matters (gem install mvnclean; mvnclean) if you already have Ruby installed and operational.

Geoffrey Wiseman
  • 4,632
  • 3
  • 28
  • 46
  • Glad to hear it. Guess I should go to the trouble of making it into a gem. – Geoffrey Wiseman Oct 16 '15 at 21:43
  • it seems I spoke too soon. I don't know the pattern - but some of the jars got deleted although I know I had used them recently. But, at the same time, some remained. – catholicon Oct 17 '15 at 12:32
  • Hm. Well, if you're able to give me more specifics, I'd be happy to look into it. If you get that far, file an issue on GitHub for me to track. Seems to be working fairly consistently for me, but there could be something specific for Cygwin I need to look into, for instance. Did you look at the list it outputted before agreeing, or was it too long to be worth the review? If you do get around to trying it again, would it help if I added the last-used date to the summary? (https://github.com/geoffreywiseman/mvnclean/issues/10) – Geoffrey Wiseman Oct 18 '15 at 15:19
  • yeah, sure you can add some option to dump debug output (jar:last access date)... I've subscribed the issue you've opened. – catholicon Oct 19 '15 at 02:28
  • Updated; take a look at the issue, describes some of your options. – Geoffrey Wiseman Oct 20 '15 at 15:00
  • Out of curiosity, did you ever try this again? – Geoffrey Wiseman Feb 03 '16 at 14:15
  • no sorry I didn't get around to try it again. I have it at the back of my mind though :). – catholicon Feb 03 '16 at 20:59
1

Just clean every content under .m2-->repository folder.When you build project all dependencies load here.

In your case may be your project earlier was using old version of any dependency and now version is upgraded.So better clean .m2 folder and build your project with mvn clean install.

Now dependencies with latest version modules will be downloaded in this folder.

  • 2
    Unless you had legacy jars added manually to the repository, or the dependencies are no longer available in the internet. This answer is a bit dangerous... at least back up first! – Jose Manuel Gomez Alvarez Nov 17 '16 at 10:10
0

You need to copy the dependency you need for project. Having these in hand please clear all the <dependency> tag embedded into <dependencies> tag from POM.XML file in your project.

After saving the file you will not see Maven Dependencies in your Libraries. Then please paste those <dependency> you have copied earlier.

The required jars will be automatically downloaded by Maven, you can see that too in the generated Maven Dependencies Libraries after saving the file.

Thanks.

0

I did spend some hours looking at this problem and to the answers, many of them rely on the atime (which is the last access time on UNIX systems), which is an unreliable solution for two reasons:

  1. Most UNIX systems (including Linux and macOS) update the atime irregularly at best, and that is for a reason: a complete implementation of atime would imply the whole file system would be slowed down by having to update (i.e., write to the disk) the atime every time a file is read, moreover having a such an extreme number of updates would very rapidly wear out the modern, high performance SSD drives
  2. On a CI/CD environment, the VM that's used to build your Maven project will have its Maven repository restored from a shared storage, which in turn will make the atime get set to a "recent" value

I hence created a Maven repository cleaner and made it available on https://github.com/alitokmen/maven-repository-cleaner/. The bash maven-repository-cleaner.sh script has one function, cleanDirectory, which is a recursive function looping through the ~/.m2/repository/ and does the following:

  • When the subdirectory is not a version number, it digs into that subdirectory for analysis
  • When a directory has subdirectories which appear to be version numbers, it only deletes all lower versions

In practice, if you have a hierarchy such as:

  • artifact-group
    • artifact-name
      • 1.8
      • 1.10
      • 1.2

... maven-repository-cleaner.sh script will:

  1. Navigate to artifact-group
  2. In artifact-group, navigate to artifact-name
  3. In artifact-name, delete the subfolders 1.8 and 1.2, as 1.10 is superior to both 1.2 and 1.8

This is hence very similar to the solutions Andronicus and Pavan Kumar have provided, the difference is that this one is written as a Shell script. To run the tool on your CI/CD platform (or any other form of UNIX system), simply use the below three lines, either at the beginning or at the end of the build:

wget https://raw.githubusercontent.com/alitokmen/maven-repository-cleaner/main/maven-repository-cleaner.sh
chmod +x maven-repository-cleaner.sh
./maven-repository-cleaner.sh
alitokmen
  • 11
  • 1