Version Control and Deployment Workflow Across Development, Staging, and Production Environments.
A well-structured version control and deployment workflow ensures code consistency, reliability, and traceability across multiple environments.

1. Environment Overview
Development (Dev):
Used by developers for active feature development and debugging. Frequent commits and experimental branches are common here.Staging (Stg/UAT):
A replica of the production environment used for testing, QA, and user acceptance. Only stable and reviewed code from development should be deployed here.Production (Prod):
The live environment accessed by end users. Only thoroughly tested and approved code should reach this stage.
2. Git Branching Strategy
A common and effective branching model is Git Flow (or a simplified version of it):
Branch | Purpose | Example |
|---|---|---|
| Stable production-ready code | Tagged releases (e.g., |
| Ongoing development and integration branch | Features are merged here after review |
| Individual features or fixes |
|
| Pre-production release candidates |
|
| Urgent fixes on production |
|
3. Tagging for Releases
Use Git tags to mark stable points in history for deployment:
Development tags:
dev-v1.0.0Staging tags:
stg-v1.0.0Production tags:
v1.0.0
Tags make rollbacks and deployment tracking easier.
4. Deployment Workflow
Step-by-step pipeline:
Development Phase
Developers create or update feature branches.
After completion, feature branches are merged into
develop.Automated tests run (CI pipeline).
Staging Phase
When
developis stable, merge it intostagingor create arelease/*branch.Apply a staging tag (
stg-vX.X.X).Deploy to staging environment for QA and UAT.
Fix bugs on the same branch and retag if needed.
Production Phase
Once approved, merge the release or staging branch into
main.Tag production release (
vX.X.X).Deploy to production environment using CI/CD.
Hotfix Handling
Create
hotfix/*frommainfor urgent issues.Merge back to both
mainanddevelopafter deployment.
5. CI/CD Integration
Tools like GitHub Actions, GitLab CI, CircleCI, or Jenkins can automate:
Build and test pipelines
Environment-specific deployments
Version tagging and release notes
Example:
# Example: GitHub Actions (simplified)
on:
push:
tags:
- 'v*' # Deploy only on version tags
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy to Production
if: startsWith(github.ref, 'refs/tags/v')
run: ./scripts/deploy-prod.shDifference Between GitHub Tags and Branches
Aspect | Git Branch | Git Tag |
|---|---|---|
Purpose | A branch represents an active line of development — it moves as new commits are added. | A tag represents a fixed point in Git history — usually used to mark specific releases or milestones. |
Mutability | Mutable — you can add new commits, rebase, or delete a branch. | Immutable — once created, it points to a specific commit (like a snapshot). |
Use Case | Used for ongoing work such as features, bug fixes, or releases. | Used for versioning or marking releases (e.g., |
Lifecycle | Short-lived (feature branches) or long-lived ( | Permanent reference to a commit, does not change over time. |
Deployment Relevance | Deployed automatically during active development (e.g., from | Used to deploy specific, stable versions (e.g., production release tags). |
Naming Convention |
|
|
Visibility | Appears in branch lists and can be merged into other branches. | Appears in releases or tags list, not part of merge workflows. |
Typical Command |
|
|
Example Use in Workflow | Work on new feature → merge to | After merging to |
In Simple Terms
Branches = active workspaces.
You build and update features or fixes here.Tags = version markers.
You freeze and label code at a specific state — often for release, rollback, or audit purposes.
Example: Combined Use
# Developer workflow
git checkout -b feature/login
# ...work, commit, merge to develop...
# Merge develop → main after testing
git checkout main
git merge develop
# Create a production release tag
git tag -a v1.0.0 -m "Production release 1.0.0"
git push origin v1.0.0This marks the exact commit that was deployed to production — making version tracking and rollback easy.
When to Use Branches vs Tags
1. Use Branches When…
Branches are for active, changeable work — anything that’s still being developed, tested, or reviewed.
✅ Typical Scenarios
Situation | Example | Why a Branch |
|---|---|---|
Developing a new feature |
| You’re still coding, may need reviews and commits. |
Fixing a bug |
| You need a temporary workspace for changes. |
Preparing a new release |
| You’re stabilizing a version before tagging it for production. |
Environment-specific deployment |
💡 Tip:
Branches are living lines of development — they evolve and are meant to be merged or deleted after use.
2. Use Tags When…
Tags are for marking stable, completed states of your repository — snapshots that should never change.
✅ Typical Scenarios
Situation | Example | Why a Tag |
|---|---|---|
Marking a production release |
| You want to identify exactly what version went live. |
Marking a staging build |
| To record what was tested before production. |
Versioning historical milestones |
| For rollback or audit purposes. |
Archiving old code states |
| To reference a specific snapshot that won’t change. |
💡 Tip:
Tags are immutable labels — perfect for releases, audits, and deployments.
3. Real-World Example: Development → Staging → Production
Stage | Use Branch | Use Tag |
|---|---|---|
Development | Work on | Optional (e.g., |
Staging / UAT | Merge | Tag as |
Production | Merge | Tag as |
4. In Summary
Purpose | Use | Description |
|---|---|---|
Ongoing development | Branch | To work on changes without affecting main code |
Team collaboration | Branch | Each developer can work independently |
Release or deployment version | Tag | To mark a commit as a fixed, released version |
Rollback or audit | Tag | To know exactly what code was deployed |
Comments
No comments yet.