把 Git 提交历史变成一条流动的河——Project River

作者:仿生狮子日期:2026/4/22

是什么

你有没有好奇过一个开源项目十年的贡献者活动长什么样?谁一直在写代码?谁是后来加入的?版本大升级时社区发生了什么变化?

我做了 Project River,一个 Git 历史可视化工具——输入一个 Git 仓库,能把每位贡献者的提交活动渲染成随时间流动的河流图(Streamgraph)。

项目地址:github.com/Lionad-Moro…

在线体验:lionad-morotar.github.io/project-riv…

landing.gif

直接看效果:

project-detail.png河流越宽,说明当天的提交越多。每条色带是一位贡献者,一眼就能看出"谁在写代码"、"社区什么时候开始膨胀"、"核心作者跑了没有"。

几个有趣的发现

项目分开发和静态版,静态版预制了几个知名项目的数据,如果你想分析自己的项目,需要去 Github 拉代码本地运行。

而静态版本预置的个项目的数据,每个都能讲出不同的故事。

React — Facebook 的集体力量

和 Vue 不同,React 没有一条独大的色带。多条宽带交替出现,反映出 Facebook 内部多人协作的模式。每年的 React Conf 前后都能看到提交量的明显脉冲。

jQuery — 一个时代的落幕

jQuery 的河流图像一条逐渐干涸的河。2014 年前波澜壮阔,之后逐年收窄。这是前端生态热度更替最直观的注脚。

能做什么

缩放和刷选 — 底部有一个 minimap,拖动选择框就能聚焦任意时间段。也支持触控板捏合缩放。

贡献者高亮 — 鼠标悬停在某个色带上,对应贡献者的提交明细会浮现出来,其他层自动淡出。

项目健康信号 — 自动分析贡献集中度、活跃度趋势等指标,帮助判断一个项目是否"健康"。

怎么用

最快的方式是直接打开 在线 Demo,预置了四个项目的数据。

如果你想分析自己的仓库:

  1. docker compose up -d 启动 PostgreSQL
  2. pnpm install && pnpm db:migrate
  3. pnpm dev 启动开发服务器
  4. 通过页面按钮或 CLI 工具分析你的 Git 仓库

刷新页面就能看到你的河流图了。

为什么是河流图

市面上的 Git 可视化工具(比如 GitHub Insights)大多用折线图或热力图展示提交量。但折线图只能回答"总量多少",无法直观感受比例和流向。

而河流图使用面积编码,同时展示总量和构成变化——对评估开源项目健康度来说,这是更合适的信息密度。

如果你也在关注开源项目的可持续性、或者想看看自己团队的提交节奏长什么样,欢迎试试。

GitHub 仓库 | 在线体验


如果觉得有意思,点个赞让更多人看到,非常感谢!


把 Git 提交历史变成一条流动的河——Project River》 是转载文章,点击查看原文


相关推荐


React性能优化
whuhewei2026/4/13

React应用在复杂场景下容易出现渲染性能瓶颈,合理优化能显著提升用户体验。React性能优化手段的核心在于减少不必要的渲染、控制资源加载和合理使用缓存机制。 1. 使用 React.memo 避免子组件无意义重渲染 当父组件更新时,即使子组件props未变,也会默认重新渲染。React.memo可缓存组件输出,仅在props变化时重新更新。 示例Demo: import React, { useState } from "react"; const ExpensiveComponen


PHP $_GET 变量详解
froginwe112026/4/5

PHP $_GET 变量详解 引言 PHP $_GET 变量是 PHP 中用于处理 URL 查询字符串参数的一个内置数组。在 Web 开发中,$_GET 变量经常用于收集来自表单的数据或者从 URL 中提取信息。本文将详细介绍 PHP $_GET 变量的基本用法、操作方法和注意事项。 一、$_GET 变量简介 在 PHP 中,$_GET 是一个超级全局变量,用于存储通过 URL 传递的参数。这些参数以名值对的形式出现在 URL 中,如 http://www.example.com/?ke


go实战案例:如何基于 Consul 给微服务添加服务注册与发现?
五年小兵勇闯互联网2026/3/27

在单体应用向微服务架构演进的过程中,原本的巨石型应用会按照业务需求被拆分成多个微服务,每个微服务会提供特定的功能,并可能依赖于其他的微服务。每个微服务实例都可以动态部署,服务实例之间的调用通过轻量级的远程调用方式(HTTP、消息队列等)实现,它们之间通过预先定义好的接口进行访问。         由于服务实例是动态部署的,每个服务实例的地址和服务信息都可能动态变化,这就势必需要一个中心化的组件对各个服务实例的信息进行管理,该组件管理了各个部署好的服务实例元数据,包括服务名、IP地址、端口号、服务


VMware虚拟机CentOS磁盘扩容完整指南(解决growpart报错 & LVM扩容)
Microi风闲2026/3/19

文章目录 前言✨一、环境与背景二、第一阶段:VMware 层面扩容三、第二阶段:CentOS 系统内部扩容方法一:标准LVM扩容流程(推荐)方法二:解决 growpart 报错方案(备用) 四、总结与注意事项 前言✨ 在日常开发和运维中,我们经常遇到 VMware 虚拟机磁盘空间不足的问题。本文记录了如何为一台正在运行的 CentOS 7 虚拟机安全地扩容磁盘空间的全过程。本次操作不仅涵盖了标准的扩容步骤,还重点解决了实际操作中可能遇到的两个关键问题: growpart


OpenClaw实战-NAS配置从0到1详细教程及踩坑记录
可夫小子2026/3/11

💡 大家好,我是可夫小子,关注AI编程、AI自动化和自媒体。 背景 我去年在自己Macbook上就已经安装了Openclaw了,当时基本就是一行命令,比较顺利。经过这两个月,Openclaw版本经历了很多更新,当时的安装教程有些过时了。最近,我需要在一台群晖的Nas部署Openclaw,硬是花了两天时间才完成。我把整个详细的部署过程,一些踩坑经历用图文记录下来,就有这篇包含30多张截图的图文。 方案说明 在Nas安装Openclaw,主要有三种方案来实现 直接通过官方脚本,安装到Nas物


NineData 迁移评估功能正式上线
NineData2026/3/3

做过数据库迁移的人,应该都有过类似经历:明明方案写得挺好,时间排得也挺满,但心里一直不踏实。因为真正的问题,往往不是工具能不能迁,而是迁过去以后还能不能跑。 NineData 这次做的迁移评估功能,本质上就只做一件事:提前把不确定性拆开,摊在你面前。 NineData 的一份体检报告,把风险摊在桌面上 异构迁移真正需要关注的是:要改多少?哪些能改?哪些根本不能动? 下面来列一列 NineData 能做哪些事情。 一、对象兼容性评估:哪些能直接迁,哪些一定要改 系统会自动分析源库和目标库的对象差异


AI 系统架构
lizhongxuan2026/2/23

AI 系统看起来很复杂,但核心可以压缩成三句话: 尽量少搬数据:很多时候不是算不动,而是数据搬运太慢。 尽量提高有效计算密度:让硬件更多时间在做有价值的乘加计算。 尽量重叠计算与通信:训练和推理都要避免“设备空等”。 换句话说,AI 性能问题本质上是 计算(Compute)+ 访存(Memory)+ 通信(Communication) 的协同问题。 1. AI 系统栈 层级主要职责典型问


Flutter三方库适配OpenHarmony【apple_product_name】异步调用与错误处理
淼学派对2026/2/14

前言 欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net 本文将围绕 apple_product_name 的实际 API,从 Future 基础到全局错误兜底,给出一套完整的异步调用与错误处理方案。 先给出结论式摘要: 所有 API 返回 Future:getMachineId()、getProductName()、lookup() 都是异步的,必须 await 或 .then()三类异常要分层捕获:PlatformExc


基于uview-pro的u-dropdown扩展自己的dropdown组件
LC同学479812026/2/6

基于uview-pro的u-dropdown扩展自己的dropdown组件 uview-pro的u-dropdown只能是菜单,且只能向下展开,当前组件采用它的核心逻辑,去除多余逻辑,兼容上/下展开,以及自定义展示的内容,不再局限于菜单形式 import type { ExtractPropTypes, PropType } from 'vue'; import { baseProps } from 'uview-pro/components/common/props'; /** * u-


🔥别再用递归了!WeakMap 的影子索引“让树不再是树!”
vilan_微澜2026/1/28

一、前言 大家好,我是微澜。今天来分享一个基于 WeakMap 实现的快速对树形结构数据进行增删改查操作的useTree hook函数,它是基于JavaScript 的 WeakMap 特性,在不改动原始数据的前提下,实现了一套 O(1) 查找的影子索引结构,这个影子其实就是对象的引用地址,让树形数据操作像操作数组一样简单! 二、为什么选择 WeakMap? 1. 非侵入性 (Non-invasive) 通过 WeakMap 在内存中构建了一套 Node -> Parent 的映射。原始数据对象

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 XYZ博客