Skip to main content

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. conda is 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

gvit clone example

gvit prune example


⚙️ 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.toml or 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 prune command
  • 🌳 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, and virtualenv support
  • 🔒 Dependency validation: commit command 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

  1. Clones the repository using standard git clone
  2. Detects repository name from URL (handles .git suffix correctly)
  3. Proceeds to environment setup (steps 3-7 below)

gvit init: Initializes Git repository + creates environment

  1. Initializes Git repository using git init
  2. Optionally adds remote if --remote-url is provided
  3. Proceeds to environment setup (steps 3-7 below)

gvit setup: Creates environment for existing repository

  1. Verifies Git repository exists in target directory
  2. Detects remote URL if available
  3. Proceeds to environment setup (steps 3-7 below)

gvit pull: Pulls changes and syncs dependencies

  1. Finds tracked environment for current repository
  2. Runs git pull with any extra arguments you provide
  3. Compares dependency file hashes (stored in registry vs. current files)
  4. Reinstalls only changed dependencies automatically
  5. Updates registry with new hashes

gvit envs reset: Resets an environment to clean state

  1. Deletes the environment backend (venv folder or conda env)
  2. Recreates it empty with the same Python version
  3. Reinstalls dependencies from registry (unless --no-deps)
  4. Updates registry with new hashes, freeze snapshot, and timestamp
  5. Preserves registry entry (unlike delete + setup)

gvit commit: Validates dependencies before committing

  1. Finds tracked environment for current repository
  2. Compares pip freeze outputs (stored snapshot vs. current state)
  3. Detects package changes: added, removed, modified versions
  4. Validates dependency files to ensure changes are reflected
  5. Shows detailed report of discrepancies (if any)
  6. Runs git commit with any extra arguments you provide

Environment Setup Process (common to all commands)

  1. 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)
  2. Resolves dependencies with priority system:
    • CLI arguments (highest priority)
    • Repository config (.gvit.toml)
    • Local config (~/.config/gvit/config.toml)
    • Default values (lowest priority)
  3. Installs dependencies from:
    • pyproject.toml (with optional extras support)
    • requirements.txt or custom paths
    • Multiple dependency groups (_base, dev, test, etc.)
  4. 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)
  5. 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)
  • checkout and 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gvit-0.3.0.tar.gz (265.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gvit-0.3.0-py3-none-any.whl (44.3 kB view details)

Uploaded Python 3

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

Hashes for gvit-0.3.0.tar.gz
Algorithm Hash digest
SHA256 2234e27130c6461be5f2288f09d62c777874404101fa1a53f0bdd45d7959c9b2
MD5 02a2802e01d33a81b807caf3a69e3816
BLAKE2b-256 773f006b8b4cde257f4a4e68c113ce46ef1fdb3c654c74a6b4cb302c3f35dbf8

See more details on using hashes here.

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

Hashes for gvit-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3744f1cbe4cfbdaeaf84af7b312358f44affc96bbfdab8d077c49f6f40a4c997
MD5 9c7d59281b467f11b3cd20cabce02164
BLAKE2b-256 a842f98c3b0587aa3d19b726ed3c7f3700023f4dca0bbf497b8f5a6201094e5d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page