Git Way turns your phone into a real GitHub push client. Point it at a project
folder, it compares that folder against a repository's actual Git tree (real blob
SHA hashing, not just filenames), shows you exactly what changed, and pushes a
single atomic commit — all from the Storage Access Framework, no git binary and
no laptop involved.
- Features
- Screenshots
- Tech stack
- Project structure
- How a push actually works
- Getting started
- Contributing
- License
Compare & push
- Real diff engine — hashes local files as Git blobs and compares against the repository's live tree, so Added / Modified / Removed is always accurate, not guessed from timestamps.
- Repository-scaffolding files (
README.md,LICENSE,.gitignore,.github/workflows,.gitkeep, Play Storescreenshots/, etc.) are automatically excluded from "Removed" detection — pushing from your phone never threatens to delete files GitHub itself owns. Anything else can be marked "don't track" per-file, permanently. - Manual file selection before every push — select all, clear, or pick files one by one per Added/Modified/Removed group.
- Atomic commits via GitHub's Git Data API (blob → tree → commit → ref update) — a push either lands completely or not at all, never a half-finished commit.
- Automatic retry with backoff on transient network errors (timeouts, 502/503/504);
GitHub's real error message is parsed and shown — never just a bare
HTTP 422. - Live, granular progress: Validating → Uploading files → Creating tree → Creating commit → Updating branch → Verifying → Done, with a cancel button at every stage.
Safety
- Smart Upload Protection — scans every file before upload for secrets (API
keys, tokens) and known-sensitive files (keystores,
.env), and blocks or redacts them automatically. - Project/Repository Identity Match — detects the Android
applicationIdfrom both the local folder and the remote repo before a push, and warns if they don't match, so you can't accidentally push one app's code into another app's repo.
Everyday use
- GitHub sign-in via a Personal Access Token only — no OAuth backend, nothing proxied through a third-party server.
- In-app Repository Browser — view a repo's remote file tree, open files with syntax highlighting, delete files/folders directly on GitHub.
- Repository list with search, sort (recent / A–Z), and per-language color coding.
- Light, Dark, and true-black AMOLED themes.
![]() |
![]() |
![]() |
![]() |
| Layer | Choice |
|---|---|
| Language | Kotlin |
| UI | Jetpack Compose + Material 3 (custom "Liquid Glass" design system) |
| Architecture | MVVM (ui → domain → data), manual DI (no Hilt/Koin) |
| Networking | Retrofit + kotlinx.serialization, GitHub REST + Git Data API |
| Async | Kotlin Coroutines |
| Local storage | Storage Access Framework (project files), AndroidX Security / |
| EncryptedSharedPreferences (GitHub token) | |
| Min SDK | 26 (Android 8.0) |
Git_Way/
├── app/
│ └── src/main/
│ ├── kotlin/com/io/git/way/
│ │ ├── AppContainer.kt # Manual DI container
│ │ ├── GitWayApp.kt # Application class
│ │ ├── MainActivity.kt # Single-activity host
│ │ │
│ │ ├── data/
│ │ │ ├── local/ # On-device logic — no network
│ │ │ │ ├── FolderScanner.kt # SAF folder walk → LocalFile list
│ │ │ │ ├── GitBlobHasher.kt # Real Git blob SHA-1 hashing
│ │ │ │ ├── PathNormalizer.kt # Path cleanup before pushing
│ │ │ │ ├── SecretScanner.kt # Smart Upload Protection: secrets
│ │ │ │ ├── KeystoreSanitizer.kt # Smart Upload Protection: keystores
│ │ │ │ ├── ProtectionScanner.kt # Orchestrates the scan above
│ │ │ │ ├── IgnoreEngine.kt # .gitignore-style local filtering
│ │ │ │ ├── IgnoreListManager.kt # User's manual "don't track" list
│ │ │ │ ├── AppIdentityDetector.kt # applicationId match protection
│ │ │ │ ├── TokenManager.kt # Encrypted PAT storage
│ │ │ │ └── NetworkUtils.kt # Connectivity pre-check
│ │ │ │
│ │ │ ├── remote/
│ │ │ │ ├── GitHubApiService.kt # Retrofit endpoints (REST + Git Data API)
│ │ │ │ ├── RetrofitProvider.kt # Client/JSON setup
│ │ │ │ └── dto/GitHubDtos.kt # Wire-format models
│ │ │ │
│ │ │ └── repository/
│ │ │ └── GitHubRepositoryImpl.kt # Push pipeline, retries, error parsing
│ │ │
│ │ ├── domain/
│ │ │ ├── ComparisonEngine.kt # Added/Modified/Removed diff logic
│ │ │ ├── RepositoryScaffoldFiles.kt # Repo-only-file exclusion rules
│ │ │ ├── CommitMessageBuilder.kt
│ │ │ ├── model/ # Plain Kotlin domain models
│ │ │ └── repository/GitHubRepository.kt # Interface the ViewModels depend on
│ │ │
│ │ ├── navigation/
│ │ │ ├── GitWayNavGraph.kt
│ │ │ └── Routes.kt
│ │ │
│ │ └── ui/
│ │ ├── common/ # Shared ViewModel, formatters, file-icon mapping
│ │ ├── theme/ # Color tokens, Type, Theme, "Liquid Glass" components
│ │ └── screens/
│ │ ├── splash/
│ │ ├── auth/ # Token entry
│ │ ├── overview/
│ │ ├── repos/ # Repository list
│ │ ├── browser/ # In-app remote file browser
│ │ ├── folder/ # Local folder picker
│ │ ├── analysis/ # Compare / select files to push
│ │ ├── confirm/ # Final push confirmation
│ │ ├── upload/ # Live push progress
│ │ ├── complete/ # Success screen
│ │ └── profile/
│ │
│ ├── res/ # Standard Android resources
│ └── AndroidManifest.xml
│
├── .github/
│ └── workflows/
│ ├── release.yml # Tag push -> build APK -> publish GitHub Release
│ └── build-check.yml # Compile check on every push/PR
│
├── docs/
│ ├── banner.png # This README's banner
│ ├── generate_screenshots.py # Rebuilds the Screenshots section above
│ ├── RELEASING.md # How to cut a new release
│ └── screenshots/ # Drop 1.png, 2.png, 3.png, ... here
│
├── gradle/ # Version catalog + wrapper
├── build.gradle.kts
├── settings.gradle.kts
├── keystore.properties.example # Copy to keystore.properties for release builds
├── LICENSE
├── CONTRIBUTING.md
└── README.md
- Scan — the selected local folder is walked via the Storage Access Framework; every file is run through Smart Upload Protection (secret scanning, keystore detection) before anything else touches it.
- Identity check — the app's
applicationIdis read from both the local project and the target repository's remote tree; a mismatch blocks the push. - Compare — every local file is hashed the same way Git hashes a blob and
compared against the repository's current tree via the Git Data API. Repo
scaffolding (README,
.github/, etc.) never shows up as "Removed". - Select — you pick exactly which Added/Modified/Removed files to include.
- Push — blobs are created for changed files, a new tree is built on top of
the current
base_tree, a commit is created, and the branch ref is updated — in that order, atomically. Any transient failure (timeout, 5xx) retries automatically; anything else (permissions, invalid tree, etc.) shows GitHub's real error text. - Verify — after the push, the branch ref is re-fetched to confirm it now points at the new commit before the app reports success.
git clone https://github.com/Sandeepbedia/GitWay.git
cd GitWay
cp keystore.properties.example keystore.propertiesOpen the project in Android Studio, let Gradle sync, and run the app
configuration on a device or emulator (API 26+). No backend, API keys, or .env
setup needed — Git Way talks to api.github.com directly using a GitHub
Personal Access Token you paste in at
runtime.
Create a classic token with these three scopes (the Connect screen validates and flags any that are missing):
| Scope | Needed for |
|---|---|
repo |
Read/write all repositories (contents, PRs, issues, releases) |
workflow |
Updating .github/workflows files and triggering runs |
delete_repo |
Deleting repositories (Profile → Repo settings) |
A fine-grained token works too, but GitHub doesn't report its permissions via the API — grant the equivalent repository permissions (contents read/write, workflows, and delete) and the app will proceed with a "couldn't verify scopes" warning.
Tagged pushes (v1.0, v1.1, ...) are built and published automatically by
.github/workflows/release.yml — see
docs/RELEASING.md for the full process. The app itself
checks the latest release
on launch and shows an in-app Update available dialog when a newer version has
been published — no manual "check for updates" needed.
Contributions are genuinely welcome — bug fixes, small features, docs, and UI polish. Please read CONTRIBUTING.md first; it covers dev setup, code conventions, and the Pull Request checklist. Please open an issue before starting on anything larger than a small fix, so scope can be agreed on before you invest time.
Git Way is released under the GNU General Public License v3.0 — see LICENSE for the full text. The short version:
- ✅ You can read the code, fork it, build it, modify it, and redistribute it.
- ✅ You can publish your own modified/rebranded copy — as long as it also stays open source under GPL-3.0 and you keep the copyright/license notices.
- ❌ You can't relicense it as closed-source or strip the GPL terms from a redistributed copy.




