Skip to content
All posts
July 8, 20264 min read

A Git Workflow That Actually Fits a Solo Android Developer

Team git advice is built for code review and many contributors. As a solo dev maintaining 20+ apps, I use a leaner workflow — feature branches, conventional commits, and protected main — without the overhead that doesn't apply to one person.

GitWorkflowSolo DeveloperAndroidCI
Share:

Most git tutorials assume a team: pull requests for review, approvals, release trains. I work alone across more than twenty apps. Half of that ceremony is pointless for one person, and the other half is more valuable than people admit. The trick is keeping the parts that protect future me and dropping the parts that only exist to coordinate other humans.

Main Is Sacred, Even Alone

The single most useful rule I follow: never commit directly to

code
main
. Every change goes through a branch, even a one-line fix. This isn't about review — it's about having a clean, always-deployable
code
main
and a place to abandon work that goes sideways.

I enforce it with a local hook so I can't forget:

bash
# .git/hooks/pre-commit (or a global hook)
branch=$(git rev-parse --abbrev-ref HEAD)
if [ "$branch" = "main" ] || [ "$branch" = "master" ]; then
  echo "Direct commits to $branch are blocked. Create a feature branch."
  exit 1
fi

When the machine refuses, you stop relying on discipline.

Branch Names That Describe Intent

I keep branch naming boring and consistent so

code
git branch
reads like a changelog:

text
feat/offline-sync
fix/crash-on-empty-list
chore/bump-compose-bom
perf/lazy-list-scroll

The prefix matches my commit types, so by the time I open a branch I already know the shape of the work.

Conventional Commits Pay for Themselves

Even solo, I write commits as

code
type: subject
:

text
feat: add biometric unlock to settings
fix: prevent NPE when user has no avatar
perf: cache parsed config to avoid re-reading on resume

The payoff is automation. My release notes are generated straight from the log —

code
feat
and
code
fix
become the "What's New" entries, and
code
chore
/
code
ci
/
code
docs
get filtered out. A consistent format turns a pile of commits into a Play Store changelog with no manual editing.

Squash on Merge, Keep History Linear

Inside a branch I commit messily — checkpoints, "wip", whatever. On merge I squash into one clean commit so

code
main
reads as one logical change per feature. A linear history means
code
git bisect
actually works when a regression shows up three apps and two weeks later.

bash
git checkout main
git merge --squash feat/offline-sync
git commit   # one clean conventional message

Clean Up Branches, But Verify First

Stale branches pile up fast across many repos. The temptation is to delete anything that isn't

code
main
. Don't — verify merged status first, or you'll lose unmerged work permanently.

bash
# Only branches whose work is already in main:
git branch --merged main | grep -v '^\*\| main$'

I learned this the expensive way: deleting on "not main" alone instead of "merged into main" is how you destroy work you can't get back. Scan, show yourself the list, then delete only what's confirmed merged.

Tag Releases So You Can Always Go Back

Every Play Store build gets a tag. When a user reports a crash on version 14, I can check out the exact tree that shipped instead of guessing.

bash
git tag -a v1.4.0 -m "Release 1.4.0"
git push origin v1.4.0

Why This Matters More Solo, Not Less

The instinct is that a solo developer can skip process because there's nobody to coordinate with. I think that's backwards. On a team, the process exists partly because other people catch your mistakes — a reviewer notices the direct commit to main, a teammate remembers why a branch exists. Alone, there is no one. The only safety net is the structure you build for yourself, and the only reviewer of your three-week-old decision is a tired version of you who has forgotten everything.

That's why I lean on automation over discipline. Discipline fails at 1 a.m. when you're rushing a hotfix. A hook that refuses the commit does not get tired. Conventional commits don't depend on me remembering to summarize the work later; the summary is the work. Tags don't depend on me recalling which build shipped; the tag is the record. Every one of these habits is really a way of moving knowledge out of my head and into the repository, where it survives context-switching across twenty different apps.

The other quiet benefit is that consistent git habits make tooling trivial. Because every repo follows the same branch and commit conventions, a single script can generate release notes for any of them, flag stale branches across all of them, or check which app is behind on a dependency. Consistency is what turns twenty repos from twenty separate maintenance burdens into one fleet you can operate with shared tools. The workflow isn't overhead — it's the thing that makes maintaining this many apps possible at all without a team behind me. Skip it and each repo drifts into its own special case, and special cases are exactly what a solo developer cannot afford to accumulate.

Key Takeaways

  • Block direct commits to
    code
    main
    with a hook; protect a clean, deployable trunk even when no one else touches it.
  • Name branches with intent-revealing prefixes that match your commit types.
  • Write conventional commits so release notes generate themselves from the log.
  • Squash feature branches into one clean commit to keep history linear and
    code
    git bisect
    usable.
  • Delete branches only after verifying they're merged into
    code
    main
    — never on "not main" alone.
  • Tag every release so you can reproduce exactly what shipped when bugs come in later.
Share:
S

Sudarshan Chaudhari

AI Systems Builder / Product Engineer

Bangkok, Thailand

Solo Android developer with 13+ years in QA, building Android apps, AI automation systems, and developer tools at SudarshanTechLabs.

Stay updated

Get new posts on Android, Kotlin, and solo dev straight to your inbox.

Newsletter preferences

Related Apps

MyFamilyTracker

Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.

Building something? Available for Android dev and QA consulting.

Work with me

Comments — powered by Giscus