Fun with the Migration Tool

Fun with the Migration Tool

If you haven’t used the migration tool to move metadata from one org to another you are missing out. While there are several ways to move metadata between orgs the migration tool is powerful and a great addition to your Salesforce toolbelt.

There are tons of resources to get you going. This one will get you a grasp of what you are working with and this has the list of metadata types you can retrieve and deploy.

When working with Salesforce to migrate metadata the migration tool synonymously referred to as Ant. Getting your machine setup involves Java, the Ant build tool, and the migration tool jar.

After you install all the prerequisites and get migration tool working the TLDR main pieces are:

  • ant-salesforce.jar: allows you to use ant to interact with the Salesforce metadata API
    • Every release has a new version which relates to the release API 
  • your credentials and login endpoints
  • build.xml: the commands[targets] you can run
  • package.xml: your list of metadata to retrieve or deploy
  • destructiveChanges.xml: remove metadata from your org, separate from deploy
  • destructiveChangesPre.xml: remove metadata before your package deploys
  • destructiveChangesPost.xml: remove metadata after your package deploys

As you work with retrieving and deploying metadata you will find and possibly build a few things that are a little less used but still certainly useful.

A few I’m going to talk about here are:

  • listMetadata
  • Retrieving the package.xml of a change set
  • Retrieving foldered metadata like reports
  • Execute a shell script from an ant build.xml

There may be several ways to get this kind of information but this can be another tool you put in your tool box.


After you’ve used the retrieve and deploy tasks, which you will use a lot, look at the readme for some other less commonly used but powerful tasks like listMetadata.

I used listMetadata this week to get a specific list of CustomMetadata. I entered the metadataType as CustomMetadata in my build.xml for the target listMetadata.

From the command line I executed that target

$ ant listMetadata

Which gave me an output listing all the CustomMetadata in my org with the following format

[sf:listMetadata] FileName: customMetadata/
[sf:listMetadata] FullName/Id: Mapping.Education_Call/m02c00000007XyOAAU
[sf:listMetadata] Manageable State: unmanaged
[sf:listMetadata] Namespace Prefix: null
[sf:listMetadata] Created By (Name/Id): David Meyer/00541000002a2BUAAY
[sf:listMetadata] Last Modified By (Name/Id): David Meyer/00541000002a2BUAAY


I used that to filter what I was looking for and output only the Names I was interested in.
I’ve found this useful to quickly get a list of metadata to include in my package.xml
Sometimes the member names are not straightforward with some characters needing to be encoded in your package.xml

profile name

listMetadata is quick way to get exactly that, lists of different metadata types in your org which you can use in a variety of ways. Share with your friends, build into scripts, whatever you like.


Retrieving the package.xml of a change set

You may have some colleagues that put together a massive change set to move from one org to another and now you want to move that same stuff from the org it was moved to on to a third org. Instead of rebuilding a change set you can get the content of that change set. The package.xml that could be used as well as the current state of the metadata associated to that package.xml

Get the name of your Change Set

change set name

Create a target in your build.xml that creates a directory and retrieves the Named Package

retrieve named Package/change set

Execute your target from the command line

retrieve namedPackage

Which will retrieve a package.xml and the metadata listed in the Change Set

retrieved namedPackage


Retrieving foldered metadata like reports

Looking at the metadata types you can retrieve you will notice some are allowed to be retrieved with a wildcard, ApexClass, and others have to be explicitly listed, CustomLabel.

Others like reports need even more detail. The name of the report and the name of the folder.

The challenge is to get the reports and the folders.

On my Mac I am going to use a shell script, some templates, the listMetadata task, and a bulkRetrieve task to retrieve all the report folders and the reports they contain.

We’ll use listMetadata to retrieve all the report folders using the ReportFolder metadata type. Once we’ve got all the folders we’ll loop through that list using bulkRetrieve to get all the reports in that folder. Each call using bulkRetrieve generates a package.xml for that folder so after we’ve retrieved all the reports for all the folders we’ll traverse our foldered directories and build a package.xml that includes all the Reports/files.

You can find the code on github.

To get started, I navigate to the directory where my files are located

open and populate my credentials along with the path to my ant-salesforce.jar jar.location

open a terminal window and execute the script passing as a parameter the type of foldered metadata you want to retrieve [Report,EmailTemplate,Dashboard,Document]

cmd line run script

The script puts the passed in parameter $1 in the ‘which’ variable

We define:
which api version number to be used in scripts
tmpPkgXml: the file we will use to build our ultimate package.xml
buildFile: this will contain a target with all our bulkRetrieve commands to get the foldered metadata
srcPath: the path where we will retrieve our metadata to

The line that starts with folders=( makes listMetadata call using the file get-folders.xml.

The result of the call is that all the folders for the specified metadata type are stored as an array in ‘folders’

We iterate through the array

adding bulkRetrieve tasks for each folder to get-Reports.xml

Then we execute the target retrieveType we just built. Retrieving all the reports

Finally we write the beginning of our final package.xml
Traverse all the files and write the members to our package.xml
and close our package


Execute a shell script from an ant build.xml

Now that we can run this shell script to get our metadata we may want to invoke it from an ant process. To do that we could add a target[run-getAllsh] to a build xml specifying the path to our script and the argument we’ve been passing [Report]

run shell from build xml


All good fun with the migration tool, ant, and a shell script.


Phone: 312-602-4000
222 W. Adams
Chicago, IL 60606
Show Buttons
Share On Facebook
Share On Twitter
Share on LinkedIn
Hide Buttons