A CLI tool that mirrors your GitHub contribution history from a work or secondary account to your main account by creating backdated commits.
Useful when you want your primary GitHub profile to reflect contributions made on other accounts (e.g., work, freelance, or school).
- Fetches the contribution calendar from the source GitHub account
- Analyzes existing commits in your target repository
- Creates empty backdated commits to match the source contribution count
The tool is idempotent: you can run it multiple times safely. It only creates the commits needed to match the source, skipping dates that already have enough commits.
Commits look like this:
Contribution sync: 2024-01-15 (1/3)
Contribution sync: 2024-01-15 (2/3)
Contribution sync: 2024-01-15 (3/3)
Prerequisites:
- Bun runtime installed
- GitHub personal access token with
read:userscope (andreposcope if usingAUTO_PUSHorTARGET_REPO_URL)
git clone https://github.com/nandosobral03/git-copycat
cd git-copycat
bun install- Create a target repository on GitHub where the mirrored commits will live
- Clone it locally or initialize a new repo and add the remote
- Copy the example environment file and fill in your values:
cp .env.example .envEdit .env with your configuration:
| Variable | Required | Description |
|---|---|---|
GITHUB_TOKEN |
Yes | GitHub personal access token (needs read:user scope, and repo scope if using TARGET_REPO_URL) |
SOURCE_USERNAME |
Yes | GitHub username to copy contributions from (must have public contributions visible) |
TARGET_REPO_PATH |
* | Path to local target repository |
TARGET_REPO_URL |
* | HTTPS URL to clone target repo from (alternative to TARGET_REPO_PATH) |
GIT_USER_NAME |
No | Git user name for commits (required when using TARGET_REPO_URL) |
GIT_USER_EMAIL |
No | Git user email for commits (required when using TARGET_REPO_URL) |
FROM_DATE |
No | Start date (ISO format, default: 1 year ago) |
TO_DATE |
No | End date (ISO format, default: today) |
DRY_RUN |
No | Set to true to preview without creating commits |
AUTO_PUSH |
No | Set to true to automatically push commits |
CI |
No | Set to true to skip interactive confirmation (for CI/CD) |
* Either TARGET_REPO_PATH or TARGET_REPO_URL is required.
bun run startYou can run git-copycat automatically on a schedule using GitHub Actions.
- Create a target repository on GitHub where the mirrored commits will live. It must have at least one commit (can be just a README).
- Fork or clone this repository
- Add the following secrets to your repository (Settings > Secrets and variables > Actions):
| Secret | Description |
|---|---|
GH_PAT |
GitHub personal access token with read:user and repo scopes |
SOURCE_USERNAME |
GitHub username to copy contributions from |
TARGET_REPO_URL |
HTTPS URL of your target repository (e.g., https://github.com/user/repo.git) |
GIT_USER_NAME |
Your git commit author name |
GIT_USER_EMAIL |
Your git commit author email (see note below) |
- The workflow runs daily at 6:00 AM UTC. You can also trigger it manually from the Actions tab.
Edit .github/workflows/sync.yml to change the schedule or other settings.
For commits to show up on your GitHub contribution graph, all of these must be true:
- Email must match - Your git email (
git config user.emailorGIT_USER_EMAILin CI) must be linked to your GitHub account. Important: If your email is set to "Private" in GitHub email settings, commits using that email won't be linked to your profile. Use your GitHub noreply email instead:<your-user-id>+<username>@users.noreply.github.com(you can find this in your GitHub email settings). - Enable private contributions on your git contribution graph. (If your target repo is private, remember to enable "Private contributions" in your GitHub profile settings)
- Commits must be on the default branch - Usually
mainormaster. - Repo cannot be a fork - Commits in forks don't count unless merged upstream.
Run DRY_RUN=true first to preview what will be created.
If you need to remove the generated commits:
# Find the commit hash before the sync started
git log --oneline
# Reset to that commit (destructive - loses all commits after)
git reset --hard <commit-hash>
# Force push to update remote
git push --forceOr just delete the target repository entirely if it was created only for this purpose.
GitHub contribution graphs have always been trivial to fake. This tool doesn't change that. The graph works on an honor system; it's a rough signal, not a verified credential. This tool is intended for consolidating your own legitimate work across accounts, not for misrepresenting your activity. Use your own judgment
