git repo design pattern for sfdx projects

Read the answers on What's the best practice for putting multiple projects in a git repository? for some possible solutions (over on Stack Overflow). My biggest concern is that if you end up screwing up something in one of the projects, and you try to fix it, you might end up reversing changes in other projects by accident. If you do decide to follow the path of multiple projects in a single repo, consider using "orphan branches", which will help isolate accidental destructive changes. There's details in the answer linked above and also on git-checkout, look for the --orphan option.

In my personal opinion, you would be better off with separate repositories, because it avoids the possibility that you'll merge something into something else that you didn't mean to do, which can cause an absolute mess of things. While it's "easy" to clean up most mistakes, merging two entire projects together might result in a lot of downstream messes, since you'll basically be forced to backtrack and rebase. Every developer depending on your repo will be forced to undo all their work and clone the repository fresh to avoid any lingering mixups. You don't want this to happen.

Keep in mind, too, that a git repo essentially contains every copy of every change ever committed to the repo when you clone or pull; obviously, this is not literally the case in terms of disk space, but it does make the cloning process longer. This may make clones and pulls more painful than they need to be in terms of processing time. There's other ways of dealing with this, but simply having one repository per project makes that management trivial.

Also, git servers do tend to have an absolute maximum repository size. You'll reach this size sooner if you have multiple, active projects all going at once in the same repository. It might not matter with just Apex Code and Lightning, but if you've got a lot of heavy duty files (data load files, static resources, documents, attachments, etc), you'll exhaust your limits faster than you would with separate repositories.

Note that sfdx uses a project configuration file to pull source. So if you have project1, project2, and project3, and you're in project1's directory, you'll pull the contents of project1 into it, but not project2 or project3. However, if you screw up a username/alias even once, you'll end up having to reset/clean your repository and you'll risk losing work in the scratch org. The last thing you want to do is have a major conflict of (for example) 2,000 files and have to try and manually resolve it.


With the advent of 2nd Generation Packaging and Developer Controller Packages with SalesforceDX; Salesforce is telling us to break a project into related components called artifacts.

These artifacts/DCP's can be stored, versioned and released independently.

To answer your question, let's take an example :

All the source-code for project 1 resides in

force-app/main/default

directory.

Once you break it up into some logical artifacts it could look like

force-app/main
force-app/chatBot
force-app/recruitment

Now, you can define their inter-dependency, if any in the sfdx-project.json like before installing chatBot, main package must be deployed to scratch org first and which version number should be deployed. See more settings here.

So this is how your Git repository should be shaped. Each repo having one SFDX project and that SFDX project could have multiple artifacts.

To push these packages in the scratch org, you need to push them using packaging 2 commands.

sfdx force:package:install -i 04t... --targetusername [email protected]

See the Salesforce Documentation for more commands.

Checkout, Salesforce's DreamHouse app's repo to view the structure and specifically the pkg-2 branch's sfdx-project.json over here.

Also, see my another answer where I've posted a sample sfdx-project.json with dependencies.


If you are splitting a "consumer org" code base into multiple packages, I think in many cases, mono-repo makes way more sense.

My primary argument comes down to the fact that, while you're abstracting your code into project/packages, the reality is that these individual package do not exist in isolation. They will ALWAYS live along side each other in your production org in a single state.

Having these together in the same repo will simplify dependency management and give you a single linear git history of your org.

The exception would be any general purpose code (stuff that's not really specific to your orgs domain; IOW might be installed into multiple orgs).

From a development perspective, these projects can still exist in isolation (with minimal dev-ops magic). The only real difference is that you've moved .git up to the parent level.

my-org
-- .git
-- green
--- src
--- sfdx-project.json
-- blue
--- src
--- sfdx-project.json
-- red
--- src
--- sfdx-project.json

You still work on only one project at a time (you DO NOT work out of the top level folder). Each project would still have its own isolated "environment".

Let's say we have a major feature that impacts green and blue. We can have two teams develop these feature in the same branch (separate sub-branches). We can then release these feature together in the same PR (don't squash).

To address some of the concerns listed by those suggesting multi-repo:

  • As long as you are somewhat considerate of what you commit, it seems unlikely that you would clobber something else. With a proper branch strategy and restrictions it's extremely unlikely that these type of mistakes would end up in upstream branches. However, with larger teams & junior devs, it's definitely something to consider.

  • I also don't see any reason to use orphan branches.

  • I've never run into issue with repo size, but I guess that could be a real concern... Cloning is the only operation that is really impacted by repo size. Github has a maximum repo size of 100GB (though they recommend keeping it below 1GB).

  • A concern not mentioned is that mono-repo will grant everyone read access to everything (you can restrict who has the ability to write to different branches). If this is a concern, then it might not be the right solution for you.

Again, I'm not saying that mono-repo is always the way to go, but I do think it's worth considering. Depending on your circumstances, it could be a much simpler approach.

To read more varying points of view on the matter, checkout these blogs:

  • https://danluu.com/monorepo/
  • https://medium.com/@mattklein123/monorepos-please-dont-e9a279be011b