Context & Background
I am dealing with two Git repos with Salesforce SFDX source:
R1 (project P1). Implementation is completed and will go live in 4 months.
R2 (project P2, started later and in the middle of the development)
Both projects deploy to one Salesforce org (same Production org).
CI/CD: Azure DevOps (no third-party DevOps tools).
Objective: create a mono-repo R so both teams develop in one place while
preserving history.
Thought Constraints / Requirements
Proposed Target repo layout (R):
root/
sfdx-project.json
packages/
p1/ # P1 (from R1)
p2/ # P2 (from R2)
common/ # shared metadata
scripts/ci/
.forceignore
.gitignore
azure-pipelines.yml
Plan to merge (preserve history)
Create empty repo R (or use R1 as base).
Add R1 as remote and pull it into packages/p1 with git subtree:
git remote add r1 <R1_URL> git fetch r1 mkdir -p packages/p1 git subtree add --prefix=packages/p1 r1/main --squash
git remote add r2 <R2_URL> git fetch r2 mkdir -p packages/p2 git subtree add --prefix=packages/p2 r2/main --squash
I can drop --squash if full granular history per subtree is preferred.
Create packages/common and move shared metadata there (objects/labels/value sets/utility Apex/etc.).
Rule I plan to follow: if an object is used by both projects, move the entire object folder (and its fields/layouts/etc.) to common.
Resolve naming/API collisions (Apex, LWC bundle folders, flows, static resources).
Validate to Integration Sandbox (Azure DevOps) with check-only deploys per changed directory.
What I’ve already done / tried
Prototyped git subtree locally with a small sample; directory history is preserved as expected.
Drafted Azure DevOps pipeline to detect changed package dirs and run sf project deploy start --dry-run.
Identified branches from both repos that needs to be merged Prod from P1 and Dev from P2.
At this point I just want to validate my strategy as it is very crucial to put up a right plan and strategy in place before starting the hands on execution.
If your goal is to have both projects keep their history and end up merged into a single repository, take 1 branch from each repo.... say main and merge them, having moved the root directory of each project into a subdirectory, so that when merging, they do not take the same (FS) namespace.
So, say that I am working on my local R1 repo... and I have origin for the central R1 repo. Add a second remote R2 that points to the central R2 repo. Fetch and now you can see R2/main.
So, let's work
git checkout merge-r1 R1/main
mkdir r1 # create a directory R1 that will hold everything related to R2
git mv ./* r1/ # that should move everything from the root of the r1 project into the subdirectory r1
# make sure that hidden files are moved too, just in case.
git commit -m "R1: moving everything into r1 subdirectory"
Now let's do the same for R2
git checkout -b merge-r2 R2/main
mkdir r2 # create a directory R1 that will hold everything related to R2
git mv ./* r2/ # that should move everything from the root of the r1 project into the subdirectory r2
# make sure that hidden files are moved too, just in case.
git commit -m "R2: moving everything into r2 subdirectory"
Now, let's merge the history of both projects... I will stay on R2 but it could be done from r1, no problem
git merge --allow-unrelated-histories merge-r1 -m "Merging history of R1"
That should give you no problem. Now, take this branch and push it into the main branch of the repo where you want to keep it (or both)... of course, make sure along with your people understand what is going on with this approach before moving forward to push into any public branch (up to this point, everything has been made on a local private branch and has not affected any public branch).
git push R1 @:main
And now the history of both branches has been tied together into a single branch.