Personally, I never had any problems with the SFDX CLI, which is why I was surprised they were replacing it with the SF CLI. What I now sometimes struggle with is translating all of my cheat sheet references from one to the other, and the sifting through the plethora of search results that still refer to the SFDX way of doing things. OK, I know I can minimize the second part by setting the date range in my Google searches, but when I’m being lazy (or in a hurry, both of which are more common than I prefer) I use Perplexity.ai rather than Google.
Most recently my conversion conundrum cropped up with removing components that I had deployed through the CLI. I found a great SFDX syntax in Perplexity literally one day before it was slated to be retired. Here is the relevant part of the session that got me to the solution:
Question: cli to delete objects from an org
Answer:To delete objects from a Salesforce org using the CLI, you can use the destructive changes process. Here’s how to do it:Step 1: Create Destructive Changes XML
Create a file nameddestructiveChanges.xml
with the following structure:<?xml version="1.0" encoding="UTF-8"?> <Package xmlns="http://soap.sforce.com/2006/04/metadata"> <types> <members>ObjectName1__c</members> <members>ObjectName2__c</members> <name>CustomObject</name> </types> </Package>ReplaceObjectName1__c
andObjectName2__c
with the API names of the objects you want to delete.Step 2: Create Empty Package XML
Create a file namedpackage.xml
with the following content:xml <?xml version="1.0" encoding="UTF-8"?> <Package xmlns="http://soap.sforce.com/2006/04/metadata"> <version>62.0</version> </Package>Step 3: Deploy Destructive Changes
Run the following Salesforce CLI command:bash sfdx force:mdapi:deploy -d . -w -1 -u YourOrgAliasThis command deploys the destructive changes to your org:
-d .
specifies the current directory as the deployment source-w -1
waits for the deployment to finish-u YourOrgAlias
specifies the target org aliasAdditional Considerations
- Ensure you have the necessary permissions to delete objects in your org.
- Deleting objects will also delete all associated records and metadata (fields, validation rules, etc.).
- Some objects may have dependencies that prevent deletion. You might need to remove these dependencies first.
- Always test this process in a sandbox environment before applying it to production.
- Consider backing up your metadata and data before performing destructive changes.
If you need to delete other types of metadata (like Apex classes, Visualforce pages, etc.), you can include them in thedestructiveChanges.xml
file using the appropriate metadata type names.Remember, this process permanently deletes the specified objects and their data from your org, so use it with caution.
When I ran it, it worked perfectly, and output a warning that it would no longer work the next day (I did not preserve the message content, but I can tell you the date was 11/4/24 because UpNote metadata is useful). As I mentioned, I’m often in a hurry, so I often make mistakes, and what has kept me in technology since the original Wolfenstein was released is always making sure I have a way of undoing whatever I do. So I decided to go find the cool new sf CLI solution. Which was not terribly clear to me. I found the documentation a bit confusing. Going back to the old-fashioned Google search (trust me, it pains me more to write “old-fashioned Google search” than it does for you to read it), I found a Trailblazer Community post by Max Goldfarb that greatly clarified how to make the new sf call.
I have since refined the process clarified by Max once I read the documentation while in less than my usually rushed efforts. First, I keep that step 2 XML that Perplexity gave me stored in my repo as antiPackage.xml, the full path being manifest\destructiveArchive\antiPackage.xml. I could then generate the destructive xml with:
sf project generate manifest --source-dir force-app/main/default/[WHATEVER-I-WANT-TO-DESTROY] --type destroy
and then run my simplified killer command:
sf project deploy start --manifest manifest/destructiveArchive/antiPackage.xml --pre-destructive-changes manifest/destructiveArchive/destructiveChangesALL.xml -o [ALIAS]
and boom! stuff removed. I even keep a set of destructive xmls in a special folder (you may have noticed it in the command above). I continued to use this happily for a few weeks.
Today I was messing with a single component that was giving me problems (or, more accurately, I was giving it problems by building it incorrectly) and started by removing just it. Then I went about making my fixes and, feeling less hectic than usual, decided to have a package.xml just for it so the deployment would go faster (yes, I know I can do that with a right-click, but once I am comfortable with a CLI, I prefer it, and it lets me make sure that my eventual release script will have fewer issues). It was very small, which made the content leap out at me more, and, so I realized…There is no difference between the XML output with or without the “–type destroy” switch!
So now I just keep one XML for each context in manifest\deployArchive and reference it for both deploy and destroy.
© Scott S. Nelson