简介:这是一款基于 TypeScript 开发的 VSCode 插件,面向希望美化 GitHub 贡献图、灵活管理提交记录的前端开发者与开源爱好者。它支持一键批量提交 commit,可自由指定过去几年乃至未来日期的提交,既能固定次数也能随机次数,并允许一次操作覆盖多个日期范围,通过控制每日提交量来调节绿色格子的深浅,配合完善日志清晰掌握运行状态。资源包共 49 个文件,以 ts 源码、json 配置、png 截图、js 脚本及 md 文档为主,另含 css 样式、gif 演示与 woff 字体等,压缩包约 7.32MB,目录涵盖 src 源码、assets 资源、test 测试与 .github 工作流等模块,结构完整便于二次开发。目前已有 381 人学习下载,读者可借此了解 VSCode 插件从命令注册、Webview 交互到提交调度的实现思路,并直接运行体验自动提交效果。
1. 一键刷 commit 记录:把 GitHub 首页绿色格子填满,到底是怎么做到的
有人把 GitHub 个人主页的贡献图当成“代码活跃度简历”,招聘方扫一眼,绿格子密不密,心里先打个分。于是就有了 autoCommit 这类工具:一条命令,把过去几年甚至未来日期的 commit 批量写进仓库,让贡献图从稀疏变密集。它解决的不是“代码写得多”,而是“贡献图看起来连续”。适合谁?适合需要展示持续提交节奏的开发者、想测试贡献图渲染效果的人、以及在做 CI/CD 演示时需要构造历史数据的场景。但先说清楚:这东西本质是往 Git 仓库里写带指定作者和日期的空提交或文件变更,GitHub 只认 commit 的 author date 和 committer date,不校验你那天是不是真写了业务代码。所以它能“填满格子”,但填进去的是提交记录,不是代码价值。下面从原理到落地,把这条路走通。
2. 贡献图的计算规则与 autoCommit 的写入逻辑
2.1 GitHub 贡献图到底看什么字段
GitHub 贡献图(Contribution Graph)的判定条件并不复杂,但有几个硬性门槛。第一,commit 必须落在默认分支或 gh-pages 分支上,其他分支的提交不计入。第二,commit 的 author email 必须和 GitHub 账号绑定的邮箱一致,否则算不到你头上。第三,commit 的 author date 决定它落在哪一天格子里,而不是 push 时间。第四,仓库不能是 fork 来的,fork 仓库的提交默认不显示在贡献图里。第五,提交必须是通过 GitHub 上的仓库产生的,本地仓库没 push 上去不算。
这五条里,最容易被忽略的是 author email 和 fork 限制。很多人本地git config user.email设了一个随便的邮箱,提交上去发现格子没绿,回头查半天。另一个坑是直接 fork 别人的仓库来刷,结果贡献图纹丝不动,因为 GitHub 对 fork 仓库有过滤。
autoCommit 这类工具的核心操作就是:在目标仓库里,用你指定的邮箱和日期,批量生成 commit 并 push。它不修改 GitHub 的任何数据,只是模拟你“在那一天提交过”的 Git 记录。
2.2 空提交与文件变更提交的取舍
刷 commit 有两种写法:一种是git commit --allow-empty,生成没有文件变更的空提交;另一种是往一个文件里追加内容再提交。两者在贡献图上的效果完全一样,GitHub 只看 commit 对象,不看 diff 内容。
那为什么很多工具默认用文件变更而不是空提交?因为空提交在某些 CI 钩子或仓库保护规则下可能被拒绝,而带文件变更的提交更“像正常提交”。但空提交的好处是干净,不会把仓库搞得一团糟。我的建议是:如果只是刷贡献图,用空提交就够了;如果仓库有 pre-commit 钩子或分支保护规则禁止空提交,再改用追加文件的方式。
下面是一个用 Python 批量生成空提交并 push 的最小脚本,不依赖任何第三方库,直接调 git 命令:
import subprocess import os from datetime import datetime, timedelta # 配置区:按需修改 REPO_PATH = "/path/to/your/repo" # 本地仓库路径 AUTHOR_NAME = "Your Name" # 与 GitHub 账号一致 AUTHOR_EMAIL = "your@email.com" # 必须与 GitHub 绑定邮箱一致 START_DATE = "2023-01-01" # 起始日期 END_DATE = "2023-12-31" # 结束日期 COMMITS_PER_DAY = 3 # 每天提交次数 def run_git(args, env=None): """执行 git 命令,返回输出""" result = subprocess.run( ["git"] + args, cwd=REPO_PATH, capture_output=True, text=True, env=env ) if result.returncode != 0: print(f"git {' '.join(args)} failed: {result.stderr}") return result.stdout def make_commits(): start = datetime.strptime(START_DATE, "%Y-%m-%d") end = datetime.strptime(END_DATE, "%Y-%m-%d") current = start while current <= end: for i in range(COMMITS_PER_DAY): # 构造当天的时间戳,分散在不同小时 commit_time = current.replace(hour=9 + i * 3, minute=0, second=0) date_str = commit_time.strftime("%Y-%m-%dT%H:%M:%S") # 设置环境变量,覆盖 author 和 committer 日期 env = os.environ.copy() env["GIT_AUTHOR_DATE"] = date_str env["GIT_COMMITTER_DATE"] = date_str env["GIT_AUTHOR_NAME"] = AUTHOR_NAME env["GIT_AUTHOR_EMAIL"] = AUTHOR_EMAIL env["GIT_COMMITTER_NAME"] = AUTHOR_NAME env["GIT_COMMITTER_EMAIL"] = AUTHOR_EMAIL # 空提交 run_git(["commit", "--allow-empty", "-m", f"chore: daily commit {date_str}"], env=env) current += timedelta(days=1) # 一次性 push run_git(["push", "origin", "main"]) if __name__ == "__main__": make_commits()这段代码的逻辑很直白:遍历日期区间,每天生成若干次提交,通过环境变量GIT_AUTHOR_DATE和GIT_COMMITTER_DATE把提交时间固定到指定日期。--allow-empty保证不产生文件变更。最后统一 push。
参数说明:COMMITS_PER_DAY控制每天格子里的提交次数,GitHub 贡献图的颜色深浅按当天提交数分档,一般 1-3 次是浅绿,4-9 次是中绿,10 次以上是深绿。START_DATE和END_DATE决定刷的范围,可以跨年。AUTHOR_EMAIL必须和 GitHub 账号绑定邮箱完全一致,大小写敏感。
2.3 未来日期的 commit 能不能写
标题里提到“未来的 commit”,这听起来反直觉,但 Git 本身不禁止你把 author date 设成未来时间。你完全可以用GIT_AUTHOR_DATE="2026-01-01T12:00:00"提交,push 上去之后,GitHub 会把这个 commit 归到 2026 年 1 月 1 日的格子里。但注意:未来的格子只有在日期真正到来之后才会显示在贡献图上,GitHub 不会提前把未来的格子画出来。所以“刷未来的 commit”实际效果是:等那天到了,格子自动变绿,你不需要再操作。
这个特性适合做“预填充”,比如你预计接下来几个月没时间提交,想提前把贡献图排满。但风险是:如果 GitHub 后续调整贡献图规则,或者你的邮箱绑定变了,这些未来提交可能不算数。我的做法是未来日期最多刷三个月,再远就不碰了。
3. 从零跑通 autoCommit 的完整操作路径
3.1 环境准备与仓库初始化
先确认本地有 Git,并且能正常 push 到 GitHub。如果你还没有仓库,新建一个空仓库,不要勾选 README 初始化,否则本地 push 会冲突。新建之后,在本地初始化并关联远程:
# 新建目录并初始化 mkdir commit-filler && cd commit-filler git init git branch -M main # 关联远程仓库,替换成你的实际地址 git remote add origin git@github.com:yourname/commit-filler.git # 先做一次正常提交,确保 push 通路没问题 echo "# commit filler" > README.md git add README.md git commit -m "init" git push -u origin main这一步的关键是确认 SSH key 或 token 配置正确。如果 push 报权限错误,先解决认证问题,再继续后面的批量提交。很多人卡在这里,以为是脚本问题,其实是远程认证没配好。
3.2 用脚本批量生成指定日期区间的提交
上面第 2 章给的 Python 脚本可以直接用,但有几个实操细节要补。第一,脚本里的REPO_PATH要指向你刚初始化的仓库目录。第二,如果仓库默认分支不是 main,把 push 命令里的分支名改掉。第三,批量提交会产生大量 commit 对象,如果一天刷 10 次、刷一年,就是 3650 个 commit,push 的时候可能比较慢,建议分批次 push,比如每三个月 push 一次。
如果你不想写 Python,也可以用纯 bash 循环:
#!/bin/bash # 批量空提交脚本,按天循环 REPO_PATH="/path/to/your/repo" cd "$REPO_PATH" || exit 1 START="2023-01-01" END="2023-03-31" EMAIL="your@email.com" NAME="Your Name" current="$START" while [ "$(date -d "$current" +%s)" -le "$(date -d "$END" +%s)" ]; do for i in 1 2 3; do export GIT_AUTHOR_DATE="${current}T0${i}:00:00" export GIT_COMMITTER_DATE="${current}T0${i}:00:00" export GIT_AUTHOR_NAME="$NAME" export GIT_AUTHOR_EMAIL="$EMAIL" export GIT_COMMITTER_NAME="$NAME" export GIT_COMMITTER_EMAIL="$EMAIL" git commit --allow-empty -m "chore: $current #$i" done current=$(date -d "$current + 1 day" +%Y-%m-%d) done git push origin mainbash 版本的好处是不依赖 Python 环境,在 macOS 和 Linux 上都能跑。注意date -d在 macOS 上行为不同,如果是 Mac,需要装 GNU coreutils 或者改用date -v语法。这个坑我踩过,脚本在 Ubuntu 上跑得好好的,换到 Mac 直接报错。
3.3 验证贡献图是否生效
push 完成后,打开 GitHub 个人主页,看贡献图有没有变化。如果没有变化,按以下顺序排查:
第一,检查 commit 的 author email 是否和 GitHub 账号绑定邮箱一致。在仓库目录执行git log --format="%ae" | head -5,看输出的邮箱对不对。第二,检查 commit 是否在默认分支上。git branch确认当前分支,git log --oneline看提交记录。第三,检查仓库是不是 fork 来的。如果是 fork,贡献图不会显示,需要新建一个非 fork 仓库。第四,检查 commit 的日期是否在贡献图显示范围内。GitHub 贡献图默认显示最近一年,如果你刷的是两年前的日期,需要点贡献图下方的年份切换才能看到。
验证的时候可以用git log --format="%ad %ae %s" --date=short快速查看所有提交的日期和邮箱,一眼就能看出哪条不对。
4. 避坑指南:刷 commit 时最容易翻车的五个地方
4.1 邮箱不匹配导致格子不绿
现象:脚本跑完,push 成功,但贡献图一点变化没有。原因:GIT_AUTHOR_EMAIL设了一个不是 GitHub 账号绑定的邮箱。GitHub 靠邮箱来关联 commit 和账号,邮箱不对,commit 就归不到你头上。解决:去 GitHub 设置里查绑定邮箱,确保脚本里的AUTHOR_EMAIL和它完全一致。如果有多个邮箱,选 primary 那个。
4.2 fork 仓库的提交不计入贡献图
现象:在 fork 来的仓库里刷了几百个 commit,贡献图纹丝不动。原因:GitHub 默认不把 fork 仓库的提交算进贡献图,这是为了防止有人靠 fork 刷格子。解决:新建一个非 fork 的空仓库,把远程地址换掉,重新刷。如果你确实想在 fork 仓库里保留提交,可以提 PR 合并到上游,但那样操作成本太高,不如直接建新仓库。
4.3 分支保护规则拒绝空提交
现象:git commit --allow-empty本地成功,但 push 被远程拒绝。原因:仓库开了分支保护,要求提交必须包含文件变更,或者要求通过 PR 合并。解决:改用追加文件的方式提交,往一个log.txt里追加时间戳,这样每次提交都有 diff。或者临时关闭分支保护,刷完再开。
4.4 时区导致日期偏移
现象:明明设的是 2023-06-15 提交,贡献图上却显示在 2023-06-14。原因:GIT_AUTHOR_DATE如果不带时区偏移,Git 会按本地时区解释,而 GitHub 按 UTC 显示。解决:在日期字符串里显式带上时区,比如2023-06-15T12:00:00+08:00,这样不管本地时区是什么,GitHub 都能正确归位。
4.5 刷太多导致仓库体积膨胀
现象:刷了几年 commit 之后,仓库.git目录变得很大,clone 变慢。原因:每个 commit 对象都会占用空间,几千个空提交虽然单个很小,累积起来也不容忽视。解决:控制刷的数量,没必要每天 10 次,每天 1-2 次就足够让格子变绿。如果已经刷多了,可以用git rebase压缩历史,但操作有风险,建议在新仓库里重新刷。
5. 进阶技巧:让贡献图看起来更自然
5.1 随机化提交时间和频率
每天固定 9 点、12 点、15 点提交,贡献图虽然绿了,但 commit 时间戳整齐得像机器生成的。想看起来更像真人,可以在脚本里加随机偏移:
import random from datetime import datetime, timedelta def random_commit_times(date, count): """在一天内随机生成 count 个提交时间""" times = [] for _ in range(count): hour = random.randint(8, 22) minute = random.randint(0, 59) second = random.randint(0, 59) times.append(date.replace(hour=hour, minute=minute, second=second)) return sorted(times)把这段逻辑嵌到前面的脚本里,替换固定的hour=9 + i * 3,每天提交次数也改成random.randint(1, 5),这样贡献图的颜色深浅会有自然波动,不会每天一模一样。
5.2 用 commit message 模拟真实开发节奏
空提交的 message 如果全是chore: daily commit,翻 commit 记录的人一眼就看出来是刷的。可以准备一组看起来像正常开发的 message,随机选取:
MESSAGES = [ "fix: 修复边界条件判断", "feat: 增加配置项解析", "refactor: 提取公共方法", "docs: 更新接口说明", "test: 补充单元测试用例", "style: 调整代码格式", "chore: 升级依赖版本", ] import random msg = random.choice(MESSAGES)这样 commit 记录看起来更像真实项目。但注意,message 只是表面功夫,如果仓库里没有任何实际代码,翻两页还是会露馅。所以这个技巧适合配合一个真实的小项目使用,而不是空仓库硬刷。
5.3 验证贡献图渲染的边界情况
如果你是在做贡献图相关的工具开发,需要测试不同提交密度下的渲染效果,可以用 autoCommit 的思路构造边界数据:某天 0 提交、某天 1 提交、某天 10 提交、某天 50 提交,然后观察 GitHub 贡献图的颜色分档。根据我的实测,GitHub 的颜色分档大致是:0 次灰色,1-3 次浅绿,4-6 次中绿,7-9 次深绿,10 次以上最深绿。但这不是官方文档写的,可能随版本调整,所以只作为参考。
另外,贡献图在移动端和桌面端的渲染略有差异,移动端格子更小,颜色分档看起来没那么明显。如果你要截图做展示,建议用桌面端浏览器。
5.4 一个我自己的习惯
我现在刷 commit 只刷最近三个月,而且每天最多 2 次,message 用真实的开发记录。刷完之后,我会把仓库设成 private,这样别人看不到 commit 内容,但贡献图仍然显示。等过一段时间,如果确实有真实提交,再把仓库转 public。这样既保持了贡献图的连续性,又不会让人翻到一堆空提交。说到底,贡献图只是门面,真正能撑住场面的还是仓库里有没有东西。希望帮到你。
本文还有配套的精品资源,点击获取