An educational tool to visualize and understand Git internals
Gitoscope provides an interactive web interface for exploring how Git manages files, commits, trees, and blobs. Perfect for learning Git's internal object model and understanding the relationship between the working copy, staging area, and HEAD commit.
- Features
- Quick Start with Docker
- Using Gitoscope
- Docker Configuration
- Local Development Setup
- Available Scripts
- Troubleshooting
- Documentation
- Contributing
- Working Copy Visualization: See your current file system state in real-time
- Staging Area View: Understand what's staged for the next commit
- HEAD Commit Details: Explore the current commit contents
- Git Internals Graph: Visual representation of commits, trees, and blobs
- Real-time Updates: Changes to the repository immediately visible in the UI
- Interactive Exploration: Click through Git objects to understand relationships
- Educational Focus: Designed specifically for learning Git internals
The easiest way to run Gitoscope is using Docker. No Node.js installation required!
Perfect for exploring Git internals without affecting your own repositories.
docker run --name gitoscope -p 8080:3000 depsir/gitoscopeThen open your browser at: http://localhost:8080
The container includes an empty Git repository at /repo inside the container. You can manipulate this repository to see how Gitoscope visualizes changes.
Enter the container to manipulate the repository:
# Open a shell inside the container
docker exec -it gitoscope /bin/sh
# Navigate to the repository
cd /repo
# Make some changes
echo "Hello Git!" > hello.txt
git add hello.txt
git commit -m "Add hello.txt"
# Refresh the browser to see the changesExit the container shell: Type exit or press Ctrl+D
Mount your local Git repository to visualize it with Gitoscope.
docker run --name gitoscope -p 8080:3000 -v /absolute/path/to/your/repo:/repo depsir/gitoscopeExample (Linux/Mac):
docker run --name gitoscope -p 8080:3000 -v /home/user/projects/my-repo:/repo depsir/gitoscopeExample (Windows with WSL):
docker run --name gitoscope -p 8080:3000 -v /c/Users/YourName/projects/my-repo:/repo depsir/gitoscopeIf you're already inside a Git repository:
Linux/Mac:
docker run --name gitoscope -p 8080:3000 -v "$(pwd)":/repo depsir/gitoscopeWindows PowerShell:
docker run --name gitoscope -p 8080:3000 -v ${PWD}:/repo depsir/gitoscopeWindows CMD:
docker run --name gitoscope -p 8080:3000 -v %cd%:/repo depsir/gitoscopeThen open your browser at: http://localhost:8080
# Stop the container
docker stop gitoscope
# Start it again
docker start gitoscope
# Remove the container (when you're done)
docker rm -f gitoscopeIf you've cloned the repository and want to build locally:
# Clone the repository
git clone https://github.com/intresrl/gitoscope.git
cd gitoscope
# Build the Docker image
docker build -t my-gitoscope .
# Run your custom image
docker run --name gitoscope -p 8080:3000 -v "$(pwd)":/repo my-gitoscopeGitoscope provides two main views to help you understand Git internals.
URL: http://localhost:8080 (or http://localhost:8080/ or http://localhost:8080/index)
This is the primary view showing the three areas of Git:
Shows all files currently in your working directory.
- Green files: Tracked and committed
- Modified files: Changed since last commit
- Untracked files: New files not yet added to Git
Shows files staged for the next commit (via git add).
- Files here will be included in your next commit
- Also called the "Index" or "Cache" in Git terminology
Shows files as they exist in the current HEAD commit.
- This is the last committed state
- Click on files to see their content
- View file status: See which files are modified, staged, or committed
- Click on files: View file contents from any of the three areas
- Compare states: Understand the difference between working copy, staging, and HEAD
- Make changes:
- Modify files in your repository
- Run
git addto stage files - Run
git committo commit changes - Refresh the browser to see updates
Example Workflow:
# If using Docker with internal repo
docker exec -it gitoscope /bin/sh
cd /repo
# Create a new file
echo "console.log('Hello');" > app.js
# Refresh browser - you'll see app.js in Working Copy only
# Stage the file
git add app.js
# Refresh browser - you'll see app.js in Working Copy AND Staging Area
# Commit the file
git commit -m "Add app.js"
# Refresh browser - you'll see app.js in all three columnsURL: http://localhost:8080/internals
This view shows Git's internal object database as an interactive graph.
- Commits (yellow nodes): Commit objects with messages and metadata
- Trees (green nodes): Directory structures
- Blobs (blue nodes): File contents
- References (labels): Branches, tags, and HEAD pointer
- Nodes: Each node represents a Git object
- Click on a node to see its details
- Hover to see object ID
- Edges: Lines connecting objects show relationships
- Commit → Tree: The commit's root directory
- Commit → Parent Commit: Commit history
- Tree → Blob: Files in the tree
- Tree → Tree: Subdirectories
- Select a reference: Choose HEAD, a branch, or a tag from the dropdown
- Explore the graph:
- Click on commit nodes to see commit details
- Click on tree nodes to see directory contents
- Click on blob nodes to see file contents
- Understand relationships: Follow edges to see how Git links objects
- Navigate history: Click through parent commits to traverse history
Understanding the Graph:
HEAD → [Commit A] → [Tree] → [Blob: file.txt]
↓
[Commit B] (parent)
↓
[Commit C] (grandparent)
This shows:
- Current HEAD points to Commit A
- Commit A has a tree (root directory)
- Tree contains a blob (file)
- Commit A's parent is Commit B
- Commit history goes back to Commit C
By default, Gitoscope runs on port 3000 inside the container. Map it to any port on your host:
# Map to host port 8080 (recommended)
docker run -p 8080:3000 ...
# Map to host port 3000
docker run -p 3000:3000 ...
# Map to host port 9000
docker run -p 9000:3000 ...Then access at http://localhost:<YOUR_PORT>
The repository must be mounted at /repo inside the container:
docker run -v <HOST_PATH>:/repo ...Important Notes:
- The path must point to a Git repository (contains
.gitdirectory) - The repository must be initialized (
git initalready run) - Read/write permissions are required for the container to access files
Run the container in the background:
docker run -d --name gitoscope -p 8080:3000 -v "$(pwd)":/repo depsir/gitoscopeThe -d flag runs the container in detached mode.
View logs:
docker logs gitoscope
# Follow logs in real-time
docker logs -f gitoscopeSet custom environment variables:
# Use a different port inside the container
docker run -e PORT=8000 -p 8080:8000 ...
# Enable debug logging
docker run -e DEBUG=gitoscope:* ...For learning (internal repo):
docker run -d \
--name gitoscope \
-p 8080:3000 \
--restart unless-stopped \
depsir/gitoscopeFor visualizing your own repo:
docker run -d \
--name gitoscope \
-p 8080:3000 \
-v "$(pwd)":/repo \
--restart unless-stopped \
depsir/gitoscopeWith custom port and debug logging:
docker run -d \
--name gitoscope \
-p 9000:3000 \
-v "$(pwd)":/repo \
-e DEBUG=gitoscope:* \
depsir/gitoscopeFor contributing to Gitoscope or running without Docker:
- Node.js: >= 22.0.0
- npm: >= 10.0.0
- Git: Any recent version
-
Clone the repository
git clone https://github.com/intresrl/gitoscope.git cd gitoscope -
Install dependencies
npm install
-
Configure repository path
cp config.js.template config.js
Edit
config.jsand set therepopath:module.exports = { repo: '/absolute/path/to/your/git/repository', };
Important: Use an absolute path, not a relative path.
-
Start the application
npm start
-
Open your browser
Navigate to http://localhost:3000
Run with auto-reload on file changes:
npm run watchRun with debugging and auto-reload:
npm run watchdDebug mode (with Node.js inspector):
npm run debugThen open Chrome DevTools at chrome://inspect
npm start- Start the production server on port 3000
npm run watch- Auto-reload on file changes (using nodemon)npm run watchd- Auto-reload with debugging enablednpm run debug- Debug mode with Node.js inspector
npm test- Run all tests with Jestnpm run test:watch- Run tests in watch mode (re-run on changes)npm run test:coverage- Generate code coverage report
npm run lint- Check code quality with ESLintnpm run lint:fix- Auto-fix ESLint issuesnpm run format- Format code with Prettiernpm run format:check- Check code formatting without modifying files
Error: The container name "/gitoscope" is already in use
Solution:
# Remove the existing container
docker rm -f gitoscope
# Then run your docker run command againError: fatal: not a git repository or empty visualization
Solution:
- Ensure the mounted directory is a Git repository (contains
.git) - Check the volume mount path is correct
- Verify the repository is initialized:
git init
Check what's mounted:
docker exec -it gitoscope ls -la /repoError: bind: address already in use
Solution:
- Use a different host port:
-p 9000:3000 - Or stop the process using port 8080
Find what's using the port (Linux/Mac):
lsof -i :8080Causes:
- Repository has no commits yet
- config.js points to wrong directory
Solutions:
# Make an initial commit if repository is empty
cd /path/to/repo
git add .
git commit -m "Initial commit"
# Verify config.js has correct path
cat config.jsSolution: Refresh your browser (F5 or Ctrl+R)
Gitoscope doesn't auto-refresh - you need to manually refresh the page after making Git operations.
Solution: Make sure you're accessing the correct URL:
- Main view: http://localhost:8080/
- Internals: http://localhost:8080/internals
If you encounter issues:
-
Check the application logs:
# Docker docker logs gitoscope # Local # Logs appear in terminal
-
Check the GitHub Issues
-
Open a new issue with:
- Your environment (Docker version, Node.js version, OS)
- Steps to reproduce
- Expected vs actual behavior
- Logs or error messages
- ARCHITECTURE.md - System architecture, design decisions, and implementation details
- API.md - Complete REST API reference with examples
- CLAUDE.md - Development context for AI assistants
gitoscope/
├── __tests__/ # Test suites (Jest)
│ ├── integration/ # API integration tests
│ └── unit/ # Unit tests
├── bin/ # Server bootstrap
│ └── www # Entry point
├── controllers/ # Request handlers
│ └── apiController.js # API route controllers
├── lib/ # Core Git operations
│ ├── git.js # Git operations using simple-git
│ └── gitModels.js # Data models/factories
├── public/ # Frontend assets
│ ├── javascripts/ # React components & visualization
│ └── stylesheets/ # CSS files
├── routes/ # Express routes
│ ├── api.js # API endpoints
│ └── index.js # View routes
├── views/ # Pug templates
│ ├── index.pug # Main view
│ └── internals.pug # Internals view
├── app.js # Express app configuration
├── config.js.template # Configuration template
├── Dockerfile # Multi-stage Docker build
└── package.json # Dependencies and scripts
We welcome contributions! Here's how to get started:
-
Fork the repository on GitHub
-
Clone your fork
git clone https://github.com/YOUR_USERNAME/gitoscope.git cd gitoscope -
Create a feature branch
git checkout -b feature/amazing-feature
-
Make your changes
- Write clean, documented code
- Follow existing code style
- Add tests for new features
-
Run quality checks
npm run lint # Check code quality npm run format # Format code npm test # Run tests
-
Commit your changes
Use Conventional Commits:
git commit -m "feat: add amazing new feature" git commit -m "fix: resolve issue with status display" git commit -m "docs: update README with examples"
-
Push to your fork
git push origin feature/amazing-feature
-
Open a Pull Request on GitHub
This project uses:
- ESLint for linting (eslint:recommended + Prettier)
- Prettier for code formatting
- Jest for testing
- Conventional Commits for commit messages
Before submitting a PR, ensure:
npm run lint # No linting errors
npm run format # Code is formatted
npm test # All tests passRun the test suite:
npm test # Run all tests
npm run test:watch # Watch mode
npm run test:coverage # With coverage reportTest with Docker:
docker build -t gitoscope-test .
docker run -p 8080:3000 gitoscope-test- Node.js 22+ - JavaScript runtime
- Express.js 4.x - Web framework
- simple-git 3.x - Git operations (wraps native git commands)
- Pug 3.x - Template engine
- React - UI components (loaded via CDN)
- Cytoscape.js - Graph visualization for internals view
- Vanilla CSS - Styling
- Jest - Testing framework
- ESLint - Code linting
- Prettier - Code formatting
- Nodemon - Development auto-reload
MIT License - see LICENSE file for details
Francesco Sacchi - sacchi@intre.it
- Andrea Caglio - caglio@intre.it
- Gianni Bombelli (bombo82) - bombo82@giannibombelli.it
# Start with an empty repository
docker run --name gitoscope -p 8080:3000 depsir/gitoscope
# Open browser at http://localhost:8080
# Make changes and see how Git tracks them
docker exec -it gitoscope /bin/sh
cd /repo
# ... make git operations ...
# Refresh browser to see changesUse Gitoscope during lectures to show:
- How files move from working copy → staging → commit
- How Git stores objects internally (commits, trees, blobs)
- The difference between branches and commits
- How merge commits create multiple parents
# Visualize your problematic repository
cd /path/to/problematic/repo
docker run --name gitoscope -p 8080:3000 -v "$(pwd)":/repo depsir/gitoscope
# Open http://localhost:8080/internals
# Explore the commit graph to understand the issueGitoscope helps you understand:
- Working Directory: Your file system
- Staging Area (Index): Files prepared for commit
- Repository (.git): Committed snapshots
- Commits: Snapshots with metadata (author, message, timestamp)
- Trees: Directory structures (like folders)
- Blobs: File contents (binary or text)
- References: Pointers to commits (branches, tags, HEAD)
- Every commit points to a tree (root directory)
- Trees contain blobs (files) and other trees (subdirectories)
- Commits point to parent commits (history)
- References point to commits (branches point to latest commit)
A: Yes! When using Docker with volume mounts, your repository stays on your local machine. Gitoscope only reads the repository; it doesn't send data anywhere.
A: No. Gitoscope only reads from the repository. It cannot modify files, create commits, or change branches.
A: Gitoscope is designed as an educational tool, not for production use. It lacks authentication, rate limiting, and other production features.
A: Gitoscope works in all modern browsers: Chrome, Firefox, Safari, Edge.
A: Gitoscope works best with small to medium repositories. Very large repositories (thousands of commits/files) may have performance issues.
# Pull the latest Docker image
docker pull depsir/gitoscope
# Or rebuild from source
git pull
docker build -t depsir/gitoscope .Made with ❤️ for Git learners everywhere
Gitoscope - Making Git internals visible and understandable