Chapter 72: DevOps Projects Part 2: Git Branching, Hooks, Conflicts, Semver, Monorepo and Gitea
72.5 Project 15: Monorepo vs multi-repo setup
Friends, companies choose one big repo or many small ones. Today we build both shapes on disk, compare clone size and change blast radius, and write a one-page decision note.
मित्रांनो, कंपन्या एक मोठा repo किंवा अनेक छोटे निवडतात. आज दोन्ही shapes disk वर बनवू, clone size आणि change blast radius तुलना करू, आणि one-page decision note लिहू.
दोस्तों, कंपनियाँ एक बड़ा repo या कई छोटे चुनती हैं. आज दोनों shapes disk पर बनाएँगे, clone size और change blast radius की तुलना करेंगे, और one-page decision note लिखेंगे.
What you will build in this project
- A monorepo with two apps and one shared lib.
- Two separate repos for the same apps.
- Clone-size and path-filter comparison.
- A short decision note for the team.
1. Start from a real company story
At Infosys in Bengaluru, the payments team had 40 micro-repos. A shared date helper needed 40 pull requests to update.
One missed repo broke month-end reports. Cost: about ₹4 lakh in emergency fixes.
Kiran tried a monorepo for three services that always release together, and kept a separate repo for a rarely touched legacy tool.
Today we feel both shapes with real folders and git commands.
Ravindra Bagale's Tip
Many students copy a famous company layout without asking how often services release together. Match the shape to your release cadence. Keep that habit.
खूप students प्रसिद्ध company ची layout विचार न करता copy करतात. तुमच्या release cadence नुसार shape निवडा. सवय ठेवा.
बहुत students मशहूर company की layout बिना सोचे copy करते हैं. अपनी release cadence के हिसाब से shape चुनें. आदत रखिए.
2. Start and prepare
Step 1: Create monorepo tree
Why: Folders first. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: mkdir tree. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 1: tree
Type this:
rm -rf /tmp/mono /tmp/multi && mkdir -p /tmp/mono/apps/api /tmp/mono/apps/web /tmp/mono/libs/common && printf '%s\n' 'api' > /tmp/mono/apps/api/main.txt && printf '%s\n' 'web' > /tmp/mono/apps/web/index.txt && printf '%s\n' 'date-helper' > /tmp/mono/libs/common/dates.txt && find /tmp/mono -type f | sort
You will see:
/tmp/mono/apps/api/main.txt
/tmp/mono/apps/web/index.txt
/tmp/mono/libs/common/dates.txt
What it means: Monorepo tree ready.
Example 2: init mono
Type this:
cd /tmp/mono && git init && git config user.email 'kiran@infosys.example' && git config user.name 'Kiran' && git add . && git commit -m 'chore: monorepo baseline' && git branch -M main && git log --oneline -1
You will see:
m01 chore: monorepo baseline
What it means: One commit tracks all apps.
Example 3: ls
Type this:
cd /tmp/mono && ls apps libs
You will see:
api
web
common
What it means: Layout clear.
Step 2: Commit monorepo baseline
Why: One history. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: git commit. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 4: show lib
Type this:
cd /tmp/mono && cat libs/common/dates.txt
You will see:
date-helper
What it means: Shared helper lives once.
Example 5: files
Type this:
cd /tmp/mono && git ls-files
You will see:
apps/api/main.txt
apps/web/index.txt
libs/common/dates.txt
What it means: Three paths tracked.
Example 6: status
Type this:
cd /tmp/mono && git status -sb
You will see:
## main
What it means: Clean.
Step 3: Create api multi-repo
Why: api alone. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: git init api. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 7: api repo
Type this:
mkdir -p /tmp/multi/api && printf '%s\n' 'api' > /tmp/multi/api/main.txt && cd /tmp/multi/api && git init && git config user.email 'kiran@infosys.example' && git config user.name 'Kiran' && git add . && git commit -m 'chore: api only' && git branch -M main && echo api_ok
You will see:
api_ok
What it means: Standalone api repo.
Example 8: web repo
Type this:
mkdir -p /tmp/multi/web && printf '%s\n' 'web' > /tmp/multi/web/index.txt && cd /tmp/multi/web && git init && git config user.email 'kiran@infosys.example' && git config user.name 'Kiran' && git add . && git commit -m 'chore: web only' && git branch -M main && echo web_ok
You will see:
web_ok
What it means: Standalone web repo.
Example 9: list multi
Type this:
find /tmp/multi -name HEAD | sort
You will see:
/tmp/multi/api/.git/HEAD
/tmp/multi/web/.git/HEAD
What it means: Two separate Git databases.
3. Build the main pieces
Step 4: Create web multi-repo
Why: web alone. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: git init web. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 10: du mono
Type this:
du -sh /tmp/mono /tmp/mono/.git
You will see:
16K /tmp/mono
52K /tmp/mono/.git
What it means: One .git for everything (lab sizes tiny).
Example 11: du multi
Type this:
du -sh /tmp/multi/api /tmp/multi/web /tmp/multi/api/.git /tmp/multi/web/.git
You will see:
8K ...
8K ...
48K ...
48K ...
What it means: Two .git folders; grows with history.
Example 12: count commits multi
Type this:
cd /tmp/multi/api && git rev-list --count HEAD; cd /tmp/multi/web && git rev-list --count HEAD
You will see:
1
1
What it means: Separate histories.
Step 5: Compare disk size
Why: du -sh. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: du. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 13: path log api
Type this:
cd /tmp/mono && git log --oneline -- apps/api
You will see:
m01 chore: monorepo baseline
What it means: Path filter focuses on api.
Example 14: path log lib
Type this:
cd /tmp/mono && git log --oneline -- libs/common
You will see:
m01 chore: monorepo baseline
What it means: Same commit touches lib too at start.
Example 15: note path
Type this:
echo 'CI can test only changed paths with path filters'
You will see:
CI can test only changed paths with path filters
What it means: Blast radius tip.
Step 6: Show monorepo log path
Why: path limited log. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: git log -- path. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 16: multi logs
Type this:
cd /tmp/multi/api && git log --oneline; echo '---'; cd /tmp/multi/web && git log --oneline
You will see:
a01 chore: api only
---
w01 chore: web only
What it means: Two logs to read for one product.
Example 17: no shared
Type this:
test ! -d /tmp/multi/libs && echo 'no_shared_lib_yet'
You will see:
no_shared_lib_yet
What it means: Shared code would need a third repo or copy-paste.
Example 18: pain
Type this:
echo 'shared helper update needs one PR in mono, many PRs in multi'
You will see:
shared helper update needs one PR in mono, many PRs in multi
What it means: Core difference.
4. Automate and verify
Step 7: Show multi-repo logs
Why: two histories. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: git log. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 19: change lib
Type this:
cd /tmp/mono && printf '%s\n' 'date-helper-v2' > libs/common/dates.txt && git add libs/common/dates.txt && git commit -m 'feat: dates helper v2' && git log --oneline -2
You will see:
m02 feat: dates helper v2
m01 chore: monorepo baseline
What it means: One commit upgrades the shared lib for all apps.
Example 20: both apps see
Type this:
cd /tmp/mono && git show HEAD:libs/common/dates.txt
You will see:
date-helper-v2
What it means: Single source of truth.
Example 21: path since
Type this:
cd /tmp/mono && git log --oneline m01..HEAD -- libs/common
You will see:
m02 feat: dates helper v2
What it means: Scoped history.
Step 8: Simulate shared lib change
Why: one commit vs many. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: edit lib. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 22: multi would need
Type this:
echo 'In multi-repo: PR to common-lib, then PR to api, then PR to web = 3 reviews'
You will see:
In multi-repo: PR to common-lib, then PR to api, then PR to web = 3 reviews
What it means: Blast count.
Example 23: mono needs
Type this:
echo 'In monorepo: 1 PR touching libs/common and maybe app callers'
You will see:
In monorepo: 1 PR touching libs/common and maybe app callers
What it means: One review.
Example 24: count
Type this:
printf '%s\n' 'multi_prs=3' 'mono_prs=1' > /tmp/pr-count.txt && cat /tmp/pr-count.txt
You will see:
multi_prs=3
mono_prs=1
What it means: Numbers for the note.
Step 9: Count PRs needed
Why: count the pain. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: echo count. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 25: note
Type this:
cd /tmp/mono && printf '%s\n' '# Decision note: mono vs multi' '' '## Context' 'api and web release every week together.' 'Legacy billing tool releases twice a year.' '' '## Choice' 'Keep api+web+libs in a monorepo.' 'Keep legacy billing in its own repo.' '' '## Why' 'Shared dates helper needs one PR, not three.' 'CI path filters keep test time low.' 'Different cadence for legacy avoids blocking.' > decision-note.md && wc -l decision-note.md
You will see:
16 decision-note.md
What it means: Decision note written.
Example 26: head
Type this:
cd /tmp/mono && head -8 decision-note.md
You will see:
# Decision note: mono vs multi
## Context
api and web release every week together.
What it means: Readable.
Example 27: grep choice
Type this:
cd /tmp/mono && grep -A2 '## Choice' decision-note.md
You will see:
## Choice
Keep api+web+libs in a monorepo.
Keep legacy billing in its own repo.
What it means: Clear choice.
5. Harden and accept
Step 10: Write decision note
Why: write reasons. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: printf note. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 28: commit note
Type this:
cd /tmp/mono && git add decision-note.md && git commit -m 'docs: add mono vs multi decision note' && git log --oneline -3
You will see:
m03 docs: add mono vs multi decision note
m02 feat: dates helper v2
m01 chore: monorepo baseline
What it means: Note stored in history.
Example 29: show path
Type this:
cd /tmp/mono && git log --oneline -- decision-note.md
You will see:
m03 docs: add mono vs multi decision note
What it means: Path log works.
Example 30: files
Type this:
cd /tmp/mono && git ls-files | wc -l
You will see:
4
What it means: Four tracked paths.
Step 11: Commit note
Why: store the note. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: git commit. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 31: cadence note
Type this:
printf '%s
' 'api+web weekly together; billing twice a year' > /tmp/cadence.txt && cat /tmp/cadence.txt
You will see:
api+web weekly together; billing twice a year
What it means: Cadence drives the shape.
Example 32: mono paths
Type this:
cd /tmp/mono && git ls-files 'apps/*'
You will see:
apps/api/main.txt
apps/web/index.txt
What it means: Two apps in one history.
Example 33: multi count
Type this:
ls -d /tmp/multi/api /tmp/multi/web | wc -l
You will see:
2
What it means: Two repos.
Step 12: Acceptance checklist
Why: Kiran signs off when these pass. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: All green. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 34: rule
Type this:
printf '%s\n' 'Choose monorepo when services release together; multi when cadence and owners differ.' > /tmp/repo-shape-rule.txt && cat /tmp/repo-shape-rule.txt
You will see:
Choose monorepo when services release together; multi when cadence and owners differ.
What it means: Rule card.
Example 35: both shapes exist
Type this:
test -d /tmp/mono/.git && test -d /tmp/multi/api/.git && test -d /tmp/multi/web/.git && echo shapes_ok
You will see:
shapes_ok
What it means: Lab complete.
Example 36: Sign-off
Type this:
echo 'Kiran: PASS'
You will see:
Kiran: PASS
What it means: Done.
Check yourself
Q1. Who chose the Infosys mix?
Kiran
Q2. Folder for shared code in the lab?
libs/common
Q3. Two apps in the monorepo?
api and web
Q4. Tool to measure folder size?
du
Q5. Note file name?
decision-note.md
Q6. What drives the choice?
Release cadence
Friends, you built both shapes and wrote a decision note. Did you understand? Let us try it once more. Add a third tiny service and decide whether it joins the monorepo.
मित्रांनो, तुम्ही दोन्ही shapes बनवून decision note लिहिला. तिसरी छोटी service आणून ठरवा ती monorepo मध्ये जाईल का.
दोस्तों, आपने दोनों shapes बनाकर decision note लिखा. तीसरी छोटी service लाकर तय करें कि वह monorepo में जाएगी या नहीं.
Lab: try at home
- Create the monorepo layout.
- Create two single-service repos.
- Compare du and log scope.
- Write decision-note.md.
- Commit the note in the monorepo.
Recap
- Monorepo shines when services release together.
- Multi-repo shines when teams and cadences differ.
- Path filters limit CI blast radius.
- Shared libs are easier in one repo.
- Write the reason down.