Thank you for your interest in contributing to Commit+! This guide will help you get up and running.
- Code of Conduct
- How Can I Contribute?
- Setting Up Your Development Environment
- Building & Running
- Running Tests
- Project Structure
- Coding Conventions
- Pull Request Process
- Style Guide
Be respectful and constructive in all interactions. By participating in this project, you agree to follow the Commit+ Code of Conduct.
- Check existing issues first to avoid duplicates.
- Open a new issue with a clear title and description.
- Include your macOS version, Commit+ version, and steps to reproduce.
- Open an issue with the feature request label.
- Describe the problem you're trying to solve, not just the solution.
- Include mockups or examples if applicable.
Please do not report security vulnerabilities through public issues. See SECURITY.md for responsible disclosure instructions.
- Pick an issue labeled good first issue or help wanted, or open a discussion for new features.
- Follow the development setup and coding conventions below.
- Submit a pull request with a clear description of your changes.
| Tool | Version |
|---|---|
| macOS | 26.2+ |
| Xcode | 26.2+ |
| Git | Any recent version (via Homebrew or Xcode Command Line Tools) |
git clone https://github.com/Commit-Plus/commit-plus.git
cd commit-plusopen macgit.xcodeprojOr build from the command line:
xcodebuild -project macgit.xcodeproj -scheme macgit -destination 'platform=macOS' buildNote: Xcode places DerivedData under
~/Library/Developer/Xcode/DerivedData/macgit-<hash>/. The hash is derived from the project path, so each worktree gets its own DerivedData folder.
Open macgit.xcodeproj in Xcode and press Cmd+R.
xcodebuild -project macgit.xcodeproj -scheme macgit -destination 'platform=macOS' buildxcodebuild -project macgit.xcodeproj -scheme macgit -configuration Release -destination 'platform=macOS' buildxcodebuild -project macgit.xcodeproj -scheme macgit -destination 'platform=macOS' testTests live in macgitTests/ and create temporary Git repositories to exercise real Git operations.
bash scripts/test-command-line.shThis compiles and runs the CLI integration tests outside of Xcode. It does not launch the app.
Tip: Run tests after non-trivial changes. If the full test suite crashes during bootstrapping ("Early unexpected exit" /
abort() called), a successful build is sufficient — do not re-run the suite.
macgit/
├── App/ # App entry point, AppState, toolbar wiring
├── Views/ # SwiftUI views (10 subdirectories by feature area)
├── Services/ # Git operations & business logic
├── Models/ # Data models
├── ViewModels/ # View models
├── Resources/ # Assets
command-line/ # CLI tool source (commit command)
scripts/ # Build, test, and release automation
macgitTests/ # XCTest test suite
docs/ # Design specs and implementation plans
Git operations are centralized in macgit/Services/GitStatusService*.swift.
Firebase rules, Cloud Functions, backend tests, and operator scripts are maintained in the private landing-page repository. See Firebase setup for native client configuration.
Preserve existing copyright and license notices, including third-party attribution. Contributors may add their own copyright notice; no specific author name or email is required.
For new Swift source files, use either the full AGPL v3 header from an existing project file or a short SPDX notice:
// SPDX-License-Identifier: AGPL-3.0-or-laterThe repository license is in LICENSE. Keep third-party code's original notices rather than replacing them with the project header.
Enable the shared hooks once per checkout:
git config core.hooksPath .githookspre-commitchecks staged Swift content and warns about missing AGPL notices. It does not block commits or require personal attribution.pre-pushvalidates release tag versions againstMARKETING_VERSION.
- Use Swift 5.0 with
async/awaitandactorfor concurrency. - Follow standard Swift API Design Guidelines.
- Prefer SwiftUI for all UI code.
- Use descriptive naming; avoid abbreviations unless they are widely understood.
- Views should be thin — delegate logic to ViewModels or Services.
- Git operations go through
Services/GitStatusService*.swift. - Use
@ObservableorObservableObjectfor state management as appropriate.
-
Fork the repository and create a feature branch from
main:git checkout -b feature/my-feature main
-
Make your changes following the coding conventions above.
-
Add or update tests in
macgitTests/for any non-trivial change. -
Build and test before submitting:
xcodebuild -project macgit.xcodeproj -scheme macgit -destination 'platform=macOS' build xcodebuild -project macgit.xcodeproj -scheme macgit -destination 'platform=macOS' test
-
Commit with a clear, descriptive message. Use Conventional Commits when possible:
feat(stash): add undo support for stash apply fix(merge): resolve conflict marker rendering docs: update contributing guidelines -
Push your branch and open a pull request against
main. -
In your PR description:
- Describe what changed and why.
- Reference any related issues (e.g.,
Closes #42). - Include screenshots or screen recordings for UI changes.
-
Respond to review feedback. Maintainers may request changes before merging.
- Commits: imperative mood, lowercase, no period (e.g., "add undo support", not "Added undo support" or "Adds undo support").
- PR titles: match commit style.
- Branches: use descriptive names like
feature/drag-drop-stash,fix/merge-conflict-rendering.
Thank you for contributing to Commit+!