用 Git 仓库构建个人技能账本:从数据模型到自动可视化

📅 发布时间:2026/9/9 11:02:24
用 Git 仓库构建个人技能账本:从数据模型到自动可视化
昨晚帮一个前同事改简历他写了八年 Java却在“专业技能”那一栏憋了十分钟最后填了一堆“熟悉 XXX、了解 XXX”自己都说不清里面哪些能直接上生产环境哪些只是看过几篇博客。这个场景我见过太多次。大多数人手里的技能清单就是简历那一栏跟着项目走、跟着面试官问什么走从来没有一份真正属于自己的、可以长期维护的“技能账本”。所以过去两年我做了一个叫 skills 的个人项目本质上是把“我会什么”变成一套可以版本管理、可以自动生成可视化图表、可以定期复盘迭代的数据库。它解决三个问题第一面试或晋升答辩时说不清自己的能力边界第二学了新东西但过了两个月就忘了当时掌握到什么程度第三对“今年到底成长了多少”没有可量化的感知。我把整套方案走通之后发现这件事对工作三年以上、需要做技术规划或者开始带人的开发者尤其有用。不过思路不限于程序员运营、设计、销售所有需要盘点个人能力的岗位都可以用同一套模型只是技能名和分类维度不同。后面我会用开发者的例子讲但你可以把“Python”换成“用户访谈”把“Docker”换成“广告投放”逻辑完全一样。这篇文章就围绕 skills 这个项目展开从数据模型怎么定义到文件怎么组织再到雷达图怎么生成、自动化怎么跑最后是两年用下来踩的坑。1. 为什么“技能清单”不能只写在简历里提到技能盘点多数人第一反应是“我直接打开简历文档改一改不就行了”。简历是给别人看的它的目的是在有限篇幅内说服面试官所以写上去的都是挑过的、积极的、跟岗位匹配的。但作为一份帮你做决策的数据资产它严重不合格。简历技能栏有三个结构性缺陷。一是没有时间维度你不知道“熟练使用 Redis”是发生在三年前还是上个月实践时效完全丢失二是没有证据链“熟练”到底指单独扛过缓存方案还是跑过几节课的 demo简历里无从验证三是没有负空间你不会在简历里写“我三个月没碰前端了”但真实决策需要知道哪些技能正在生锈。skills 项目的第一性原理很简单把技能当成系统里的数据来管理而不是当作文案来润色。一旦你把它当成数据就会自然地想给它设计字段、定状态、写校验规则、做变更记录、画趋势图。这件事跟写代码没有本质区别而且做一次能持续受益很多年。1.1 从一次改简历说起回到开头那个前同事的例子。我让他把最近参与过的所有项目按时间列出来然后针对每个项目问一句话“这里面哪些技术点是你要查文档才能写出来的哪些是你不用查就能直接改的”再把两种技术分开。结果发现他简历里写的“熟悉微服务治理”实际能力水平大概是“能照着公司现成模板加一个新接口”而他不怎么会写进简历的“SQL 性能调优”反而是他真正常年在救火的能力。这件事很有代表性。人们普遍会高估日常使用频率低但名声大的技术同时低估那些已经内化成习惯的技术。原因也很好解释前者出现在各种岗位描述里看得多了会产生熟悉感错觉后者因为太熟练反而觉得“这不算什么技能”。一份真正可靠的技能数据必须用一种稳定的刻度去度量而不是靠记忆里的感觉。所以我从一开始就放弃了“把技能写成一段话”的形式转而规定每个技能条目必须包含技能名称、所属分类、当前等级、等级判断依据、最近一次实践时间、实践证据链接。后面几个字段才是让这套系统区别于普通清单的关键。1.2 技能账本应该是一棵会生长的树技能盘点不能做成一张平铺的表格那样一过五十条就乱得没法看。它本质上是一棵树根是“能力地图”往下分领域再往下是具体技能最底下一层是每项技能的证据和备注。做分类的时候想清楚层级后面做可视化、做复盘都会省很多力气。我用的顶层分类是这几个语言层、框架与运行时、数据与存储、基础设施与运维、工程实践、软技能。每个顶层分类下再挂具体的技能节点。比如“语言层”下面挂 Python、Go、JavaScript“数据与存储”下面挂 MySQL、Redis、Elasticsearch、Kafka。这个树不是静态的每年都会修剪——有的技能从“常用”变成“偶尔”有的技能从“了解”升到“精通”还有的新技术在项目里用了半年该挂上去了。树的根不需要频繁改动改的是枝叶。我个人体会是一年做一次大修剪每个季度做一次小更新数据就能保持相当好的新鲜度。不要高估自己的记忆力也不要高估自己的自律能力后面我会讲怎么用自动化脚本倒逼自己定期更新。2. 技能数据模型等级定义是整套系统的地基最早期我把技能等级做成“熟悉 / 了解 / 精通”三档用了不到一个月就发现完全没法用。这三个词的主观性太强今天心情好Redis 就是“精通”明天遇到一个没见过的报错它瞬间降级成“了解”。同一项技能在不同时间的评分波动很多时候不是技能本身变了而是度量尺子变了。后来我参考了能力素质模型里常用的行为锚定法把等级改成五档并且给每一档挂上可观察的行为示例。只有“会用”和“能手写原理”这种客观可验证的描述才能当刻度。2.1 五级能力标准的“可观察行为”锚点五档等级定义如下表所示这套定义我沿用至今只在表述上微调过几次等级名称可观察行为锚点典型示例0未接触不能独立完成任何相关任务基本靠搜索没写过 GraphQL只知道它和 REST 不一样1了解看过资料或教程能在指导下完成简单任务能照着官方文档搭一个 Express 服务2可用在真实项目中独立使用过能处理常规问题独立为项目接入 Redis 缓存并处理过期策略3熟练多个项目中稳定交付能讲清原理和取舍能说清 Kafka 分区与消费者组的关系并设计过生产级 Topic 方案4精通能优化方案、带人、沉淀最佳实践主导过全链路压测与性能调优并输出团队规范文档每个等级的描述必须满足一个条件别人可以通过观察你的工作产出来判断这个评分是否成立。这样一来给自己打分的时候就无法靠“感觉”必须找到对应的项目事实来支撑。如果找不到三个月内的行为证据那评分就应该往下调这是整套模型最核心的约束。2.2 分类维度与粒度控制分类维度的设计直接决定雷达图长什么样。维度太少图太粗糙维度太多雷达图会变成蜘蛛网没法读。我最终选择了六个维度每个维度下挂若干技能节点而且严格控制技能节点的粒度。粒度是这个项目里最容易翻车的地方。什么叫粒度不一致把“Python”和“正则表达式”并列把“Kubernetes”和“Docker 网络模型”并列都会让统计失去意义。我的解决方法是规定只有“领域级技能”才参与评分和可视化“子技能”只作为证据和备注存在。比如“Python”是领域级技能“Python 的 asyncio 协程模型”是子技能放在“Python”这个条目的备注里。数据模型设计成这样才能保证雷达图不会反映出一个畸形的能力结构。另外每个顶层分类最好只保留三到八个核心技能节点。超过八个说明这个领域被你拆得太碎可以合并同类项少于三个说明这个维度涵盖过宽应该继续拆分。这个原则让我在每次更新仓库时都有明确的取舍依据。2.3 记录“证据”而不是记录“感觉”这是整套数据模型里面我最有底气推荐的设计。每一笔技能评分都必须伴随至少一条“实践证据”字段包括时间、事件描述、产出物链接或仓库地址。证据的作用是锚定评分回看数据的时候你不会看到一个孤零零的数字而是能看到“2023 年 6 月在订单中心重构中负责异步任务调度模块”这种具体事实。证据的另一个作用是防止技能数量虚胖。很多人盘点技能时会潜意识地“秀肌肉”把用过一天的技术也标成掌握而一旦要求写出证据这个膨胀过程就会被迫停止。那些你写不出任何证据的条目要么降级要么直接删掉。到年底统计时这些证据还能直接变成晋升材料的第一手素材比临时回忆要准确得多。实际数据结构就是下面这个样子{ skill: Python, category: language, level: 3, evidence: [ { date: 2025-02-10, event: 将订单中心的消息消费链路从多线程改造为 asyncio 协程吞吐提升约 40%, link: https://github.com/yourname/order-center } ], updated: 2025-02-15 }从数据结构可以看出来这里没有“掌握程度打分理由”这种描述性字段所有的判断都交给level加evidence一起解读。你想把等级改成 4就必须再补一条拿得出手的证据这一步实际操作中比任何提醒都管用。3. 文件组织与存储选型为什么最终选了 Git 仓库数据模型定下来之后接下来就是选存储。你可能觉得这是小事但存储方式直接决定了这套系统能不能长期用下去。我前后对比过在线表格、Notion、本地 Excel、Git 仓库四种方案各有各的适用场景但最终只有 Git 仓库完全满足我的需求。在线表格是绝大多数人的首选优点是输入方便、支持多人协作、手机上也能改。但它的致命伤是几乎无法做数据校验——你想把等级限制在 0 到 4把日期格式统一成 ISO 格式在线表格的单元格没法天然约束另外一个问题是变更历史稀烂改坏了不好回滚也看不出评分什么时候改过。对于只想临时盘点一次的人来说完全够用但要长期维护就捉襟见肘。Notion 这一类知识库工具的体验介于表格和代码之间。关系数据库、看板视图、时间线功能确实强大自定义程度也很高。但我用下来的体会是它跟我的日常工作流是割裂的。我的代码、文档、CI 系统都在 Git 生态里为了维护技能库额外打开一个 Notion 页面慢慢地就会忘记更新。数据一旦停止更新这套系统就死了。3.1 在线文档、Notion 和 Git 仓库的取舍我最终选择的方案是Git 仓库作为唯一事实源用 Markdown 做人类可读的说明文档用 JSON 做机器可读的结构化数据再用脚本把 JSON 渲染成可视化页面。理由可以总结为三点。第一是版本化能力强。每一次技能变更都是一次 commit我可以精确到某一天把某项技能从 2 级升到 3 级回滚起来也毫无负担。第二是自动化方便。JSON 文件放在仓库里之后我可以在 CI 里加各种校验规则等级是否越界、日期的格式是否正确、是否有缺失字段。第三是低成本沉淀。Git 本身就是我日常工作的载体每次更新技能库只是多一次 commit 的事不需要切换工具习惯养成的心理障碍小很多。下面是仓库目录结构skills-repo/ ├── README.md ├── data/ │ ├── languages.json │ ├── frameworks.json │ ├──>import json import glob from jinja2 import Template skills [] for f in glob.glob(data/*.json): with open(f) as fp: data json.load(fp) for item in data: if item.get(status) active: skills.append(item) categories {} for s in skills: categories.setdefault(s[category], []).append(s) # 每个分类取平均等级作为雷达图的一个轴 radar_indicators [] radar_values [] for cat, items in categories.items(): avg_level round(sum(i[level] for i in items) / len(items), 2) radar_indicators.append({name: cat, max: 4}) radar_values.append(avg_level) template Template(open(templates/radar_template.html).read()) html template.render( radar_indicatorsjson.dumps(radar_indicators, ensure_asciiFalse), radar_valuesjson.dumps(radar_values) ) with open(output/index.html, w) as f: f.write(html)这段代码不复杂但有个细节值得说雷达图用的是分类平均等级而不是单个技能等级因为雷达图的轴如果对应单个技能三十多个技能就有三十多个轴图会变成一团乱麻。分类平均等级牺牲了一点精确性换来的是可读性。想看单个技能的详情鼠标悬停或点击分类名称再跳到对应的 JSON 段落就行。4.3 热力矩阵与技能变更追踪热力矩阵我用的是前端表格 CSS 色块方案没有额外引入图表库。每个技能条目一行等级值映射到背景色0 级是浅灰4 级是深蓝。这套方案加载快、写起来简单而且可以直接嵌入到同一个 HTML 页面里。除了静态视图我还在页面里加了一个“过去八次变更记录”时间线数据来自 Git log。每次有人把技能从 2 调整到 3都会生成一条记录时间线就是这些记录的可视化。年中复盘的时候我打开页面往下拉一下时间线就能快速回忆这半年在哪些方向投入了精力避免“自我感觉学了很多一问却想不起来”的尴尬。5. 自动化维护让技能雷达“自己长出来”再漂亮的数据模型只要停止更新就是废纸。很多技能盘点项目都是“三分钟热度”——建仓库、画图、发朋友圈然后下个月就忘了这回事。为了对抗这个问题我花了很大精力把维护流程自动化尤其是利用 GitHub Actions 做持续校验和提醒。早期我试过在手机日历里设置每两周提醒一次“更新技能库”效果非常差因为那个周末我通常根本不在电脑前提醒弹出来划掉就完了。后来我转变了思路与其靠“提醒人”不如靠“提醒数据”。数据本身过期时让系统主动报错人被迫去处理。5.1 数据过期提醒超过 90 天没碰的技能自动报警我的做法是在校验脚本里加了一个过期检查逻辑。每一项技能都有一个updated字段记录最近一次实践或者最后确认技能等级的时间。校验脚本在每次运行时计算当前日期和updated的间隔超过 90 天的技能会被标记为stale并在生成的页面里用黄色背景高亮。比这更进一步的是我在 GitHub Actions 里配置了一个定时任务每周一早上自动跑一次校验脚本。如果有stale数据脚本会直接创建一个 issue标题就叫“技能过期提醒Python 已超过 90 天未更新”正文列出相关的证据链接。我打开仓库看到这个 issue就知道自己该去补充实践或者调低评分了。这条自动化链路是整个项目里投入产出比最高的一部分。它把“主观自律”变成了“客观触发”我不需要每天盯数据数据自己会来找我。人的意志力不可靠但 CI 定时任务可以做到风雨无阻。5.2 用 GitHub Actions 做持续校验和页面发布工作流的配置文件长这样name: validate-and-deploy on: push: branches: [main] schedule: - cron: 0 22 * * 0 jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - uses: actions/setup-pythonv5 with: python-version: 3.12 - run: pip install jinja2 - run: python scripts/validate.py env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pagesv4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./output publish_branch: gh-pages这个工作流做了两件事每当有新的 commit 推送到 main 分支时自动跑一遍校验校验通过后立刻把渲染好的页面发布到gh-pages分支GitHub Pages 会自动生效每周日晚上 22 点定时任务也会触发一次校验专门检查数据是否过期有问题的数据通过 issue 通知我。我实际用下来的感受是自动化脚本 定时任务这套组合让 skills 仓库真正“活”了。它不再是一个靠意志力维持的文档而是一个有生命周期管理的系统。数据过期会被发现页面总是最新的我只需要专注于一件事——“填证据”和“改等级”。6. 实战中踩过的坑与应对方式这个项目跑了两年中间翻过不少车。如果你也要做类似的技能盘点系统下面这几个坑值得提前知道不然容易在数据积累到几十条之后才发现模型有问题返工成本非常高。分数漂移是最早遇到的坑。同一项技能连续两周评分从 3 滑到 2 又回到 3原因不是技能变了而是两次打分时参考的记忆片段不一样。为了校准我后来强制要求每次改分必须面对上一条证据不能再凭整体印象打分。要么更新证据把新版实践补进去等级才能往上走要么保留原有等级不变。6.1 分数漂移同样一个技能一个月内分数忽高忽低你如果在系统里放了五十个技能手动维护等级时最常犯的错就是“手一格一格打分”的时候尺度完全漂移。我实测发现连续评十个技能之后前五个和后五个的评分尺子已经不一样了注意力下降导致标准松懈。解决方法是在页面上加了一条“最近一次全量校准日期”字段并且每周只允许自己改十个以内的技能等级。一旦超过十个系统会提示你休息一下或者分两天再评。这个方法听起来很笨但确实有效它强制把评分过程拆成小块减少疲劳带来的主观偏移。6.2 粒度混乱技能树“长歪”了怎么修剪第二个坑是技能粒度越来越乱。刚建仓库时只有三十条后面越加越多最高峰到了七十多条。每条看起来都合理但雷达图越看越不对劲——有的维度塞了十几个节点有的维度只有两个节点数据之间的可比性已经没了。我找了个周末做了一次大修剪把维度内超过八个的技能合并同类项把“子技能”降级到证据备注里最终从七十多条收到四十二条。修完之后雷达图的可读性和之前完全不在一个量级这也是为什么我在前面的数据模型部分反复强调要控制粒度不是因为强迫症是因为粒度直接影响可视化和决策质量。6.3 技能盘点如何落到面试、晋升和年度规划里最后说点实际的。这套系统最大的收益不是雷达图好看而是它成了我面试、晋升和年度规划的数据底座。面试前我会直接打开 pages 链接把技能雷达和部分证据项目发给对方省掉了很多自我介绍里“熟悉”与“精通”的拉扯。面试官看到证据比看到形容词更有判断依据沟通效率明显提升。晋升答辩时最有用的部分是 Git 时间线。我把时间线上的 commit 整理成“半年投入记录”配合证据链接一起放进材料基本不需要再去翻聊天记录和邮件回想自己干了啥。年度规划也简单了直接看雷达图的凹陷维度那通常就是明年的成长方向。如果你从零开始搭这个系统我的建议是第一周只录入二十个技能先跑通校验、页面渲染、GitHub Actions 这三段链路再慢慢补齐到五十个以上。一上来就追求大而全很容易把时间耗在整理历史数据上最后连页面都没跑起来。先把骨架立住技能树和证据库随着日常实践长出来才是可持续的节奏。我现在的习惯是每次做完一个有点技术含量的任务顺手就更新一条技能证据。这个动作只需要两分钟但一年下来积累的数据量相当可观。技能的盘点从来不是一次性工程而是伴随职业生涯的长期项目。