Back to Blog
December 5, 202518 min readArion Interactive Team

Mastering Version Managers: The Complete Guide to nvm, jenv, and gvm

Master the art of managing multiple runtime versions seamlessly with nvm for Node.js, jenv for Java, and gvm for Go. Never struggle with version conflicts again.

Development ToolsnvmjenvgvmTutorialDevOps
Mastering Version Managers: The Complete Guide to nvm, jenv, and gvm

Managing multiple versions of programming languages is a challenge every developer faces. Whether you're maintaining legacy projects, testing across different versions, or working on multiple applications simultaneously, version managers are essential tools in your development arsenal. This comprehensive guide walks you through setting up and mastering nvm (Node Version Manager), jenv (Java Environment Manager), and gvm (Go Version Manager).

Why Version Managers Matter

Before diving into setup, let's understand why version managers are indispensable:

Project-Specific Requirements: Different projects often require different language versions. A legacy application might need Node.js 14, while your new project uses Node.js 20.

Testing Across Versions: Ensure compatibility by testing your code against multiple runtime versions without complicated system-wide installations.

Team Consistency: Version managers make it easy to ensure every team member uses the exact same language version, eliminating "works on my machine" scenarios.

Safe Experimentation: Test new language features and versions without affecting your stable development environment.

Part 1: Setting Up nvm (Node Version Manager)

Node Version Manager is the most popular tool for managing multiple Node.js installations. It's fast, reliable, and incredibly easy to use.

Installing nvm

On Linux/macOS/WSL:

# Download and install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

# Or using wget
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

The installation script automatically adds nvm to your shell profile (~/.bashrc, ~/.zshrc, or ~/.profile).

Activate nvm immediately:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"

Verify installation:

nvm --version
# Output: 0.39.7

Using nvm: Essential Commands

Install the latest LTS version:

nvm install --lts

Install a specific version:

nvm install 18.19.0
nvm install 20.11.0
nvm install 16.20.2

List installed versions:

nvm ls
# Output shows all installed versions with the current one marked

Switch between versions:

nvm use 18.19.0
# Now using node v18.19.0

nvm use 20
# Automatically uses the latest v20.x installed

Set a default version:

nvm alias default 20.11.0
# This version loads when you open a new terminal

Check current version:

node --version
# v20.11.0

Pro nvm Tips

Project-specific Node version with .nvmrc:

Create a .nvmrc file in your project root:

echo "18.19.0" > .nvmrc

Now anyone can use the correct version:

cd your-project
nvm use
# Found '.nvmrc' with version <18.19.0>
# Now using node v18.19.0

Automatic version switching (optional):

Add to your ~/.zshrc or ~/.bashrc:

# Automatically switch Node version when entering a directory with .nvmrc
autoload -U add-zsh-hook
load-nvmrc() {
  local node_version="$(nvm version)"
  local nvmrc_path="$(nvm_find_nvmrc)"

  if [ -n "$nvmrc_path" ]; then
    local nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")
    if [ "$nvmrc_node_version" = "N/A" ]; then
      nvm install
    elif [ "$nvmrc_node_version" != "$node_version" ]; then
      nvm use
    fi
  elif [ "$node_version" != "$(nvm version default)" ]; then
    nvm use default
  fi
}
add-zsh-hook chpwd load-nvmrc
load-nvmrc

Migrate global packages:

When switching versions, migrate your global npm packages:

nvm install 20 --reinstall-packages-from=18

Uninstall a version:

nvm uninstall 16.20.2

Part 2: Setting Up jenv (Java Environment Manager)

jenv allows you to manage multiple Java installations seamlessly, perfect for projects requiring different JDK versions.

Installing jenv

On macOS with Homebrew:

brew install jenv

On Linux/WSL:

git clone https://github.com/jenv/jenv.git ~/.jenv

Configure your shell:

For Bash (~/.bashrc):

export PATH="$HOME/.jenv/bin:$PATH"
eval "$(jenv init -)"

For Zsh (~/.zshrc):

export PATH="$HOME/.jenv/bin:$PATH"
eval "$(jenv init -)"

Reload your shell:

exec $SHELL -l

Verify installation:

jenv --version
# jenv 0.5.x

Installing Java JDKs

Before using jenv, you need Java installations. Here's how to install multiple versions:

On Ubuntu/Debian:

# Install OpenJDK 11
sudo apt install openjdk-11-jdk

# Install OpenJDK 17
sudo apt install openjdk-17-jdk

# Install OpenJDK 21
sudo apt install openjdk-21-jdk

On macOS:

# Install via Homebrew
brew install openjdk@11
brew install openjdk@17
brew install openjdk@21

Configuring jenv

Add Java versions to jenv:

# On Linux
jenv add /usr/lib/jvm/java-11-openjdk-amd64
jenv add /usr/lib/jvm/java-17-openjdk-amd64
jenv add /usr/lib/jvm/java-21-openjdk-amd64

# On macOS (Homebrew installations)
jenv add /usr/local/opt/openjdk@11
jenv add /usr/local/opt/openjdk@17
jenv add /usr/local/opt/openjdk@21

List managed versions:

jenv versions
# Output:
#   system
# * 17.0 (set by /home/user/.jenv/version)
#   11.0
#   21.0

Using jenv: Essential Commands

Set global Java version:

jenv global 17.0

Set local (project-specific) version:

cd your-java-project
jenv local 11.0
# Creates .java-version file

Set shell-specific version:

jenv shell 21.0
# Affects only current shell session

Verify current Java version:

java -version
# openjdk version "17.0.x"

Pro jenv Tips

Enable plugins for better functionality:

# Enable export plugin (sets JAVA_HOME automatically)
jenv enable-plugin export

# Enable maven plugin
jenv enable-plugin maven

# Enable gradle plugin
jenv enable-plugin gradle

List available plugins:

jenv plugins

Check which Java jenv is using:

jenv which java
# Shows full path to java executable

Part 3: Setting Up gvm (Go Version Manager)

gvm makes managing multiple Go versions effortless, essential for Go developers working across different projects.

Installing gvm

Prerequisites:

# On Ubuntu/Debian
sudo apt-get install curl git mercurial make binutils bison gcc build-essential

# On macOS
xcode-select --install
brew install mercurial

Install gvm:

bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)

Source gvm in your shell:

The installer automatically adds gvm to your shell profile. Reload it:

source ~/.gvm/scripts/gvm

Verify installation:

gvm version
# Go Version Manager v1.0.x

Using gvm: Essential Commands

List available Go versions:

gvm listall
# Shows all available Go versions

Install a Go version:

# Install Go 1.21 (requires existing Go or binary bootstrap)
gvm install go1.21.5 -B

# Install Go 1.22
gvm install go1.22.0 -B

The -B flag uses pre-compiled binaries (faster and simpler).

List installed versions:

gvm list
# Shows all installed Go versions

Switch to a version:

gvm use go1.21.5
# Now using version go1.21.5

# Set as default
gvm use go1.21.5 --default

Verify current version:

go version
# go version go1.21.5 linux/amd64

Pro gvm Tips

Create isolated Go environments (pkgsets):

# Create a package set for a specific project
gvm pkgset create myproject

# Use the package set
gvm pkgset use myproject

# List package sets
gvm pkgset list

Package sets isolate dependencies, similar to Python virtual environments.

Uninstall a Go version:

gvm uninstall go1.20.0

Update gvm itself:

gvm get

Real-World Workflows

Scenario 1: Full-Stack Developer

You're working on multiple projects:

# Project A: Legacy Node.js app
cd project-a
echo "14.21.3" > .nvmrc
nvm use
npm install

# Project B: Modern React app
cd ../project-b
echo "20.11.0" > .nvmrc
nvm use
npm install

# Project C: Java microservice
cd ../project-c
jenv local 17.0
./mvnw spring-boot:run

# Project D: Go CLI tool
cd ../project-d
gvm use go1.22.0
go build

Scenario 2: CI/CD Integration

.github/workflows/node-ci.yml:

name: Node CI
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [16.x, 18.x, 20.x]
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm ci
      - run: npm test

Scenario 3: Team Onboarding

Project README.md:

## Setup

1. Install nvm: [instructions]
2. Install correct Node version:
   \`\`\`bash
   nvm install
   nvm use
   \`\`\`
3. Install dependencies:
   \`\`\`bash
   npm install
   \`\`\`

Troubleshooting Common Issues

nvm: command not found

Solution: Source nvm in your current shell:

source ~/.nvm/nvm.sh

Make sure the nvm initialization is in your shell profile.

jenv: JAVA_HOME not set

Solution: Enable the export plugin:

jenv enable-plugin export
exec $SHELL -l

gvm: cannot install Go version

Solution: Use binary installation:

gvm install go1.22.0 -B

Slow shell startup with version managers

Solution: Use lazy loading. Add to ~/.zshrc:

# Lazy load nvm
export NVM_DIR="$HOME/.nvm"
nvm() {
  unset -f nvm
  [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
  nvm "$@"
}

Best Practices

1. Always Use .nvmrc / .java-version Files

Document required versions in your project:

# .nvmrc
18.19.0

# .java-version
17.0

2. Document Version Requirements

Update your README.md:

## Requirements
- Node.js 18.x (managed via nvm)
- Java 17 (managed via jenv)
- Go 1.21+ (managed via gvm)

3. Don't Commit node_modules or Build Artifacts

Your .gitignore:

node_modules/
.nvmrc
.java-version
target/
dist/

4. Keep Version Managers Updated

# Update nvm
cd "$NVM_DIR" && git pull && cd -

# Update gvm
gvm get

5. Use CI/CD Version Matrices

Test against multiple versions automatically to catch compatibility issues early.

Conclusion

Version managers—nvm, jenv, and gvm—are essential tools that eliminate version conflicts, streamline team collaboration, and enable seamless multi-project development. By mastering these tools, you can:

  • Switch between project environments instantly
  • Test across multiple runtime versions effortlessly
  • Onboard new team members in minutes
  • Maintain legacy and modern projects simultaneously

Start with nvm if you're primarily a JavaScript developer, add jenv for Java projects, and incorporate gvm for Go development. Each tool follows similar patterns, making it easy to adopt additional version managers as your tech stack grows.

At Arion Interactive, we leverage these version managers across our development teams to ensure consistent, reproducible builds and seamless collaboration. Ready to modernize your development workflow? Let's build something amazing together!