Skip to main content
Migrating to Git from other version control systems requires planning and understanding of how Git differs from your current system. This guide helps teams successfully transition to Git.

Understanding Git’s Differences

Before migrating, understand how Git differs from centralized VCS:

Distributed vs. Centralized

Traditional VCS (CVS, SVN):
  • Single central repository
  • Commits go directly to server
  • Need network for most operations
  • Linear history model
Git:
  • Every clone is a complete repository
  • Commits are local operations
  • Work offline, sync later
  • Branch-based history model

Key Conceptual Differences

1

Commits are snapshots, not deltas

Git stores complete snapshots of your project, not just changes. This makes operations like branching extremely fast.
2

Branches are lightweight

Creating a branch in Git is instant and cheap. Branches are fundamental to Git workflows, not expensive operations to avoid.
3

Staging area

Git has an intermediate staging area (index) between your working directory and repository. This provides fine-grained control over what you commit.
4

No repository is special

While you can designate a central repository, technically all clones are equal. This enables flexible workflows.

Migration Strategies

Assessment Phase

Before migrating, assess your current setup:
1

Inventory your repositories

  • How many repositories?
  • How large are they?
  • What’s the branching structure?
  • Are there large binary files?
2

Identify dependencies

  • Build scripts referencing VCS
  • Deployment processes
  • CI/CD pipelines
  • Developer tools and IDEs
3

Plan the transition

  • Phased migration vs. big bang
  • Training schedule
  • Pilot projects
  • Rollback plan

Planning Considerations

Timeline:
  • Allow time for learning and adjustment
  • Plan for lower productivity during transition
  • Schedule training sessions
  • Have Git experts available for questions
Resources:
  • Allocate time for training
  • Set up Git infrastructure (hosting, CI/CD)
  • Prepare documentation
  • Assign migration champions

Migrating from CVS

Using git-cvsimport

1

Install dependencies

# Install cvsps (version 2.1 or higher)
# From https://github.com/andreyvit/cvsps
2

Import CVS repository

# From CVS working directory
git cvsimport -C <destination> <module>

# Example:
cd /path/to/cvs/checkout
git cvsimport -C ~/git/project myproject
3

Review imported history

cd ~/git/project
git log --oneline
git branch -a
4

Create a bare repository

git clone --bare project project.git
scp -r project.git server:/git/repositories/

CVS to Git Command Mapping

# CVS                        # Git equivalent
cvs checkout project        git clone user@server:project.git
cvs update                  git pull
cvs commit                  git commit -a && git push
cvs add file.txt            git add file.txt
cvs remove file.txt         git rm file.txt
cvs diff                    git diff
cvs log                     git log
cvs tag RELEASE_1_0         git tag v1.0
cvs status                  git status

Workflow Translation

CVS workflow:
cvs update
# Make changes
cvs commit
Git equivalent:
git pull
# Make changes
git add changed-files
git commit -m "message"
git push
In Git, commit and push are separate operations. You can make multiple local commits before pushing to the central repository.

Migrating from Subversion

Using git-svn

1

Clone SVN repository

# Standard layout (trunk, branches, tags)
git svn clone -s https://svn.example.com/project

# Non-standard layout
git svn clone https://svn.example.com/project \
  --trunk=main \
  --branches=feature-branches \
  --tags=release-tags

# Large repository (start from recent revision)
git svn clone -s -r 1000:HEAD https://svn.example.com/project
2

Clean up the import

# Convert SVN tags to Git tags
git for-each-ref refs/remotes/origin/tags | \
while read sha type ref; do
  tag=$(echo $ref | sed 's|refs/remotes/origin/tags/||')
  git tag -a "$tag" -m "Tag $tag" "$ref"
  git branch -r -d "origin/tags/$tag"
done

# Convert remote branches to local branches
git for-each-ref refs/remotes | \
while read sha type ref; do
  branch=$(echo $ref | sed 's|refs/remotes/origin/||')
  git branch "$branch" "$ref"
done
3

Create bare repository

git clone --bare project project.git

SVN to Git Command Mapping

# SVN                        # Git equivalent
svn checkout url            git clone url
svn update                  git pull
svn commit                  git commit -a && git push
svn add file                git add file
svn delete file             git rm file
svn copy ^/trunk ^/branch   git branch branch
svn switch ^/branch         git switch branch
svn merge                   git merge
svn diff                    git diff
svn log                     git log
svn info                    git remote show origin
svn status                  git status

Hybrid Approach

During transition, maintain both SVN and Git:
# Keep syncing with SVN while using Git
git svn clone -s https://svn.example.com/project
cd project

# Work in Git
git checkout -b feature
# Make changes
git commit -am "Implement feature"

# Sync with SVN
git svn rebase
git svn dcommit
When using git-svn, avoid using Git merge commits. SVN doesn’t understand merge history, so use rebase instead.

Migrating from Mercurial

Using fast-export

1

Install fast-export

git clone https://github.com/frejr/fast-export.git
2

Convert repository

# Create new Git repo
mkdir project-git
cd project-git
git init

# Import from Mercurial
../fast-export/hg-fast-export.sh -r /path/to/hg/project

# Clean up
git checkout HEAD
3

Verify conversion

git log --oneline
git branch -a

Mercurial to Git Command Mapping

# Mercurial                  # Git equivalent
hg clone                    git clone
hg pull                     git fetch
hg update                   git pull
hg commit                   git commit -a
hg push                     git push
hg add                      git add
hg remove                   git rm
hg branch                   git branch
hg merge                    git merge
hg diff                     git diff
hg log                      git log
hg status                   git status
hg tag                      git tag

Setting Up Git Infrastructure

Choosing a Hosting Solution

Self-hosted options:
  • GitLab: Full DevOps platform, CI/CD included
  • Gitea: Lightweight, easy to deploy
  • Gogs: Minimal resource requirements
Cloud-hosted options:
  • GitHub: Largest community, excellent integrations
  • GitLab: Integrated CI/CD, flexible plans
  • Bitbucket: Integrates with Atlassian tools
  • Azure DevOps: Microsoft ecosystem integration

Creating a Central Repository

Set up a shared bare repository:
1

Create bare repository

# On the server
mkdir -p /git/repositories/project.git
cd /git/repositories/project.git
git init --bare --shared
2

Configure access

# SSH access
# Add developers' public keys to ~/.ssh/authorized_keys

# Or use git-shell for restricted access
chsh -s $(which git-shell) gituser
3

Push initial content

# From migrated repository
git remote add origin user@server:/git/repositories/project.git
git push -u origin --all
git push -u origin --tags

HTTP(S) Access

Set up HTTP(S) access with git-http-backend:
# Apache configuration
<VirtualHost *:443>
    ServerName git.example.com
    
    SetEnv GIT_PROJECT_ROOT /git/repositories
    SetEnv GIT_HTTP_EXPORT_ALL
    
    ScriptAlias /git/ /usr/lib/git-core/git-http-backend/
    
    <Location /git>
        AuthType Basic
        AuthName "Git Access"
        AuthUserFile /etc/apache2/git-users
        Require valid-user
    </Location>
</VirtualHost>

Team Training

Training Plan

1

Basic Git concepts (1-2 hours)

  • Repositories, commits, branches
  • Distributed model
  • Staging area
  • Basic commands
2

Daily workflow (2-3 hours)

  • Cloning, pulling, pushing
  • Creating branches
  • Making commits
  • Merging changes
3

Team workflow (1-2 hours)

  • Pull requests
  • Code review
  • Resolving conflicts
  • Team conventions
4

Advanced topics (optional)

  • Rebasing
  • Cherry-picking
  • Stashing
  • History rewriting

Hands-on Exercises

Provide practical exercises:
# Exercise 1: Basic workflow
# Clone, branch, commit, push, pull request

# Exercise 2: Resolving conflicts
# Create conflicting changes, merge, resolve

# Exercise 3: Fixing mistakes
# Amend commits, reset, revert

# Exercise 4: Working with history
# View logs, diff between branches, blame

Migration Checklist

Pre-Migration

  • Assess current VCS usage and repositories
  • Choose Git hosting solution
  • Plan migration strategy and timeline
  • Set up Git infrastructure
  • Prepare training materials
  • Test migration process on pilot project
  • Document new workflows and conventions
  • Update CI/CD configurations

During Migration

  • Conduct training sessions
  • Import repository history
  • Verify imported data
  • Set up remote repository
  • Update developer workstations
  • Migrate build and deployment scripts
  • Update documentation and wiki
  • Provide hands-on support

Post-Migration

  • Archive old VCS repositories
  • Monitor and address issues
  • Collect feedback from team
  • Refine workflows based on experience
  • Document lessons learned
  • Provide ongoing training and support
  • Decommission old VCS infrastructure

Common Migration Challenges

Large Binary Files

Problem: Git doesn’t handle large binary files efficiently. Solution: Use Git LFS (Large File Storage)
# Install Git LFS
git lfs install

# Track large files
git lfs track "*.psd"
git lfs track "*.mp4"
git lfs track "*.zip"

# Migrate existing files
git lfs migrate import --include="*.psd,*.mp4"

Huge Repository History

Problem: Importing decades of history takes too long. Solutions:
# Option 1: Shallow import
git svn clone -s -r 1000:HEAD https://svn.example.com/project

# Option 2: Split by date
# Archive old history separately
# Import recent history into Git

# Option 3: Use shallow clones for developers
git clone --depth 100 https://github.com/org/project.git

Complex Branch Structures

Problem: SVN branch structure doesn’t map cleanly to Git. Solution: Simplify during migration
# Map to standard Git structure
trunk    -> main
branches -> feature branches
tags     -> Git tags

# Archive inactive branches
# Consolidate redundant branches

Team Resistance

Problem: Team members resist change. Solutions:
  • Start with pilot projects
  • Provide extensive training
  • Have Git champions on each team
  • Allow time for learning curve
  • Demonstrate benefits (speed, offline work, better branching)

Maintaining Both Systems

During transition, you might need to maintain both:

Bidirectional Sync

# Set up git-svn
git svn clone -s https://svn.example.com/project

# Work in Git
git commit -am "Changes"

# Push to Git remote
git push origin main

# Sync back to SVN
git svn rebase
git svn dcommit

Migration Period Best Practices

  • Designate one system as source of truth
  • Minimize changes to old system
  • Set a firm cutover date
  • Communicate clearly which system to use
  • Provide clear migration status updates

Post-Migration Optimization

Repository Cleanup

# Remove unnecessary files
git filter-repo --path unwanted/ --invert-paths

# Clean up history
git reflog expire --expire=now --all
git gc --prune=now --aggressive

Establish Workflows

# Document your chosen workflow
# - Feature branch workflow
# - Gitflow
# - Forking workflow

# Set up branch protection
# - Require reviews
# - Require status checks
# - Prevent force pushes to main

Optimize for Your Team

1

Review and refine

After a few weeks, gather feedback and adjust workflows.
2

Automate workflows

Set up hooks, CI/CD, and automated checks.
3

Document conventions

Create a CONTRIBUTING.md with your team’s Git conventions.
4

Continuous improvement

Regularly review and update practices based on team needs.
Successful migration is as much about people and process as it is about technology. Invest in training and allow time for adjustment.