Defines common Git conventions and workflows used across Tobit.Labs projects.
The goal is to keep repositories, branches, and commit histories consistent and easy to understand.
- Branch Strategy
- Environment Branches
- Feature Branches
- Branch Naming
- Commits
- Gitmoji
- Commit Messages
- GitKraken AI
- Merging
- General Principles
Depending on the project, one of two branching strategies can be used.
Projects with multiple deployment environments use dedicated branches for each environment:
develop
│
▼
qa
│
▼
staging
│
▼
main
Changes move through the environments in this order:
develop → qa → staging → main
Each branch represents a different level of stability.
Projects that do not require dedicated environment branches can use feature branches directly.
main
├── feature/user-settings
├── feature/calendar
├── feature/message-preview
└── fix/navigation-history
Feature branches should be short-lived and merged back into the appropriate target branch once the work is complete.
The develop branch contains the latest development state.
New development work is integrated here before being promoted to higher environments.
feature/*
│
▼
develop
The qa branch represents the version currently available for quality assurance and testing.
Changes should normally reach qa through develop.
develop → qa
The staging branch represents a release candidate that is intended to be close to the production version.
Only changes that have passed the previous development and QA stages should normally reach this branch.
develop → qa → staging
The main branch represents the production-ready state of the project.
Changes should only reach main after passing the required previous environments.
develop → qa → staging → main
Avoid using main as an active development branch.
Development that should not happen directly on an environment branch should be done in a dedicated branch.
Example:
develop
│
└── feature/user-settings
After the feature is complete:
feature/user-settings
│
▼
develop
Feature branches isolate unfinished work and prevent incomplete changes from affecting other developers or environments.
Branch names should clearly communicate their purpose.
Use lowercase names and kebab-case.
feature/user-settings
feature/calendar-navigation
feature/message-preview
fix/navigation-history
fix/message-rendering
fix/calendar-selection
refactor/navigation
refactor/message-store
chore/update-dependencies
chore/cleanup-assets
Keep branch names short but descriptive.
Avoid:
feature/test
fix/bug
new-feature
michael-test
changes
A commit should represent one logical change.
Prefer several focused commits over one large commit containing unrelated changes.
For example:
✨ Add user settings dialog
🐛 Fix dialog closing behavior
♻️ Extract settings state into hook
instead of:
changes
or:
✨ Add settings, fix navigation, update dependencies and refactor dialog
A commit should ideally be understandable on its own.
Do not intentionally combine unrelated:
- features,
- bug fixes,
- refactorings,
- formatting changes,
- dependency updates,
- or generated files
into the same commit.
Commit messages use Gitmoji to communicate the type of a change at a glance.
The Gitmoji should be placed at the beginning of the commit message.
<gitmoji> <message>
Examples:
✨ Add user settings
🐛 Fix navigation history
♻️ Refactor message handling
💄 Update dialog styling
📝 Update documentation
🔧 Update configuration
⬆️ Update dependencies
🔥 Remove deprecated component
Common Gitmojis include:
| Gitmoji | Purpose |
|---|---|
| ✨ | Introduce a new feature |
| 🐛 | Fix a bug |
| ♻️ | Refactor code |
| 💄 | Update UI or styles |
| 📝 | Add or update documentation |
| 🔧 | Add or update configuration |
| ⬆️ | Upgrade dependencies |
| ⬇️ | Downgrade dependencies |
| 🔥 | Remove code or files |
| 🚚 | Move or rename resources |
| ⚡️ | Improve performance |
| 🔒️ | Fix security or privacy issues |
| 🚑️ | Critical hotfix |
| 🎨 | Improve code structure or formatting |
| ✅ | Add or update tests |
| 🚀 | Deploy changes |
Use the Gitmoji that best represents the primary purpose of the commit.
Do not add multiple Gitmojis simply because a commit touches several files.
Commit messages should be short, descriptive, and written in imperative form.
Prefer:
✨ Add calendar navigation
🐛 Fix message selection
♻️ Extract navigation logic
💄 Improve mobile layout
Avoid:
✨ Added calendar navigation
🐛 Fixed some stuff
♻️ Refactoring
💄 CSS changes
The message should provide enough context to understand the purpose of the commit without inspecting every changed file.
Prefer:
🐛 Prevent duplicate message requests
over:
🐛 Fix bug
The commit title should remain concise.
Additional context can be provided in the commit body when necessary.
🐛 Prevent duplicate message requests
Avoid starting another request while the previous request for the
same message is still pending.
When using GitKraken AI to generate commit messages, use the provided prompt to ensure generated messages follow the conventions defined above.
→ GitKraken Commit Message Prompt
Changes should be merged into the branch representing the next appropriate stage.
For the environment-based workflow:
feature/*
↓
develop
↓
qa
↓
staging
↓
main
Do not skip environments unless there is a specific reason to do so.
A normal feature should therefore not be merged directly from:
feature/* → main
when the project uses the full environment workflow.
Merge conflicts should be resolved based on the intended resulting behavior.
Do not automatically accept one side of a conflict without understanding both changes.
After resolving conflicts, verify that the resulting code still works as intended.
When working with Git:
- keep commits small and logically focused,
- use Gitmoji consistently,
- write descriptive commit messages,
- use descriptive branch names,
- keep unfinished work out of stable branches,
- move changes through the defined environments,
- avoid unrelated changes in the same commit,
- and keep the repository history understandable for other developers.
A good Git history should make it possible to understand what changed and why without having to reconstruct the development process from the code alone.