{"id":21599761,"url":"https://github.com/okmanideep/app-branching-strategy","last_synced_at":"2026-05-09T18:34:44.138Z","repository":{"id":65486453,"uuid":"593059826","full_name":"okmanideep/app-branching-strategy","owner":"okmanideep","description":"Simple git branching strategy for teams working on mobile applications","archived":false,"fork":false,"pushed_at":"2023-04-06T13:31:11.000Z","size":59,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-24T18:08:24.479Z","etag":null,"topics":["git","github-actions","mobile","mobile-development"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/okmanideep.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2023-01-25T05:57:42.000Z","updated_at":"2024-03-31T09:49:43.000Z","dependencies_parsed_at":"2023-02-14T15:00:22.799Z","dependency_job_id":null,"html_url":"https://github.com/okmanideep/app-branching-strategy","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okmanideep%2Fapp-branching-strategy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okmanideep%2Fapp-branching-strategy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okmanideep%2Fapp-branching-strategy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okmanideep%2Fapp-branching-strategy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/okmanideep","download_url":"https://codeload.github.com/okmanideep/app-branching-strategy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244217639,"owners_count":20417660,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["git","github-actions","mobile","mobile-development"],"created_at":"2024-11-24T18:16:22.754Z","updated_at":"2026-05-09T18:34:39.094Z","avatar_url":"https://github.com/okmanideep.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Branching Strategy for Mobile Apps\n\n[Understand The Why s 🤔](#the-why-s-)\n\n## Repository Settings ⚙️\n* [Only allow Squash Merges](https://egghead.io/lessons/github-automatically-squash-commits-on-github-when-merging-pull-requests)\n* ✅ Delete head branches once pull request is merged\n* Settings \u003e Actions \u003e Workflow Permissions\n\t* Read and write permissions\n\t* Allow GitHub Actions to create and approve pull requests\n\n## Permanent Trunks 🛤️\n* `master` -\u003e Latest and greatest Dev Tested Code\n\nNo other permanent trunks.\n\n## Other branches that come and go ⏳\n* `feature/\u003cfeature_name\u003e`\n* `fix/\u003cbug_title\u003e`\n* `release/v-\u003cversion.major\u003e.\u003cversion.minor\u003e` \n\t* Temporary branch that lives while a release is being _prepared_\n\t* No patch number in branch name because patch number is subject to change as fixes are merged after Testing\n* `auto-backmerge/\u003cpr_number\u003e` Used to raise PRs to master for every change pushed to release branches\n\n## Versioning Scheme 🏷️\n`YYMM.DD.NN`\n\n`NN` ➡️ patch number\n\nEx: `2301.25.00`, `2302.01.04`\n\n## Automated Workflows 🤖\n### On PR merge to `master`\n🤖 [on-merge-master.yml](./.github/workflows/on-merge-master.yml)\nOn every merge to master we update the full version. Major, minor versions will be modified if the existing version is of a previous date, otherwise only the patch number will be increased.\n\n**Example**:  \nExisting Version: `2301.25.02`  \nIf a new commit is pushed on 25th Jan, 2023, the version becomes `2301.25.03`  \nIf a new commit is pushed on 26th Jan, 2023, the version becomes `2301.26.00`  \n\n### On PR merge to `release/**`\n🤖 [on-merge-release.yml](./.github/workflows/on-merge-release.yml)\n#### Update Patch Number on `release*`\nOn every commit we update the patch number on `release*` branches\n\n#### Backmerge pushes into `release/**` onto `master`\n🤖 [on-merge-release.yml](./.github/workflows/on-merge-release.yml)\nEvery push to `release*` will trigger a corresponding PR to `master` via a `auto-backmerge/\u003cpr_number\u003e` branch. \n\n\u003e The PR will be automatically merged if there are no conflicts\n\n## Manually triggered workflows 🔲\n### Prepare a new release\n🤖 [prepare-a-release.yml](./.github/workflows/prepare-a-release.yml)\nCreate a release branch from latest master, with the right version in the branch name.\n\nActions ▶️ \u003e Prepare a release \u003e Run workflow\n\n### Tag Release\n🤖 [create-tagged-release.yml](./.github/workflows/create-tagged-release.yml)\nTag the latest commit in a release branch with the right version tag and release notes\n\nActions ▶️ \u003e Create Tagged Release \u003e Run workflow (select the release branch)\n\n## Feature  Development⭐ \u0026 Bug Fixing🪲\n```mermaid\n%%{init: { 'gitGraph': {'mainBranchName': 'master', 'showCommitLabel': true}} }%%\n\ngitGraph\n\tcommit id: \"🤖 2301.25.00\"\n\tbranch fix/frames-bug\n\tcommit id: \"Fix Logic\"\n\tcommit id: \"Fix UI\"\n\tcheckout master\n\tbranch feature/dm\n\tcommit id: \"Add DB\"\n\tcommit id: \"Add Socket\"\n\tcheckout master\n\tmerge fix/frames-bug id: \"PR: Frames Bug\"\n\tcommit id: \"🤖 2301.25.01\"\n\tcheckout feature/dm\n\tmerge master id: \"Pull master\"\n\tcommit id: \"Add UI\"\n\tcheckout master\n\tmerge feature/dm id: \"PR: Feature DM\"\n\tcommit id: \"🤖 2301.25.02\"\n```\n\n## Releases ⛳\n### Preparation ⚒️\n1. Cut the release branch from latest `master` ( Actions ▶️ \u003e Prepare a release \u003e Run Workflow )\n1. Generate Artifact(APK / IPA), and Dev Test\n1. Distribute Artifact for testing\n1. Fix bugs in release branch, `master` branch and go to Step 2\n\n```mermaid\n%%{init: { 'gitGraph': {'mainBranchName': 'master', 'showCommitLabel': true}} }%%\n\ngitGraph\n\tcommit id: \"🤖 2301.25.02\"\n\tbranch release/v-2301.25\n\tcheckout master\n\tcommit id: \"PR: New Feature\" type:HIGHLIGHT\n\tcommit id: \"🤖 2301.26.00\"\n\tcheckout release/v-2301.25\n\tbranch fix/release-bug\n\tcommit id: \"Fix bug\"\n\tcheckout release/v-2301.25\n\tmerge fix/release-bug id: \"PR: Release bug\"\n\tcheckout release/v-2301.25\n\tbranch auto-backmerge/release-bug\n\tmerge master id: \"Update branch\"\n\tcheckout release/v-2301.25\n\tcommit id: \"🤖 2301.25.03\" tag: \"v-2301.25.03\"\n\tcheckout master\n\tmerge auto-backmerge/release-bug id: \"backmerge\"\n\tcheckout master\n\tcommit id: \"🤖 2301.26.01\"\n```\n\n### Making the release 🏌️\nActions ▶️ \u003e Create Tagged Release \u003e Run Workflow (select release branch)\n\nOnce we are 🟢 on all tests, do the above to tag the latest commit from the release branch and create a Github release with automated release notes. And upload the artifacts to the App Stores\n\n### Hotfix 🧯\nFixing an issue in current production build (`v-2301.16.01`)\n1. Create a branch from the release tag (tag: `v-2301.16.01` -\u003e branch: `release/v-2301.16`)\n\nThe rest is same as normal release flow\n\n```mermaid\n%%{init: { 'gitGraph': {'mainBranchName': 'release/v-2301.16', 'showCommitLabel': true}} }%%\n\ngitGraph\n\tcommit id: \"2301.16.04\" tag: \"v-2301.16.04\"\n\tbranch hotfix/crash\n\tcommit id: \"Fix crash\"\n\tcheckout release/v-2301.16\n\tmerge hotfix/crash id: \"PR Crash\"\n\tcommit id: \"🤖 2301.16.05\"\n\tbranch hotfix/bug\n\tcommit id: \"Fix bug\"\n\tcheckout release/v-2301.16\n\tmerge hotfix/bug id: \"PR Bug\"\n\tcommit id: \"🤖 2301.16.06\" tag: \"v-2301.16.06\"\n\n```\n\n# The Why s 🤔\n## Why only squash merging?\nLinear history is desirable for various reasons. All boil down to simplicity again.\n\nOnly allowing squash merging with a single trunk is the simplest way to achieve linear history. No one has to think, the right thing happens automatically.\n\nAlso in general, people have better discipline with respect to PR titles than commit messages, so your change-logs also look good.\n\n## Why have release branches at all?\nUnlike server apps, mobile app release processes tend to be long. It's common to take **2 or more weeks** if we include the gradual roll out to 10% \u003e 20% \u003e 50% \u003e 100% while observing stability and metrics along the way.\n\nMeanwhile, contributors should **NOT** have ambiguity of whether it is safe to merge to master right now. \n\nOnce the release is made and the commit is tagged, they don't have any purpose. That's why we delete them after release.\n\n```mermaid\ngantt\n\ttitle App development and releases\n\tdateFormat YYYY-MM-DD\n\ttickInterval 3day\n\n\tsection Dev 1\n\tFeature 2 ⭐ :a, 2022-01-13, 15d\n\tMerge to master: crit, milestone, after a, 0d\n\n\tsection Dev 2\n\tFeature 1 ⭐ :b, 2022-01-12, 2d\n\tMerge to master: milestone, after b, 0d\n\tLibrary Upgrade ⬆️ : l, 2022-01-16, 1d\n\tMerge to master :crit, milestone, after l, 0d\n\tFix Feature 1 🪲: b2, after r1, 2d\n\tMerge to release: milestone, after b2, 0d\n\tFramework Upgrade ⬆️ : f, 2022-01-22, 1d\n\tMerge to master :crit, milestone, after f, 0d\n\n\tsection Release\n\tPrepare Release 2201.14: milestone, after b, 0d\n\tTesting Feature 1 ⭐: r1, after b, 4d\n\tTesting Feature 1 ⭐: r2, after b2, 1d\n\tRollout 2201.14.1 10% - 100%: r3, after r2, 7d\n\tPrepare Release 2201.31: milestone, 2022-01-31, 0d\n\t\n```\n\u003e Merging to master 🟥 is safe and encouraged even when a release is ongoing\n\n## Why use a date based versioning scheme?\nIt's a date based versioning scheme that is also\n* compatible with `semver` comparisons for which version is greater than the other\n* compatible with string alphabetical order comparisons ( `2301.16.00` \u003e `2212.31.07` )\n\nAnd best of all avoids the question - **When did we release this version?** forever, from anyone in the whole team\n\nEven if answering the above question is not that important for your team, it's equally good, if not better than `semver`. Which, most teams use by default. Semantic Versioning (`semver`) makes sense for libraries. Consumers of your library want to know when there are breaking changes and when there aren't. And package managers take advantage of this convention to safely upgrade dependencies. Mobile App Users / App Stores have no such expectations from App Versions. They barely care.\n\nMy teams have been using date based versioning schemes for more than a year and it's great!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fokmanideep%2Fapp-branching-strategy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fokmanideep%2Fapp-branching-strategy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fokmanideep%2Fapp-branching-strategy/lists"}