Node.js Git Server
node-git-server is a highly configurable Git server implemented in Node.js, designed for embedding or standalone deployment within a Node.js environment. The project adheres to a 'zero dependency footprint' philosophy, aiming to keep its core lean and efficient. Its current stable version is 1.0.0, released recently after an extensive beta phase. Key differentiators include its programmatic control over Git operations, extensive configurability for authentication and authorization, and its origin as a hard fork of the well-established `pushover` library. The library migrated to TypeScript starting with version 1.0.0-beta.1, enhancing type safety and developer experience. It now requires Node.js version 16 or newer, aligning with modern Node.js LTS releases. The project shows an active development and release cadence, having frequently updated through its beta cycle to reach a stable 1.0.0 release.
Common errors
-
Error: This version of Node.js is not supported.
cause Attempting to run `node-git-server` version 1.0.0 or higher on Node.js versions older than 16.fixUpgrade your Node.js runtime to version 16 or newer. For example, using nvm: `nvm install 16 && nvm use 16`. -
ERR_REQUIRE_ESM
cause Attempting to `require()` an ESM-only package in a CommonJS context without proper configuration.fixSwitch to ESM imports: `import { GitServer } from 'node-git-server';` and ensure your `package.json` has `"type": "module"` or files end with `.mjs`. -
TypeError: callback is not a function
cause Incorrect signature provided to the `authenticate` or `authorize` functions, leading to `callback` being undefined or not a function.fixVerify that your `authenticate` and `authorize` function callbacks match the expected `(error, success)` signature and that all arguments are correctly passed as per the documentation (e.g., `(type, repository, username, password, callback)`).
Warnings
- breaking Version 1.0.0 and subsequent versions no longer support Node.js environments older than Node.js 16. Running on unsupported versions will lead to errors.
- breaking The `authenticate` function signature changed in version 0.6.0. It now accepts an object as the first argument, followed by a callback, allowing for more flexible introspection (e.g., on headers).
- gotcha The library migrated to TypeScript in version 1.0.0-beta.1. While this improves type safety, it implies that the package is primarily consumed as an ESM module. Older CommonJS `require()` statements might encounter issues if not correctly configured or if the package no longer provides a CJS entry point.
Install
-
npm install node-git-server -
yarn add node-git-server -
pnpm add node-git-server
Imports
- GitServer
const GitServer = require('node-git-server');import { GitServer } from 'node-git-server'; - GitServerOptions
import type { GitServerOptions } from 'node-git-server'; - PushEvent
import type { PushEvent } from 'node-git-server';
Quickstart
import { GitServer } from 'node-git-server';
import path from 'path';
import fs from 'fs';
const REPOS_DIR = path.resolve(process.env.GIT_REPOS_DIR ?? './tmp/repos');
// Ensure the repository directory exists
if (!fs.existsSync(REPOS_DIR)) {
fs.mkdirSync(REPOS_DIR, { recursive: true });
}
const git = new GitServer(REPOS_DIR, {
autoCreate: true, // Automatically create repositories on first push
authenticate: (type, repository, username, password, callback) => {
console.log(`Authentication attempt: ${type} for ${repository} by ${username}`);
// In a real application, validate username and password against a database
if (username === 'gituser' && password === 'gitpass') {
console.log('Authentication successful.');
return callback(null, true); // Authentication successful
}
console.log('Authentication failed.');
return callback(new Error('Authentication failed'), false); // Authentication failed
},
authorize: (type, repository, username, callback) => {
console.log(`Authorization attempt: ${type} for ${repository} by ${username}`);
// In a real application, check permissions based on user and repository
if (username === 'gituser') {
console.log('Authorization successful.');
return callback(null, true); // Authorization successful
}
console.log('Authorization failed.');
return callback(new Error('Authorization failed'), false); // Authorization failed
},
});
git.on('push', (push) => {
console.log(`Push event: ${push.repo}/${push.commit} by ${push.branch}`);
push.accept(); // Accept the push
});
git.on('fetch', (fetch) => {
console.log(`Fetch event: ${fetch.repo} by ${fetch.branch}`);
fetch.accept(); // Accept the fetch
});
const PORT = parseInt(process.env.GIT_SERVER_PORT ?? '7000', 10);
git.listen(PORT, () => {
console.log(`node-git-server running on port ${PORT}`);
console.log(`Serving repositories from: ${REPOS_DIR}`);
console.log(`Try cloning: git clone http://localhost:${PORT}/my-repo.git`);
});
// Handle process exit to close server gracefully
process.on('SIGINT', () => {
console.log('Shutting down git server...');
git.close(() => {
console.log('Git server closed.');
process.exit(0);
});
});