A bash script that mirrors your contributions from any Git repositories (private, work, personal, from any platform) to a public GitHub repository, making your coding activity visible on your GitHub profile.
Works with: GitHub, GitLab, Bitbucket, Azure DevOps, self-hosted Git, or any Git repository.
π This tool is 100% ethical and respects confidentiality
This script creates empty commits with only timestamps - it does NOT copy, share, or expose any actual code, business logic, or proprietary information from your work repositories.
What it does:
- β Creates timestamped markers showing when you made commits
- β Preserves commit dates to reflect your actual activity
- β Helps showcase your professional coding consistency
What it does NOT do:
- β Does NOT copy any source code
- β Does NOT expose project names or details
- β Does NOT share commit messages from original repositories
- β Does NOT violate any confidentiality agreements
Legal & Ethical:
- All commits are marked as generic "Activity"
- No proprietary information is disclosed
- Similar to listing work experience on LinkedIn
- Respects employer intellectual property rights
Before using: Always check your employment contract and company policies regarding public activity tracking.
Empty contribution graph - all your work is invisible
Full contribution graph showing your actual work activity
Many developers have contributions scattered across:
- π’ Private work repositories (company projects, client work)
- π Personal private projects (side projects, experiments)
- π Other platforms (GitLab, Bitbucket, Azure DevOps)
- πΌ Freelance projects (private client repos)
- π Self-hosted Git servers
All these contributions are invisible on your public GitHub profile. This script solves that problem by creating a mirror repository with timestamped commits that reflect your actual coding activity across all your repositories.
- π Works with any Git repository (GitHub, GitLab, Bitbucket, Azure DevOps, self-hosted)
- π Scans multiple local git repositories at once
- π Preserves original commit dates and times
- π€ Uses your personal identity (name and email) for commits
- π― Optional filtering by email address (work, personal, etc.)
- π Optional filtering by start date (only recent commits)
- π Generates detailed statistics and summary
- π Automatically pushes to GitHub
- β‘ Handles large commit histories efficiently
- π 100% safe - no code is copied, only timestamps
-
Copy the example environment file:
cp env.example .env
-
Edit .env with your information:
nano .env # or use your favorite editor -
First, diagnose your repositories to see what you have:
./diagnose-repos.sh # Will use PROJECTS_DIR and FILTER_EMAIL from .env -
Create a GitHub repository for your contributions (e.g.,
username/work-contributions) -
Run the import script (it will read from .env):
./import-contributions.sh
-
Wait 24 hours for contributions to appear on your GitHub profile
-
First, diagnose your repositories to see what you have:
./diagnose-repos.sh ~/work-projects your.work@company.com -
Create a GitHub repository for your contributions (e.g.,
username/work-contributions) -
Get a GitHub token (see instructions below)
-
Run the import script:
./import-contributions.sh username/work-contributions ghp_xxxxx "Your Name" your.personal@gmail.com ~/work-projects your.work@company.com
-
Wait 24 hours for contributions to appear on your GitHub profile
import-contributions.sh- Main script to import contributions to GitHubdiagnose-repos.sh- Diagnostic tool to analyze your repositories before importingenv.example- Example environment file template.gitignore- Prevents committing sensitive .env fileREADME.md- This documentation file
- Bash shell (Linux, macOS, or WSL on Windows)
- Git installed and configured
- A GitHub account with a verified email
- A GitHub Personal Access Token (with
repopermissions)
The easiest way to use both scripts is with a .env file. Here's how:
-
Copy the example file:
cp env.example .env
-
Edit the .env file:
nano .env # or vim, code, etc. -
Set your values:
# Required (for import-contributions.sh) GITHUB_REPO=username/work-contributions GITHUB_TOKEN=ghp_your_token_here AUTHOR_NAME=Your Name AUTHOR_EMAIL=your.personal@gmail.com # Optional (for both scripts) PROJECTS_DIR=~/work-projects FILTER_EMAIL=your.work@company.com SINCE_DATE=2024-01-01 # Only commits from this date onwards
-
Run any script:
./diagnose-repos.sh # Diagnose repositories ./import-contributions.sh # Import contributions
Security: The
.envfile is automatically ignored by git (see.gitignore), so your token won't be accidentally committed.
Note: Both
diagnose-repos.shandimport-contributions.shwill read from the.envfile automatically. Command line parameters will override.envvalues.
- Go to GitHub Settings β Developer settings β Personal access tokens β Tokens (classic)
- Click "Generate new token (classic)"
- Give it a descriptive name (e.g., "Import Contributions")
- Select the
reposcope (full control of private repositories) - Click "Generate token"
- Copy the token immediately (you won't be able to see it again)
Before importing contributions, it's recommended to run the diagnostic script to see what commits and emails are in your repositories.
Using .env file (if already configured):
./diagnose-repos.shUsing command line:
./diagnose-repos.sh [projects-folder] [filter-email] [since-date]Using .env file:
# If you already have .env configured with PROJECTS_DIR, FILTER_EMAIL, and SINCE_DATE
./diagnose-repos.shCheck all repositories:
./diagnose-repos.sh ~/work-projectsCheck with email filter:
./diagnose-repos.sh ~/work-projects john.work@company.comCheck with email and date filter:
./diagnose-repos.sh ~/work-projects john.work@company.com 2024-01-01Note: The diagnostic script will also read from your
.envfile if it exists. Command line parameters override the.envvalues.
- π¦ List of all repositories with git history
- π§ All email addresses used in each repository
- π Number of commits per email (filtered by date if specified)
- β Which repositories contain commits from your filter email (if provided)
- π Commit counts respect the date filter if provided
This helps you:
- Verify which repositories have your work commits
- Identify the correct email to use for filtering
- See how many commits you have in a specific time period
- Estimate how many commits will be imported
Repository diagnostics in: /Users/john/work-projects
Filter Email: Only showing commits from john.work@company.com
Since Date: Only showing commits from 2024-01-01 onwards
π¦ project-alpha
Total commits: 87
Emails:
β’ john.work@company.com (87 commits)
β Has commits from john.work@company.com: 87
π¦ project-beta
Total commits: 52
Emails:
β’ john.work@company.com (42 commits)
β’ other.dev@company.com (10 commits)
β Has commits from john.work@company.com: 42
=========================================
Summary:
Total repositories: 2
With commits: 2
With commits from john.work@company.com: 2
=========================================
This is the easiest way! Just set your configuration once and run the script:
Setup:
cp env.example .env
nano .env # Edit with your valuesRun:
./import-contributions.shThe script will automatically read all configuration from the .env file.
If you prefer to pass parameters directly:
Basic Usage (Current Directory):
./import-contributions.sh <github-repo> <github-token> <your-name> <your-email>With Custom Projects Folder:
./import-contributions.sh <github-repo> <github-token> <your-name> <your-email> <projects-folder>With Email Filter:
./import-contributions.sh <github-repo> <github-token> <your-name> <your-email> <projects-folder> <filter-email>With Date Filter (only commits since specific date):
./import-contributions.sh <github-repo> <github-token> <your-name> <your-email> <projects-folder> <filter-email> <since-date>Note: Command line arguments will override values from the .env file if both are present.
| Parameter | Required | Description |
|---|---|---|
<github-repo> |
β Yes | GitHub repository in format username/repo-name |
<github-token> |
β Yes | Your GitHub Personal Access Token |
<your-name> |
β Yes | Your personal name for commit authorship |
<your-email> |
β Yes | Your personal email (must be verified on GitHub) |
<projects-folder> |
β No | Path to projects folder (default: current directory) |
<filter-email> |
β No | Filter commits by this email in source repos |
<since-date> |
β No | Only import commits from this date onwards (YYYY-MM-DD) |
# 1. Setup your .env file once
cp env.example .env
nano .env # Add your values
# 2. Run the script (as many times as you want)
./import-contributions.shcd ~/work-projects
./import-contributions.sh johndoe/work-contributions ghp_xxxxx "John Doe" john.personal@gmail.com./import-contributions.sh johndoe/work-contributions ghp_xxxxx "John Doe" john.personal@gmail.com ~/work-projects./import-contributions.sh johndoe/work-contributions ghp_xxxxx "John Doe" john.personal@gmail.com ~/work-projects john.work@company.com./import-contributions.sh johndoe/work-contributions ghp_xxxxx "John Doe" john.personal@gmail.com ~/work-projects john.work@company.com 2024-01-01# In your .env file:
# SINCE_DATE=2024-01-01
# FILTER_EMAIL=john.work@company.com
./import-contributions.sh # Will only import commits from 2024 onwards- Scans all git repositories in the specified folder (or current directory if not specified)
- Extracts commit history (optionally filtered by email and/or date)
- Creates a new temporary git repository
- Generates mirror commits with original timestamps
- Pushes everything to your GitHub repository
- Updates your GitHub contribution graph
β οΈ Never commit your GitHub token to version control- π The
.envfile is automatically ignored by git (included in.gitignore) - π The script only creates empty commits with timestamps - no actual code is copied
- π All commits are marked as "Activity" - no sensitive information is exposed
- ποΈ Temporary files are automatically cleaned up
- β
Use
env.exampleas a template, never commit your actual.envfile
The script creates a GitHub repository with:
- A README.md with statistics (total commits, repositories, date range)
- Empty commits with timestamps matching your original work
- No actual source code (only activity markers)
Example commit message: π [project-name] Activity
[INFO] Detected configuration:
[INFO] Name: John Doe
[INFO] Email: john.personal@gmail.com
[INFO] Folder: /Users/john/work-projects
[WARN] β οΈ Make sure john.personal@gmail.com is verified on GitHub!
[INFO] Searching for repositories in /Users/john/work-projects...
[REPO] Processing: project-alpha
[INFO] β 150 commits found
[REPO] Processing: project-beta
[INFO] β 89 commits found
[INFO] =========================================
[INFO] Summary:
[INFO] Repositories found: 2
[INFO] Total commits: 239
[INFO] =========================================
[INFO] Creating mirror repository...
[INFO] Creating mirror commits (this may take a moment)...
[INFO] Progress: 100/239 (41%)
[INFO] Progress: 200/239 (83%)
[INFO] β
Created 239 mirror commits
[INFO] Uploading to GitHub...
[INFO] =========================================
[INFO] β
Process completed successfully!
[INFO] =========================================
[INFO]
[INFO] π Final summary:
[INFO] β’ Repositories processed: 2
[INFO] β’ Total commits: 239
[INFO] β’ GitHub repository: https://github.com/johndoe/work-contributions
[INFO]
[WARN] β° Contributions may take up to 24 hours to appear
- Wait time: GitHub contribution graphs update within 24 hours
- Email verification: Your personal email MUST be verified on GitHub
- Existing repos: The script uses
--forcepush, so it will overwrite the target repository - Local repos: Source repositories must be valid git repositories with commit history
- Date format: Use YYYY-MM-DD format for the since date (e.g., 2024-01-01, 2023-06-15)
The SINCE_DATE parameter is useful when you:
- Want only recent activity: Import only commits from the last year or specific period
- Have a large history: Avoid importing thousands of old commits
- Started a new job: Only show contributions from your current position
- Performance: Faster execution with fewer commits to process
Example use cases:
# Only import commits from 2024
SINCE_DATE=2024-01-01
# Only import commits from the last 6 months
SINCE_DATE=2024-06-01
# Only import commits from when you started your current job
SINCE_DATE=2023-09-15- Verify your email is added and verified on GitHub
- Check if the repository is public (contributions from private repos may not show)
- Wait up to 24 hours for the graph to update
- Ensure the commits are authored with your verified email
Make sure the path to your projects folder is correct. You can:
- Omit the path to use the current directory
- Use relative paths:
~/work-projectsor./projects - Use absolute paths:
/Users/john/work-projects
- Check your GitHub token has
repopermissions - Verify the repository format is correct:
username/repo-name - Make sure the repository exists on GitHub (create it first if needed)
- Check if the repositories have git history:
git log - If using email filter, verify the email matches exactly
- The script will show available emails in the repository if filter doesn't match
MIT License - Feel free to use and modify as needed.
Contributions, issues, and feature requests are welcome!
This tool is designed for legitimate use to showcase your professional work. Always ensure you:
- Have the right to reference your work publicly (check your employment contract)
- Don't expose any confidential information
- Use appropriate repository names and descriptions
Made with β€οΈ to help developers showcase their work