Automates virtual environment management for Git repositories
Project description
░██ ░██
░██
░████████ ░██ ░██ ░██░████████
░██ ░██ ░██ ░██ ░██ ░██
░██ ░██ ░██ ░██ ░██ ░██
░██ ░███ ░██░██ ░██ ░██
░█████░██ ░███ ░██ ░████
░██
░███████
Git-aware Virtual Environment Manager
Automates virtual environment management for Git repositories.
gvit is a command-line tool that automatically creates and manages virtual environments when you clone repositories. Its goal is to eliminate friction between version control and Python environment management.
🚀 Motivation
Have you ever cloned a project and had to do all this?
git clone https://github.com/someone/project.git
cd project
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
With gvit, all of that happens automatically:
# Clone from scratch
gvit clone https://github.com/someone/project.git
# Or setup an existing repo
cd existing-project
gvit setup
🎉 Environment created and dependencies installed!
When to use gvit vs other tools
Use gvit if you:
- Work on multiple projects simultaneously.
- Want Git workflows to automatically sync environments.
- Need centralized environment tracking.
- Want flexibility in backends (e.g.
condais crucial for certain DS/ML projects). - Work with legacy projects that still do not use
pyproject.toml.
Use uv if you:
- Primarily work on one project at a time.
- Want the fastest package installation.
- Focus on modern Python packaging (
pyproject.toml). - Need advanced dependency resolution.
Examples
⚙️ What gvit does
- 🪄 Automatically creates environments when cloning or initializing repos
- 📦 Installs dependencies from
requirements.txt,pyproject.toml, or custom paths - 🎯 Supports extra dependencies (dev, test, etc.) from
pyproject.tomlor separate files - 🧠 Remembers your preferences via local configuration (
~/.config/gvit/config.toml) - 📝 Tracks environments in registry (
~/.config/gvit/envs/) with metadata and dependency hashes - 🧘 Cleans orphaned environments automatically with
prunecommand - 🌳 Visual command tree to explore available commands
- ⚡ Smart priority resolution: CLI options → repo config → local config → defaults
- 🔧 Flexible configuration: per-repository (
.gvit.toml) or global settings - 🐍 Multiple backends:
venv(built-in),conda, andvirtualenvsupport - 🔒 Dependency validation:
commitcommand validates installed packages match declared dependencies
💻 Installation
pip install gvit
Or with pipx (recommended for CLI tools):
pipx install gvit
🧩 Usage
Initial Configuration
Set up your default preferences (interactive):
gvit config setup
Or specify options directly:
gvit config setup --backend venv --python 3.11 --base-deps requirements.txt
# or use conda
gvit config setup --backend conda --python 3.11
# or use virtualenv (faster, more features)
gvit config setup --backend virtualenv --python 3.11
Clone a Repository
Basic clone with automatic environment creation:
gvit clone https://github.com/user/repo.git
Advanced options:
# Custom environment name
gvit clone https://github.com/user/repo.git --venv-name my-env
# Specify Python version
gvit clone https://github.com/user/repo.git --python 3.12
# Install extra dependencies from pyproject.toml
gvit clone https://github.com/user/repo.git --extra-deps dev,test
# Skip dependency installation
gvit clone https://github.com/user/repo.git --no-deps
# Force overwrite existing environment
gvit clone https://github.com/user/repo.git --force
# Verbose output
gvit clone https://github.com/user/repo.git --verbose
Initialize a New Project
Similar to git init but with environment setup:
# In current directory
gvit init
# In specific directory
gvit init my-project
# With remote repository
gvit init --remote-url https://github.com/user/my-project.git
# With all options
gvit init my-project \
--remote-url https://github.com/user/my-project.git \
--python 3.12 \
--extra-deps dev,test
Setup an Existing Repository
If you already have a cloned repository and want to set up the environment:
# In the repository directory
cd my-existing-repo
gvit setup
# Or specify a different directory
gvit setup path/to/repo
# With custom options
gvit setup --python 3.12 --extra-deps dev,test
# Skip dependency installation
gvit setup --no-deps
Pull Changes and Update Dependencies
Smart git pull that automatically detects and reinstalls changed dependencies:
# Pull and auto-update dependencies if changed
gvit pull
# Pull without checking dependencies
gvit pull --no-deps
# Force reinstall all dependencies even if unchanged
gvit pull --force-deps
# Pass options to git pull
gvit pull --rebase origin main
Commit with Dependency Validation
Smart git commit that validates your installed packages match your dependency files:
# Commit with automatic validation
gvit commit -m "Add new feature"
# Skip validation if needed
gvit commit --skip-validation -m "Quick fix"
# Pass any git commit options
gvit commit -a -m "Update everything"
gvit commit --amend
What it validates:
- ✅ Detects added packages not declared in dependency files
- ✅ Detects removed packages still declared in dependency files
- ✅ Detects version changes not reflected in pinned versions
- ✅ Works with
requirements.txt,pyproject.toml, and custom paths - ✅ Shows detailed diff of package changes (added/removed/modified)
### Configuration Management
```bash
# Add extra dependency groups to local config
gvit config add-extra-deps dev requirements-dev.txt
gvit config add-extra-deps test requirements-test.txt
# Remove extra dependency groups
gvit config remove-extra-deps dev
# Show current configuration
gvit config show
Environment Management
# List all tracked environments
gvit envs list
# Show details of a specific environment
gvit envs show my-env
# Remove an environment (registry and backend)
gvit envs delete my-env
# Reset an environment (recreate and reinstall dependencies)
gvit envs reset my-env
# Reset without reinstalling dependencies
gvit envs reset my-env --no-deps
# Clean up orphaned environments (repos that no longer exist)
gvit envs prune
# Preview what would be removed
gvit envs prune --dry-run
# Auto-confirm removal
gvit envs prune --yes
Explore Commands
# Show all available commands in tree structure
gvit tree
🧠 How it works
Commands
gvit clone: Clones repository + creates environment
- Clones the repository using standard
git clone - Detects repository name from URL (handles
.gitsuffix correctly) - Proceeds to environment setup (steps 3-7 below)
gvit init: Initializes Git repository + creates environment
- Initializes Git repository using
git init - Optionally adds remote if
--remote-urlis provided - Proceeds to environment setup (steps 3-7 below)
gvit setup: Creates environment for existing repository
- Verifies Git repository exists in target directory
- Detects remote URL if available
- Proceeds to environment setup (steps 3-7 below)
gvit pull: Pulls changes and syncs dependencies
- Finds tracked environment for current repository
- Runs
git pullwith any extra arguments you provide - Compares dependency file hashes (stored in registry vs. current files)
- Reinstalls only changed dependencies automatically
- Updates registry with new hashes
gvit envs reset: Resets an environment to clean state
- Deletes the environment backend (venv folder or conda env)
- Recreates it empty with the same Python version
- Reinstalls dependencies from registry (unless
--no-deps) - Updates registry with new hashes, freeze snapshot, and timestamp
- Preserves registry entry (unlike
delete+setup)
gvit commit: Validates dependencies before committing
- Finds tracked environment for current repository
- Compares pip freeze outputs (stored snapshot vs. current state)
- Detects package changes: added, removed, modified versions
- Validates dependency files to ensure changes are reflected
- Shows detailed report of discrepancies (if any)
- Runs
git commitwith any extra arguments you provide
Environment Setup Process (common to all commands)
- Creates virtual environment using your preferred backend:
venv: Python's built-in venv module (creates.venv/in repo)virtualenv: Enhanced virtual environments (creates.venv/in repo, faster than venv)conda: Conda environments (centralized management)
- Resolves dependencies with priority system:
- CLI arguments (highest priority)
- Repository config (
.gvit.toml) - Local config (
~/.config/gvit/config.toml) - Default values (lowest priority)
- Installs dependencies from:
pyproject.toml(with optional extras support)requirements.txtor custom paths- Multiple dependency groups (_base, dev, test, etc.)
- Tracks environment in registry:
- Saves environment metadata to
~/.config/gvit/envs/{env_name}.toml - Records dependency file hashes for change detection
- Stores complete pip freeze snapshot for validation
- Stores repository information (path, URL)
- Saves environment metadata to
- Validates and handles conflicts:
- Detects existing environments
- Offers options: rename, overwrite, or abort
- Auto-generates unique names if needed
⚙️ Configuration
Local Configuration
Global preferences: ~/.config/gvit/config.toml
[gvit]
backend = "venv" # or "conda", "virtualenv"
python = "3.11"
[deps]
_base = "requirements.txt"
dev = "requirements-dev.txt"
test = "requirements-test.txt"
[backends.venv]
name = ".venv" # Directory name for venv (default: .venv)
[backends.virtualenv]
name = ".venv" # Directory name for virtualenv (default: .venv)
[backends.conda]
path = "/path/to/conda" # Optional: custom conda path
Environment Registry
Environment tracking: ~/.config/gvit/envs/{env_name}.toml
[environment]
name = "my-project"
backend = "conda"
python = "3.11"
created_at = "2025-01-22T20:53:01.123456"
[repository]
path = "/Users/user/projects/my-project"
url = "https://github.com/user/my-project.git"
[deps]
_base = "requirements.txt"
dev = "requirements-dev.txt"
[deps.installed]
_base_hash = "a1b2c3d4e5f6g7h8" # SHA256 hash for change detection
dev_hash = "i9j0k1l2m3n4o5p6"
_freeze_hash = "q7r8s9t0u1v2w3x4" # SHA256 hash of pip freeze output
_freeze = """ # Complete pip freeze snapshot for validation
package1==1.0.0
package2==2.3.4
"""
installed_at = "2025-01-22T20:53:15.789012"
Repository Configuration
Per-project settings: .gvit.toml (in repository root)
[gvit]
python = "3.12" # Override Python version for this project
[deps]
_base = "requirements.txt"
dev = "requirements-dev.txt"
internal = "requirements-internal.txt"
Or use pyproject.toml (tool section):
[tool.gvit]
python = "3.12"
[tool.gvit.deps]
_base = "pyproject.toml"
🧱 Architecture
gvit/
├── src/gvit/
│ ├── cli.py # CLI entry point (Typer app)
│ ├── env_registry.py # Environment registry management
│ ├── commands/
│ │ ├── _common.py # Shared functions between commands
│ │ ├── clone.py # Clone command logic
│ │ ├── init.py # Init command logic
│ │ ├── setup.py # Setup command logic (existing repos)
│ │ ├── pull.py # Pull command with smart dependency sync
│ │ ├── commit.py # Commit command with dependency validation
│ │ ├── tree.py # Tree command (show command structure)
│ │ ├── config.py # Config management commands
│ │ └── envs.py # Environment management commands
│ ├── backends/
│ │ ├── venv.py # Venv backend implementation
│ │ ├── virtualenv.py # Virtualenv backend implementation
│ │ └── conda.py # Conda backend implementation
│ ├── utils/
│ │ ├── exceptions.py # Custom exceptions
│ │ ├── utils.py # Helper functions
│ │ ├── validators.py # Input validation
│ │ ├── globals.py # Constants and defaults
│ │ └── schemas.py # Type definitions (TypedDict)
│ └── __init__.py
└── pyproject.toml # Project metadata
🧭 Roadmap
Current Release (v0.0.3)
| Feature | Status | Description |
|---|---|---|
| Clone command | ✅ | Full repository cloning with environment setup |
| Init command | ✅ | Initialize new Git repos with environment setup |
| Setup command | ✅ | Create environment for existing repositories |
| Pull command | ✅ | Smart git pull with automatic dependency sync |
| Commit command | ✅ | Git commit with automatic dependency validation |
| Tree command | ✅ | Visual command structure explorer |
| Venv backend | ✅ | Python's built-in venv support |
| Conda backend | ✅ | Complete conda integration |
| Virtualenv backend | ✅ | Complete virtualenv integration |
| Config management | ✅ | setup, add-extra-deps, remove-extra-deps, show |
| Environment registry | ✅ | Track environments with metadata, dependency hashes, and freeze snapshots |
| Environment management | ✅ | list, show, delete, prune, reset commands |
| Orphan cleanup | ✅ | Automatic detection and removal of orphaned environments |
| Dependency resolution | ✅ | Priority-based resolution (CLI > repo > local > default) |
| pyproject.toml support | ✅ | Install base + optional dependencies (extras) |
| Requirements.txt support | ✅ | Standard pip requirements files |
| Custom dependency paths | ✅ | Flexible path specification via config or CLI |
| Environment validation | ✅ | Detect conflicts, offer resolution options |
| TypedDict schemas | ✅ | Full type safety with typed configuration schemas |
| Dependency validation | ✅ | Validate installed packages match declared dependencies on commit |
Next Releases
| Version | Status | Description |
|---|---|---|
| 0.6.0 | 📋 Planned | Add checkout command to switch branches and sync deps |
| 0.6.0 | 📋 Planned | Shell integration (gvit activate) and completions |
| 0.6.0 | 📋 Planned | gvit sync command for full dependency refresh |
| 1.0.0 | 🎯 Goal | Stable release with all core features |
🧑💻 Example Workflows
First Time Setup
# Install gvit
pipx install gvit
# Configure defaults (use venv or conda)
gvit config setup --backend venv --python 3.11
# Add common dependency groups
gvit config add-extra-deps dev requirements-dev.txt
gvit config add-extra-deps test requirements-test.txt
Standard Project
# Clone with base dependencies
gvit clone https://github.com/user/project.git
# Activate environment
conda activate project
Project with Extra Dependencies
# Clone and install dev dependencies
gvit clone https://github.com/user/project.git --extra-deps dev
# Or multiple groups
gvit clone https://github.com/user/project.git --extra-deps dev,test
# Activate
conda activate project
Project with pyproject.toml
# Install base dependencies from pyproject.toml
gvit clone https://github.com/user/project.git
# Install with optional dependencies defined in [project.optional-dependencies]
gvit clone https://github.com/user/project.git --extra-deps dev,test
Custom Configuration
# Override everything from CLI
gvit clone https://github.com/user/project.git \\
--venv-name custom-env \\
--python 3.12 \\
--backend conda \\
--base-deps requirements/prod.txt \\
--extra-deps dev:requirements/dev.txt,test:requirements/test.txt \\
--verbose
Initialize a New Project
# Create a new project from scratch
mkdir my-new-project
cd my-new-project
gvit init --remote-url https://github.com/user/my-new-project.git
# Now ready to work
echo "# My Project" > README.md
git add .
git commit -m "Initial commit"
git push -u origin main
Setup an Existing Repository
# You already cloned a repo manually
git clone https://github.com/user/project.git
cd project
# Now set up the environment
gvit setup
# Or with specific options
gvit setup --python 3.12 --extra-deps dev,test
Daily Workflow with Pull
# Update your project (code + dependencies)
cd my-project
gvit pull
# If requirements.txt changed:
# - Dependency changes detected: base
# - Reinstalling base dependencies from requirements.txt...
# 🎉 Repository and dependencies updated successfully!
# Continue working
conda activate my-project
Managing Tracked Environments
# See all environments gvit knows about
gvit envs list
# Check environment details (shows registry file with syntax highlighting)
gvit envs show my-project
# Remove specific environment (registry + backend)
gvit envs delete old-project
# Reset an environment (recreate + reinstall dependencies from registry)
gvit envs reset my-project
# Reset without dependencies (useful for testing clean environments)
gvit envs reset my-project --no-deps
# Clean up all orphaned environments
gvit envs prune
# See what would be cleaned without actually removing
gvit envs prune --dry-run
Fixing a Broken Environment
# Your environment is corrupted or has dependency conflicts
cd my-project
# Reset the environment (recreates it from scratch)
gvit envs reset my-project-abc123
# Output:
# ⚠️ This will reset environment "my-project-abc123":
# Backend: venv
# Python: 3.11
# Path: /path/to/my-project/.venv
# Repository: /path/to/my-project
#
# Continue? [y/N]: y
#
# - Deleting environment backend...✅
# - Recreating environment with Python 3.11 (this might take some time)...✅
#
# - Reinstalling dependencies from registry...
# Group "_base"...✅
# Group "dev"...✅
#
# - Updating registry with new dependency hashes...✅
#
# 🎉 Environment "my-project-abc123" reset successfully!
# Registry updated at: ~/.config/gvit/envs/my-project-abc123.toml
# Environment is now clean and ready to use
source .venv/bin/activate
Explore Available Commands
gvit tree
# Output:
gvit
├── clone
├── commit
├── config
│ ├── add-extra-deps
│ ├── remove-extra-deps
│ ├── setup
│ └── show
├── envs
│ ├── delete
│ ├── list
│ ├── prune
│ ├── reset
│ └── show
├── init
├── pull
├── setup
└── tree
🤝 Contributing
Contributions are welcome! Areas we'd love help with:
- Additional backends (pyenv, poetry)
checkoutand other commands- Cross-platform testing
- Documentation improvements
Open an issue or submit a pull request on GitHub.
⚖️ License
MIT © 2025
⭐ Vision
“One repo, its own environment — without thinking about it.”
The goal of gvit is to eliminate the need to manually create or update virtual environments. Git and Python should work together seamlessly — this tool makes it possible.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gvit-0.3.0.tar.gz.
File metadata
- Download URL: gvit-0.3.0.tar.gz
- Upload date:
- Size: 265.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2234e27130c6461be5f2288f09d62c777874404101fa1a53f0bdd45d7959c9b2
|
|
| MD5 |
02a2802e01d33a81b807caf3a69e3816
|
|
| BLAKE2b-256 |
773f006b8b4cde257f4a4e68c113ce46ef1fdb3c654c74a6b4cb302c3f35dbf8
|
File details
Details for the file gvit-0.3.0-py3-none-any.whl.
File metadata
- Download URL: gvit-0.3.0-py3-none-any.whl
- Upload date:
- Size: 44.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3744f1cbe4cfbdaeaf84af7b312358f44affc96bbfdab8d077c49f6f40a4c997
|
|
| MD5 |
9c7d59281b467f11b3cd20cabce02164
|
|
| BLAKE2b-256 |
a842f98c3b0587aa3d19b726ed3c7f3700023f4dca0bbf497b8f5a6201094e5d
|