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.

⚙️ 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
  • 📄 Status overview: status command shows both Git and environment changes in one view

💻 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

gvit clone example

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)

Check Status

Combined view of Git status and environment changes:

# Show just repository (same as `git status`)
gvit status

# Show repository and environment status
gvit status

# In a specific directory
gvit status -e --target-dir path/to/repo

What it shows:

  • 📂 Repository Status: Standard git status output
  • 🐍 Environment Status: Packages added/removed/modified since last tracking
  • ✅ Clean overview of both code and dependency changes
  • ⚡ Quick way to see if you need to update dependency files

gvit status example

Configuration Management

# 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

gvit prune example

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

gvit status: Shows combined repository and environment status

  1. Displays git status output for repository changes
  2. Finds tracked environment for current repository
  3. Compares pip freeze outputs (stored snapshot vs. current state)
  4. Shows package changes: added, removed, modified versions
  5. Provides clean overview of both code and dependency changes

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
│   │   ├── status.py       # Status command (git + environment overview)
│   │   ├── 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
Status command Combined view of Git status and environment changes

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
├── status
└── 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.4.0.tar.gz (417.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.4.0-py3-none-any.whl (46.8 kB view details)

Uploaded Python 3

File details

Details for the file gvit-0.4.0.tar.gz.

File metadata

  • Download URL: gvit-0.4.0.tar.gz
  • Upload date:
  • Size: 417.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.4.0.tar.gz
Algorithm Hash digest
SHA256 8846a766e345cdebe46a945ed7c8a8d3f41cde5450cbcc288c1d8a847e847c30
MD5 1a20f96010b231fe39e84c5c65414c7c
BLAKE2b-256 84a1fdeff8f785bfa18b89c5775722fd7b3ad1d476f4866f074d7354ba4f2e8e

See more details on using hashes here.

File details

Details for the file gvit-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: gvit-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 46.8 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.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 18ba337fc6922167d2245be84304e40ff939caa2f6f508d81c9ed87ccde241b8
MD5 6650214d9b1ae9bf3ba0ef72927e8ac8
BLAKE2b-256 7a98b2794c83a942846f53fd6758c20fa2afa91734893ef0f1f1fee0a4f7a62d

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