SFDX and Git exercises for beginners
18 Nov 2022
Congratulations – you have a new job at Banana Stand Corporation!
The company’s primary production Salesforce org lives at https://bananastand.my.salesforce.com/
, with important sandboxes at https://bananastand--staging.sandbox.my.salesforce.com/
and https://bananastand--dev.sandbox.my.salesforce.com/
.
The most important shared Git repository corresponding to https://bananastand.my.salesforce.com/
lives at https://github.com/BananaStandCompany/salesforce_primary/
.
- Q: How do you successfully enhance these live Salesforce orgs without irritating colleagues who also use
https://github.com/BananaStandCompany/salesforce_primary/
? - A: Read on!
Train your mind to disconnect Git from Salesforce
Git is a bubble
Git was popularized by people who write code by hand, on their computers, and who work with magical systems that turn copies of that code, as found on shared URLs like GitHub.com, into live websites.
They’re accustomed to this one-way “magic” of “I put it on GitHub and then our website does what I thought it would based on the code I wrote!” because they don’t even have an alternative way to edit the website’s configuration.
They’re working with websites that don’t have anything even remotely comparable Salesforce’s admin-configurable “Setup” webpages like https://bananastand.my.salesforce.com/setup/forcecomHomepage.apexp
.
“Write it on your computer, put the stuff you wrote on your computer onto GitHub, wait 5 minutes, and admire the changes you made to a website” is the way almost all people who write about Git on the internet spend their lives.
Heck, that’s exactly how I published this blog article onto my website.
- I made a new file for this article on my hard drive.
- Using Git software running on my desktop computer, I tracked the addition of the new file as an important “commit” and commented a brief note about why I added the new file.
- Using Git software running on my desktop computer, I uploaded it to GitHub.
- 5 minutes later the article was live on my website, available for you to read.
When you search the internet for advice about Git, you’re going to see a lot of this kind of person shouting, “Git is great! Git is magic! Storing copies of files onto GitHub is how I change the configuration of running websites!”
And that’s it.
They’ll talk about Git like it’s this standalone thing that lives in a bubble.
Because for them, it does live in a bubble.
You can try Git as a bubble
To help you better understand articles you find on the internet about Git, I highly recommend familiarizing yourself with the bubble-world that most Git developers live in by reading the first article I ever wrote about Git when I was learning it trying my Git and GitHub exercises for beginners.
Live like the Git bubblers
If you’re suuuuper curious to experience the “and then a website appears – it’s magic!” part of “how the other half lives” (ahem – not us Salesforce folks, except the ones experienced at using fancy “DevOps” tooling), follow this beginner-oriented Git-to-website tutorial to spend a few minutes as a “classic Git-based web developer.”
Salesforce is a different bubble
The problem, for Salesforce people, is that the paradise described above is not at all how updating live-on-the-internet Salesforce website configuration works.
The “real code” that runs a live-on-the-internet https://bananastand.my.salesforce.com/
Salesforce org’s website (much of which was probably configured by admins clicking around that website) doesn’t live on GitHub or any of GitHub’s competitors.
The “real code” lives deep in a server room in San Francisco under Salesforce Tower.
(Not really, but you can think of it that way.)
- For decades, Salesforce has offered admins and developers lots of ways to download a copy of the Salesforce-Tower-basement to their own computers using:
- software like the Salesforce CLI
- various VSCode / IntelliJ plugins that run on top of the Salesforce CLI
- websites like Workbench
- For decades, Salesforce has also offered admins and developers lots of ways to upload new configurations into the Salesforce-Tower-basement from their own computers, as an alternative to clicking around
https://bananastand.my.salesforce.com/
’s Setup, admin-style, using:- software like the Salesforce CLI
- various VSCode / IntelliJ plugins that run on top of the Salesforce CLI
- websites like Workbench
But at no point does https://bananastand.my.salesforce.com/
(and the Salesforce-Tower-basement “real code” keeping it live on the internet) ever, ever, ever inherently have anything to do with any files that Banana Stand Corporation may or may not be hosting on GitHub or GitHub’s competitors.
Nothing at all!
Completely separate from each other!
Well … sort of.
The buzzphrase “DevOps” in the Salesforce space – and all of the tooling supporting the concept like Gearset, Copado, Metecho, and Salesforce DevOps Center – has a whole lot to do with creating an automated 2-way link between files hosted on a website like GitHub and the Salesforce-Tower-basement “real code” keeping an org like https://bananastand.my.salesforce.com/
live on the internet.
But my point is that there’s no inherent relationship between:
- The act of uploading/downloading files between your computer and a site like GitHub.com.
- The act of uploading/downloading files between your computer and Salesforce Tower’s basement.
You are the missing link
The only relationship between the two concepts is that they both happen to involve “your computer.”
Which means that the common link between “Git” and “Salesforce” is YOU.
You and your skill at planning out the order in which you do various uploadey/downloadey things on your computer.
Except when you are not the missing link
That said, in Salesforce-land, depending how much time and money Banana Stand Corporation has invested in “DevOps” practices, you might be able to completely take “your desktop computer” out of the loop and never deal with installing GitHub Desktop or VSCode or IntelliJ on it at all.
You might be able to just click-configure various Salesforce scratch, dev, sandbox, and production orgs in your web browser, admin-style.
It’s possible that Banana Stand Corporation is set up so you can let Gearset, Copado, Metecho, or Salesforce DevOps Center use the Git protocol under the hood and worry about synchronizing your clicky-configurations’ impact upon the basement of Salesforce Tower to and from copies of code hosted on a site like GitHub.
But by default you are the only link
But the relationship status between Salesforce and Git is “it’s complicated” (because technically there isn’t a relationship at all, unless you and your company force one into existence via Gearset/Copado/Metecho/DevOpsCenter-style tooling or via clever use of employees’ desktop computers).
Do I have your attention?
Any questions about the fact that “Git stuff” and “Salesforce stuff” have nothing to do with each other other than the relationships you and your company choose to build between them?
Use SFDX by itself
Install and authenticate SFDX
Install the Salesforce CLI software onto your computer.
Open up the Command Prompt program in Windows (you hit the start menu icon in the lower left, start typing “cmd
,” and press Enter).
Make sure it’s running in the context of some folder you couldn’t care less about, like C:\example
.
(You can do that by typing cd C:\example
and hitting Enter to execute the command.)
(I work a lot in Windows, so this tutorial will use Windows-style folder paths, but most of the instructions should be similar if you know how to follow along on a Mac or Linux box when reading instructions generally geared at creating, editing, and deleting files on Windows.)
Run the following 2 commands (by typing them into the command prompt and hitting Enter) so as to make sure you installed SFDX properly – both should display something like sfdx-cli/#.#.# win32-x64 node-v#.#.#
if you did:
sfdx version
sf --version
Now log the sfdx
command into all your favorite production orgs, sandboxes, dev orgs, etc. that matter to you in your everyday work and “alias” them with names you can easily remember within SFDX.
These logins should persist Windows-wide, which is why I do it from something like C:\example
just to force myself to note that they actually work that way.
First make sure that running this command doesn’t display any orgs at all (presuming you just installed the Salesforce CLI tool):
sfdx auth:list
Then run a bunch of commands in the style of sfdx force:auth:web:login --setalias ... --instanceurl ...
as I’ve documented elsewhere on my blog under “SFDX global authentication and aliasing”.
After you do, try this again:
sfdx auth:list
It should show output more like this:
=== authenticated orgs
ALIAS USERNAME ORG ID INSTANCE URL AUTH METHOD
───────────────────────────────────────────── ──────────────────────────────────── ────────────────── ──────────────────────────────────────────────────────────────────── ───────────
bananastandprod [email protected] 00D111111111111111 https://bananastandcorp.my.salesforce.com web
bananastandsandboxstaging [email protected] 00D222222222222222 https://bananastandcorp--staging.sandbox.my.salesforce.com web
bananastandsandboxdev [email protected] 00D333333333333333 https://bananastandcorp--dev.sandbox.my.salesforce.com web
devorgcreated20220101 [email protected] 00D444444444444444 https://example1-d9-dev-ed.my.salesforce.com web
devorgcreated20220606 [email protected] 00D555555555555555 https://examplecom-d8-dev-ed.my.salesforce.com web
Should return empty at first.
You can close your Windows command prompt now.
Set up a folder for your SFDX play
Create a new empty folder on your computer called c:\example\sfdxplay1\
.
Within that folder, create a new file called sfdx-project.json
and populate it with contents something like this (you’ll probably want to update the Salesforce version number to match the time that you’re reading this article, and know that different corporations have different tendencies with the value they put in “path,” but the most common choices are “force-app” and “src”):
{
"packageDirectories": [
{
"path": "force-app",
"default": true
}
],
"namespace": "",
"sourceApiVersion": "56.0"
}
Note that if you ever run sf
or sfdx
commands in a command-line tool whose current folder context isn’t at or below some folder containing an sfdx-project.json
file, a lot of them will error out with the following message:
RequiresProjectError: This command is required to run from within a Salesforce project directory.
Code: RequiresProjectError
Next, if you chose “force-app
” as the value for “path
” inside sfdx-project.json
, create an empty c:\example\sfdxplay1\force-app
folder. (Or c:\example\sfdxplay1\src\
if you chose “src
,” etc.)
If you miss this step, many sf
and sfdx
commands will error out with the following message:
Error (1): The path "force-app", specified in sfdx-project.json, does not exist. Be sure this directory is included in your project root.
Download code from Salesforce to your computer
Warning: Do not do these exercises aginst corporate production orgs or important corporate sandboxes.
If, when you were connecting the sfdx
command line tool to your favorite Salesforce orgs, you didn’t throw in some dev orgs that only you have access to, now’s the time to go back and do that.
Create field 1 in org 1 and download it
In a web browser, open one of your dev orgs (I’ll start with the one I aliased “devorgcreated20220101
” within SFDX) in a web browser and add a new checkbox field to the Contact object called “Custom Field 1
” (give it an API name of “Custom_Field_1__c
”.)
Again, open up the Command Prompt program in Windows (you hit the start menu icon in the lower left, start typing “cmd
,” and press Enter).
Make sure it’s running in the context of c:\example\sfdxplay1\
.
(Reminder: you can do that by typing cd C:\example\sfdxplay1\
and hitting Enter to execute the command.)
Run the following command, substituting “devorgcreated20220101
” with an alias appropriate to your own dev org, the way you named it when first authenticating SFDX to your favorite orgs:
sfdx force:source:retrieve --metadata CustomField:Contact.Custom_Field_1__c --targetusername devorgcreated20220101
You should see output something like this (I ran this with force-app
in my sfdx-project.json
path
):
Preparing retrieve request... done
=== Retrieved Source
FULL NAME TYPE PROJECT PATH
───────────────────────── ─────────── ───────────────────────────────────────────────────────────────────────────
Contact.Custom_Field_1__c CustomField force-app\main\default\objects\Contact\fields\Custom_Field_1__c.field-meta.xml
Opening up the C:\example\sfdxplay1\force-app
folder in Windows File Explorer, I can see that there are a whole lot of folders beneath force-app
now, and that there’s one new file named Custom_Field_1__c.field-meta.xml
buried at the bottom of it.
If you open it up in a text editor like Windows Notepad, you should see that there’s a whole lot of text formatted in the XML punctuation standard that, once you start reading it, looks like it has a whole lot to do with the boxes you checked in your web browser when creating “Custom Field 1
”.
Neat!
Create field 2 in org 2 and download it
In a different web browser, open a different dev orgs (I’ll use the one I aliased “devorgcreated20220606
” within SFDX) in a web browser and add a new checkbox field to the Contact object called “Custom Field 2
” (give it an API name of “Custom_Field_2__c
”.)
Do not use the same dev org you used earlier.
This is an exercise in showing you how easy it is to get topsy-turvy with Salesforce upload-downloads involving your computer, so we’re going to do some topsy-turvy things on purpose.
Go back to your Windows command prompt that’s running in the context of c:\example\sfdxplay1\
.
Run the following command, substituting “devorgcreated20220606
” with an alias appropriate to your second dev org, the way you named it when first authenticating SFDX to your favorite orgs:
sfdx force:source:retrieve --metadata CustomField:Contact.Custom_Field_2__c --targetusername devorgcreated20220606
Preparing retrieve request... done
=== Retrieved Source
FULL NAME TYPE PROJECT PATH
───────────────────────── ─────────── ───────────────────────────────────────────────────────────────────────────
Contact.Custom_Field_2__c CustomField force-app\main\default\objects\Contact\fields\Custom_Field_2__c.field-meta.xml
Contemplate the consequences
Open up the c:\example\sfdxplay1\force-app\main\default\objects\Contact\fields\
folder in Windows File Explorer.
This is weird, right? You’ve got just one computer on your folder with 2 files in it that, due to their very existence in the same folder on your computer, you’d presume have something to do with each other, right?
- Custom_Field_1__c.field-meta.xml
- Custom_Field_2__c.field-meta.xml
And yet, you know in your heart of hearts that those two fields have “nothing to do with each other” and “belong in two unrelated orgs.”
So, wow, what a mess that they’re sitting on your computer in the same folder as each other. The nerve!
Sit with the mess you’ve just made for a moment.
Give it a few breaths.
Think about when it might be a disaster, or how it might be a blessing.
Pros
The truth of the matter is, sometimes people do this sort of thing on purpose.
- Maybe they want to quickly criss-cross a copy of each field into the other org using the
sfdx force:source:deploy
command so that both orgs will have both fields in them.- (Ahem – that sounds like a terrible release management strategy in real life.)
- Nevertheless, off the top of my head (I didn’t test these), if you want to try it yourself, I think the commands would be:
sfdx force:source:deploy --metadata CustomField:Contact.Custom_Field_2__c --targetusername devorgcreated20220101
to put “field #2” into “dev org #1”.- After running it, you should be able to open dev org #1 in a web browser, go to Setup, and find field #2 in the Contact custom fields, alongside the field #1 you’d already created.
sfdx force:source:deploy --metadata CustomField:Contact.Custom_Field_1__c --targetusername devorgcreated20220606
to put “field #1” into “dev org #2”.- After running it, you should be able to open dev org #1 in a web browser, go to Setup, and find field #1 in the Contact custom fields, alongside the field #2 you’d already created.
- Maybe they’re about to start work making a brand new standalone installable package for the AppExchange, and they know that they’ve got some great previous work they’d like to include, cherry-picking copies of their best work from various orgs they’ve played with in the past.
- (This is a much more realistic, responsible use case for doing this sort of thing on purpose.)
Cons
Usually, people do this sort of thing on accident.
It can become a really big accident when, instead of a nice little empty c:\example\sfdxplay1\
folder, you were working in a huge folder full of a lot of code.
- What if you thought you were downloading copies of a “
playground
” sandbox’s configuration, editing them on your hard drive, and then uploading the changes back to the same “playground
” sandbox, but you were accidentally actually uploading everything on your hard drive to the “staging
” sandbox?
Oops.
And now, hinting at why I ominously warned that:
The common link between “Git” and “Salesforce” is YOU.
You and your skill at planning out the order in which you do various uploadey/downloadey things on your computer.
- What if this big old folder was tracked with Git, and connected with Git to the shared “
https://github.com/BananaStandCompany/salesforce_primary/
” repository that all of your colleagues depend upon day-to-day? What if you accidentally downloaded a bunch of junk into this folder from a Salesforce org that has nothing at all to do with the project “salesforce_primary
” represents to Banana Stand Corporation?
OOPS.
Use SFDX with Git
If you haven’t yet, read the first article I ever wrote about Git when I was learning it work through all of my Git and GitHub exercises for beginners.
Next, create a new empty folder on your computer called c:\example\sfdxplay2withgit\
. Use GitHub Desktop to track it with Git and “publish” it to a brand new URL on GitHub.com.
Retrace your steps from the “Use SFDX by itself” exercise above, making a hot mess of the contents of c:\example\sfdxplay2withgit\
.
Build it
First, put yourself in the shoes of ordinary “work well done.”
- Use
sfdx force:source:retrieve
– or your favorite IDE like VSCode or IntelliJ, if you’ve already figured out how to hook those up to live Salesforce orgs – to download a nice tidy little representation of at least 10 things about “developer org #1” that feel important to you intoc:\example\sfdxplay2withgit\
– that make you feel like what you’d probably do in the real world if you were trying to save a copy of the work you’d been doing to “developer org #1” on GitHub.com. - Make 1 or more “commits” putting a little bow around your work, publishing them all onto a brand new GitHub URL with GitHub Desktop.
- Open a web browser to your new GitHub URL and validate that you can see all of your hard work organizing backup copies of important features from “developer org #1” into a lovely little internet-hosted codebase.
Break it
Now go imitate yourself being the “oopsie” person.
- Use
sfdx force:source:retrieve
– or your favorite IDE like VSCode or IntelliJ, if you’ve already figured out how to hook those up to live Salesforce orgs – and download at least half a dozen pieces of garbage out of “developer org #2” intoc:\example\sfdxplay2withgit\
.- Even better if some of the names of things overlap with things that also exist in “developer org #1,” so that you’re completely overwriting important work with the wrong stuff entirely.
- Make 1 or more “commits” putting a little bow around your (misguided) work, publishing them all onto the same GitHub URL you already set up in the “build it” step, still using GitHub Desktop.
- Pro tip: having several “commits” will make everything a lot messier for other people to wade their way through trying to figure out what went wrong. Spread your handwork across several commits, just like could happen in the real world when you’re making a mistake over the course of several hours or days!
- Open a web browser to your GitHub URL and validate that the latest codebase is now a hot mess.
Cry over it
Simulate being the “WHAT?!” person.
- The easiest way to do this from 1 computer is to delete
c:\example\sfdxplay2withgit\
and re-clone it afresh from the GitHub URL you set up in the “Build it” step (and deliberately corrupted the contents of in the “Break it” step), just like you did during my Git exercises. - Open up
c:\example\sfdxplay2withgit\
in Windows File Explorer, pretending you’re someone who left off their “work well done” 2 weeks ago and just got back from vacation and just clicked GitHub Desktop’s “Fetch origin” button to bring their own computer’s folder up-to-date with the contents of whatever is now live on GitHub.com. - Spit out your coffee in horror, wondering what all these fields are that make absolutely no sense.
Chat with your colleagues
I know it seems over-the-top to go through all of this work just to prove to yourself that you can make a mess of things when you start playing with Salesforce “metadata” and particularly when you combine that Salesforce work with Git.
Honestly, though, I think it’s really important.
A lot of times, in the physical world, you learn how to assemble things by taking them apart, losing half of the pieces down a floor vent when they rolled off the table, watching a YouTube video, throwing one away, getting another one from the store, repeat, repeat, repeat, until finally you do know various ways of putting it back together when various things go wrong.
Git isn’t just a toaster, though. And neither is Salesforce. And it’s especially no small thing to combine them. (Pablo Gonzalez makes an excellent point that perhaps it’s not even fully possible, for some companies.)
They’re both complex and offer you choices of many ways to achieve similar goals. The choices on offer of how to achieve your goals when you combine them is an even larger array of “all great ways to get to the same place, but you have to choose one.”
That’s not something to suffer through alone with Google and StackOverflow.
That’s decision-making and release management and best practice, and that means it’s collaboration with other people.
Have a fun “make mistakes on purpose” lunch-and-learn with your fellow Salesforce admin/dev colleagues where you all watch each other break things.
- Laugh about it.
- Trade disaster stories from the real world.
- Trade tips about how you configured software on your computer, and about the rules you make yourself obey, that help you stay organized.
- (This article was inspired by my total and abject failure to answer someone’s question of “How do I set up IntelliJ Illuminated Cloud to work against my live Salesforce orgs and my company’s live GitHub.com repository?” I never did figure that out, because I’m not an IntelliJ user, but this article was my attempt to provide a precaution of, “Here are some warmup exercises you can do that will strengthen your ability to know if you broke anything while experimenting.”)
- Use these exercises as a common baseline of “Git knowledge” and “Salesforce metadata knowledge” that allows someone in the room to say, “Okay, so if we did X, Y would break” and everyone would now be on the same page and understand that conversation.
You’re never going to actually combine Salesforce and Git as manually as I had you do in these exercises – don’t worry.
Nevertheless, I think that breaking things on purpose in a safe way is a really great foundation for confidence as you talk about the things your team will actually use.
When your team explores polished ways to use Salesforce Metadata uploads-downloads and/or Git to help you manage Salesforce releases (like Gearset, Copado, Metecho, DevOps Center, CumulusCI, packaging, etc.), you’ll appreciate a little “what they’re all doing under the hood” knowledge so that your team can confidently:
- Decide for yourselves if you “like the way they work” before choosing one.
- Develop internal best practices and training about using one once you’ve chosen it and started working with it.
- Share a common language for troubleshooting, discussing, and fixing things that break over the normal course of business.