Chapter 24: Jenkins with GitHub, GitLab and Bitbucket
24.6 Branch indexing and orphaned items
Why: the problem
Think of Myntra before a big sale. The app repo has 300 branches. Half of them were merged and deleted months ago. But Jenkins still shows 300 child jobs, many red, many from people who left. The disk on the Jenkins server is 92 percent full of old workspaces and logs. A new person cannot find the real jobs. This happens because of two things. Branch indexing is how Jenkins finds branches. Orphaned items are child jobs whose branch is gone. If you never set an orphaned item strategy, Jenkins keeps them forever. In this lesson you will read the indexing log, set rules to remove dead child jobs, limit which branches get jobs, and free disk space safely.
What we will build
You will make five short-lived feature branches in menu-api, scan, then delete three of them on the host. You will read the indexing log, see the orphaned jobs, and set Orphaned Item Strategy to keep at most 2 days and 5 items. You will add a branch name filter so only main, develop, release/ and feature/ get jobs. You will add a buildDiscarder so each child keeps only 20 builds, and you will measure the disk before and after.
What: every term in plain English
- Branch indexing — The scan where Jenkins lists branches, PRs and tags and checks each for a Jenkinsfile.
- Indexing log — The console of the scan. It says why each branch was added or skipped.
- Orphaned item — A child job whose branch, PR or tag no longer exists on the host.
- Orphaned Item Strategy — A Multibranch setting: how many days and how many orphaned jobs to keep.
- Disabled item — An orphaned job shown in grey. It is not deleted until the strategy rule says so.
- Branch filter — A rule with wildcards that lists which branch names get jobs.
- buildDiscarder — A Jenkinsfile option that deletes old builds of a job.
- JENKINS_HOME — The folder where Jenkins keeps jobs, builds and logs, often /var/jenkins_home.
How: step by step
-
Make five lab branches
for b in a b c d e; do git push gl main:refs/heads/feature/tmp-$b; doneWhat it does: Five new branches on GitLab, same code as main.
Output
* [new branch] main -> feature/tmp-a ... * [new branch] main -> feature/tmp-e -
Scan and count jobs
Scan Multibranch Pipeline Now, then count jobs in the folderWhat it does: Jenkins makes five more child jobs.
Output
9 child jobs -
Delete three branches on the host
for b in a b c; do git push gl --delete feature/tmp-$b; doneWhat it does: These three are now orphans in Jenkins.
Output
- [deleted] feature/tmp-a - [deleted] feature/tmp-b - [deleted] feature/tmp-c -
Scan again and read the log
menu-api-mb > Scan Multibranch Pipeline LogWhat it does: Shows the orphans found.
Output
Will not remove feature/tmp-a because it is new 3 orphaned items found -
Set the orphaned strategy
Configure > Orphaned Item Strategy > Discard old items > Days to keep: 2 > Max # to keep: 5What it does: Jenkins removes old orphans on the next scan.
Output
(saved) -
Add a branch filter
Behaviours > Add > Filter by name (with wildcards) > Include: main develop release/* feature/* > Exclude: feature/tmp-*What it does: Only real branches get jobs.
Output
(saved) -
Scan and check disk
Scan Now; then du -sh /var/jenkins_home/jobs/menu-api-mbWhat it does: The folder is smaller.
Output
Removing orphaned item feature/tmp-a ... 18M /var/jenkins_home/jobs/menu-api-mb
Example 1: Read the indexing log line by line
Stack. Multibranch indexing
Goal. Read the indexing log line by line.
Scan Multibranch Pipeline Log
Started by timer
[Sun Oct 25 10:30:00 IST 2026] Starting branch indexing...
Checking branches...
Checking branch main
'Jenkinsfile' found
Met criteria
No changes detected: main (still at 9b77d10)
Checking branch feature/no-ci
'Jenkinsfile' not found
Does not meet criteria
Checking branch feature/tmp-d
Met criteria
Changes detected: feature/tmp-d (null -> 9b77d10)
Scheduled build for branch: feature/tmp-d
Processed 4 branches
Evaluating orphaned items in menu-api-mb
Will remove feature/tmp-a
Will remove feature/tmp-b
Will remove feature/tmp-c
Finished: SUCCESS
What each line does
Started by timer— The periodic scan ran. "Started by GitLab push" would mean a webhook.'Jenkinsfile' found / Met criteria— The branch will have a child job.No changes detected— Same commit as last time, so no new build.'Jenkinsfile' not found / Does not meet criteria— No child job. This is why a branch is missing.Changes detected (null -> 9b77d10)— A new branch. Jenkins schedules its first build.Will remove feature/tmp-a— The orphaned strategy will delete this child job.
Green output
Removed orphaned item: feature/tmp-a
Removed orphaned item: feature/tmp-b
Removed orphaned item: feature/tmp-c
Expected result. You can explain every line. When a branch has no job, you search this log for its name first.
Example 2: Keep each child small with buildDiscarder and a clean workspace
Stack. Workspace Cleanup plugin
Goal. Keep each child small with buildDiscarder and a clean workspace.
Jenkinsfile
pipeline {
agent any
options {
buildDiscarder(logRotator(numToKeepStr: env.BRANCH_NAME == 'main' ? '50' : '10',
artifactNumToKeepStr: '5'))
disableConcurrentBuilds()
timeout(time: 20, unit: 'MINUTES')
}
stages {
stage('Test') { steps { sh 'npm ci || npm install'; sh 'npm test' } }
}
post {
cleanup { cleanWs() }
}
}
What each line does
numToKeepStr: env.BRANCH_NAME == 'main' ? '50' : '10'— Keep 50 builds on main for history, only 10 on other branches.artifactNumToKeepStr: '5'— Keep files of only the last 5 builds. Files are what fill the disk.disableConcurrentBuilds()— One build per branch at a time.timeout(time: 20, unit: 'MINUTES')— Kill a stuck build so it does not hold an agent all night.cleanup { cleanWs() }— Delete the workspace after the build. Needs the Workspace Cleanup plugin.
Green output
[Pipeline] cleanWs
[WS-CLEANUP] Deleting project workspace...
[WS-CLEANUP] done
Finished: SUCCESS
$ ls /var/jenkins_home/jobs/menu-api-mb/branches/feature-badge-color/builds | wc -l
10
Expected result. Old builds go away by themselves. The workspace folder is empty after each build.
Example 3: Find the biggest jobs on disk and clean them safely
Stack. Linux, Jenkins on EC2
Goal. Find the biggest jobs on disk and clean them safely.
disk-report.sh
#!/usr/bin/env bash
set -euo pipefail
JH=/var/jenkins_home
echo "== disk"
df -h "$JH" | tail -1
echo "== top 5 job folders"
du -sh "$JH"/jobs/* 2>/dev/null | sort -rh | head -5
echo "== workspaces older than 7 days"
find "$JH"/workspace -mindepth 1 -maxdepth 1 -type d -mtime +7 | wc -l
What each line does
df -h "$JH"— How full the disk is.du -sh ... | sort -rh | head -5— The five biggest job folders.find ... -mtime +7— Workspaces not touched for 7 days. Safe to remove; Jenkins makes them again.Do not delete builds folders by hand— Jenkins keeps an index. Use buildDiscarder or the UI, then restart is not needed.2>/dev/null— Hides errors for folders you cannot read.
Green output
== disk
/dev/nvme1n1 50G 46G 4.0G 92% /var/jenkins_home
== top 5 job folders
21G /var/jenkins_home/jobs/shop-app-mb
6.1G /var/jenkins_home/jobs/menu-api-mb
...
== workspaces older than 7 days
212
Expected result. You know which job to fix first. After adding the strategy and discarder to shop-app-mb, the disk drops from 92 to 61 percent.
Verify: did it work?
-
Count orphaned (disabled) child jobs
curl -s -u ravi:$JENKINS_TOKEN "http://localhost:8080/job/menu-api-mb/api/json?tree=jobs[name,color]" | jq "[.jobs[] | select(.color==\"disabled\")] | length"What it does: Should go to 0 after the strategy runs.
Output
0 -
Check builds kept on a branch
ls /var/jenkins_home/jobs/menu-api-mb/branches/main/builds | grep -c "^[0-9]"What it does: Should be 50 or less on main.
Output
50
When it is red 1
Deleted branch still shows as a grey job for days
Cause. Orphaned Item Strategy is not set, or Days to keep is large.
Fix, step by step
- Set Discard old items with small numbers.
- Run a scan; removal happens during indexing.
When it is red 2
Branch exists on the host but no job appears
Cause. No Jenkinsfile on that branch, or the name filter excludes it.
Fix, step by step
- Search the indexing log for the branch.
- Check Include and Exclude in Filter by name.
When it is red 3
java.io.IOException: No space left on device
Cause. The Jenkins disk is full, usually from builds, artifacts and workspaces.
Fix, step by step
- Run disk-report.sh.
- Add buildDiscarder and orphaned strategy.
- Move artifacts to S3 or Nexus.
- Grow the EBS volume if still needed.
Cleanup
-
Delete the last lab branches
for b in d e; do git push gl --delete feature/tmp-$b; doneWhat it does: Leaves only real branches.
Output
- [deleted] feature/tmp-d - [deleted] feature/tmp-e -
Rescan
Scan Multibranch Pipeline NowWhat it does: Removes their jobs if the rule allows.
Output
Removed orphaned item: feature/tmp-d
Ravindra Bagale's Tip
Juni branch geli tar tichi job pan javi. Orphaned strategy set kara. Lakshat theva!
Practice tasks
Easy Read one scan log
Why: Logs answer most "where is my job" questions.
What to do: Explain every line of one indexing log.
- Open the scan log.
- Write one line per message.
Check: You can say why each branch has or has no job.
Medium Set the cleanup rules
Why: Without rules the disk fills up.
What to do: Add an orphaned strategy and buildDiscarder to one job.
- Days 2, max 5.
- Keep 10 builds on branches.
Check: Old jobs and builds disappear on the next scan.
Hard Write a disk report
Why: On-call people need numbers fast.
What to do: Run disk-report.sh weekly and save results.
- Add it as a small Jenkins job on a timer.
Check: You have two weeks of numbers.
Easy Say branch indexing and orphaned items in two lines
Why: If you can say it simply, you understand it. Juniors and interviewers both want the short version first.
What to do: Write two short lines about branch indexing and orphaned items for a fresher who knows only Linux and Git basics.
- Write the problem it solves.
- Write the one Jenkinsfile step or command you use for it.
- Read it aloud to a friend.
Check: A fresher understands it without asking a question.
Easy Start a fresh lab Jenkins
Why: Practice needs a throwaway Jenkins. If you break it, you delete it and start again.
What to do: Run Jenkins LTS in Docker with a named volume.
- docker volume create jenkins_home
- docker run -d --name jenkins -p 8080:8080 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts-jdk17
- docker logs jenkins 2>&1 | grep -A2 "initialAdminPassword"
Check: The Jenkins login page opens on localhost:8080.
Medium Do it on the second setup
Why: A release idea must work on a VM, on Docker and on Kubernetes. Only the deploy step should change.
What to do: Repeat this lesson on a different target than the one you used first.
- If you used Docker, use kind or minikube now.
- Change only the deploy commands.
- Keep the same Jenkinsfile stages.
Check: Same result, and the stage names did not change.
Medium Break it on purpose
Why: You must know the red output by face. In a real outage there is no time to read slowly.
What to do: Cause one error from the "When it is red" part of this lesson and fix it.
- Follow the error section.
- Copy the exact message into your notes.
- Write the fix in one line.
Check: You fixed it using only the steps, without searching the web.
Medium Write a release runbook page
Why: At 2 a.m. nobody remembers flags. A short page saves the on-call person.
What to do: Write a one-page runbook for this lesson.
- Title, when to use, exact commands, how to check, how to undo.
Check: A teammate can follow it alone.
Hard Explain it like an interview
Why: Interviewers want real stories, not definitions.
What to do: Record a 60 second answer about this lesson.
- Say the problem, the Jenkinsfile step, and one error you hit.
Check: Your answer has a real command and a real error message.
Hard Draw the flow top to bottom
Why: A drawing shows the order of work and who is waiting on whom.
What to do: Draw this lesson as boxes from top to bottom.
- Start at git push, go through the stages, end at the check in production.
Check: Each box matches a real step you ran.
Homework: try at home
Try at home
At home, make five branches, scan, delete three and watch the orphaned jobs. Set an orphaned strategy and a buildDiscarder and write the disk size before and after.
Recap
- Branch indexing scans the host and makes or skips child jobs.
- The indexing log tells you why a branch has no job.
- Set an Orphaned Item Strategy so dead child jobs go away.
- Use name filters to stop junk branches.
- Use buildDiscarder and cleanWs to keep the disk small.
FAQ
Will the strategy delete my main job?
No. Only orphans, whose branch is gone.
Can I see orphaned jobs before they go?
Yes. They are shown disabled until removed.
Why not set days to 0?
A branch deleted by mistake would lose its history at once. Keep a day or two.
Does a webhook also run indexing?
Yes. A push event triggers a light scan for that branch.
Should I store artifacts in Jenkins for months?
No. Push them to S3, Nexus or a registry.
Interview questions
-
What is branch indexing?
The Multibranch scan that finds branches, PRs and tags and checks for a Jenkinsfile.
-
A branch has no job. How do you debug?
Read the indexing log for it, check the Jenkinsfile exists, and check name filters.
-
How do you stop Jenkins disk filling up?
buildDiscarder, artifact limits, cleanWs, orphaned item strategy, and external artifact storage.
-
What is the Orphaned Item Strategy?
Rules for how long and how many orphaned child jobs to keep before deleting.
-
Why use a branch name filter?
To build only real branches and save agents and disk.
Quick quiz
Q1. What is an orphaned item?
A child job whose branch, PR or tag is gone.
Q2. Where do you see why a branch has no job?
In the indexing log.
Q3. Which option keeps only some builds?
buildDiscarder with logRotator.
Q4. When are orphaned items removed?
During a scan, by the Orphaned Item Strategy.
Q5. Is it safe to delete old workspaces?
Yes. Jenkins makes them again on the next build.
Samajla ka?