Changelog 自動化革命:結合 LLM 與 Git 日誌的全流程解決方案

作者: Calpa Liu
字數:4729
出版:2025 年 4 月 25 日

結合 Node.js、大型語言模型(LLM),打造一套能自動解析 Git commit 並生成語意清晰 Changelog 的工具,解放開發者的文書負擔,提升團隊協作效率。

動機與痛點:手動整理 Changelog 有多痛苦?

在現代軟體開發流程中,良好的 Changelog(變更日誌)不僅能幫助開發者追蹤歷史,更是版本管理、發布流程、甚至產品溝通的關鍵橋梁。然而,實務上要維護一份語意清晰、結構一致的 Changelog,往往是一件吃力不討好的工作。多數團隊仰賴手動彙整 Git commit、複製貼上、逐條潤飾,不但耗時繁瑣,也容易遺漏關鍵資訊,導致變更記錄失真、上下游溝通不順,甚至版本發布後才發現文件描述與實際行為不符。

此外,當團隊成員眾多、專案規模龐大,Changelog 的維護難度更是呈指數級上升。不同開發者的 commit 風格不一致,有的使用 fix:、有的使用「修 bug」、有的乾脆不寫訊息,讓自動化彙整難以啟動。即便使用 Conventional Commits 等標準,也難以產生具語意性的自然語言摘要。因此,我們需要一種更智慧、更人性化的方法——讓 AI 協助理解 commit 背後的意圖,自動撰寫出有邏輯、有重點的 Changelog,從根本解決「文件永遠趕不上代碼變更」的老問題。

本篇將進一步結合大型語言模型,讓 changelog 的撰寫邁向智慧化與語意清晰。

自動整理 Changelog 的革命時代

還在手動整理 changelog 嗎?現在只需要 git log + ChatGPT,就能一鍵產出語意清晰的變更摘要!

這篇文章將教你如何打造一個「會說話的 Git 日誌助手」: 透過 Node.js 腳本自動擷取當日的提交紀錄 ➜ 儲存為 JSON ➜ 貼到 ChatGPT ➜ 自動生成 changelog。 不只減少文書負擔,還能大幅提升團隊同步效率。

以下是實戰中使用的 ChatGPT 提示語,歡迎直接複製貼上使用:

以下是今日的 Git log 資訊,請根據此資訊完成今日的 changelog 摘要:
```
<!-- GIT LOG -->
```

1. 分析變更內容(以繁體中文撰寫回答)
根據剛剛產出的 logs/git/YYYY-MM-DD.json 檔案,請針對以下問題進行整理與說明:

今日變更的核心主題是什麼?

主要進行了哪些功能開發、錯誤修正或重構?

涉及的關鍵檔案有哪些?(請列出數個具代表性的檔案路徑)

今日總共包含幾筆 commit?

2. 產出 Markdown 摘要
請根據上方分析結果,撰寫一段簡明扼要的摘要段落,格式採用 Markdown,並適用於部落格或 changelog 使用。

輸出格式範例如下:

```md
## 2025-04-25 變更摘要

今日主要進行了 Git 相關日誌與摘要功能的開發與優化,包含:

- 新增 Git log 收集腳本 `scripts/createChangelog.ts`,自動擷取並格式化當日 commit 記錄。
- 新增 changelog 自動產生腳本 `scripts/createChangelog.ts`,並產出每日 JSON 及 Markdown 摘要。
- 新增與更新日誌檔案:`logs/git/2025-04-25.json``logs/summary/2025-04-25.md`
- 新增部落格圖片資源設定檔 `src/data/images.json`

今日共 2 筆 commit,核心主題為自動化日誌產出流程與相關檔案維護。
```

如果你希望全自動的話,那麼你可以根據以下的教學,使用指令集直接完成當日的 changelog 摘要生成。

技術選型

我們的 Git 日誌精靈將使用 Node.js 開發,這是一個理想的選擇,原因有三:首先,JavaScript/TypeScript 對於前端和全棧開發者來說門檻較低;其次,Node.js 擁有豐富的檔案系統和子進程操作 API;最後,npm 生態系統提供了大量可用的輔助庫,如 moment.js 用於時間處理。

核心架構將包含以下模組:Git 命令執行與解析模組、日誌格式化與儲存模組、人性化互動介面模組。這種模組化設計使得我們的工具不僅功能齊全,而且易於擴展和客製化。

建立專案與安裝依賴

首先,我們需要建立一個 Node.js 專案並安裝必要的依賴包。我們將使用 TypeScript 來提升代碼的可維護性和類型安全。

mkdir git-diary
cd git-diary
npm init -y
npm install typescript ts-node @types/node moment

接著,創建基本的資料夾結構:

mkdir -p logs/git logs/summary scripts
touch tsconfig.json

tsconfig.json 中設置基本的 TypeScript 配置:

{
  "compilerOptions": {
    "target": "ES2018",
    "module": "CommonJS",
    "outDir": "./dist",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

腳本開發環境準備

為了開發我們的 Git 日誌工具,需要確保系統已經安裝了 Git,並且當前資料夾是一個 Git 倉庫。如果不是,可以使用以下命令初始化一個倉庫:

git init
git config user.name "Your Name"
git config user.email "your.email@example.com"

這些準備工作完成後,我們就可以開始編寫核心腳本了。

Git 日誌收集與處理的核心邏輯

Git 命令解析與執行

我們的工具核心是從 Git 提交記錄中獲取有用資訊。我們使用 Node.js 的 child_process.execSync 方法來執行 Git 命令,下面是 Git log 命令的解析:

const raw = execSync(
  `git log --since=midnight --date=iso-strict --pretty=format:'__SPLIT__%H|%ad|%s|%b' --name-only`,
  { encoding: "utf-8" }
);

這條命令包含幾個關鍵參數:

  • --since=midnight:只獲取當天的提交記錄
  • --date=iso-strict:使用 ISO 標準格式輸出日期
  • --pretty=format:'__SPLIT__%H|%ad|%s|%b':自訂輸出格式,包含哈希值、日期、主題和詳細說明
  • --name-only:同時列出每次提交修改的檔案

這個命令會返回一個格式化的字串,我們需要解析它將其轉換為結構化資料。

日誌資料結構與格式化

接下來,我們需要將原始的 Git log 輸出解析為可用的 JSON 格式:

const commits: any[] = [];
const lines = raw.split("\n");

let current: any = null;
for (const line of lines) {
  if (line.startsWith("__SPLIT__")) {
    if (current) commits.push(current);
    const [hash, date, subject, body] = line.slice(9).split("|");
    current = { hash, date, subject, body, files: [] };
  } else if (line.trim()) {
    current?.files.push(line.trim());
  }
}
if (current) commits.push(current);

這段代碼將 Git 命令的輸出解析為一個結構化的陣列,每個元素代表一個提交記錄,包含哈希值、日期、主題、詳細說明和修改的檔案列表。這種結構使得我們可以輕鬆地進行後續處理和分析。

檔案系統操作與日誌儲存

解析後的提交記錄需要持久化儲存,以便日後查詢和分析。我們使用 Node.js 的 fs 模組來完成這一操作:

writeFileSync(
  path.join("logs", "git", `${DATE}.json`),
  JSON.stringify(commits)
);

這行代碼將解析後的提交記錄以 JSON 格式儲存到 logs/git 資料夾下,檔名為當天的日期。這樣,我們就有了一個按日期組織的提交記錄資料庫,便於日後查詢和統計。

同時,我們也需要處理摘要檔案的存在性檢查和刪除操作:

if (existsSync(path.join("logs", "summary", `${DATE}.md`))) {
  // 如果當天的摘要檔案已存在,則刪除它
  unlinkSync(path.join("logs", "summary", `${DATE}.md`));
}

這樣,每次執行腳本時,我們都能確保生成新的摘要檔案,避免資訊重複或過時。

擬人化互動設計:讓你的 CLI 工具更有溫度

擬人化輸出機制的實現

我們的工具最獨特的特點是它具有「人性化」的互動體驗。為了實現這一點,我們設計了一個模擬人類輸入的函數:

async function sleep(ms: number) {
  return new Promise((r) => setTimeout(r, ms));
}

async function sayLikeHuman(lines: string[], delay = 1000) {
  for (const line of lines) {
    console.log(line);
    await sleep(delay);
  }
}

這個函數接受一組文字行和延遲時間,並按順序輸出它們,每行之間有一定的延遲。這種延遲輸出模擬了人類打字的節奏,使得輸出看起來更像是一個真實的人在和你對話,而不是冰冷的機器輸出。

多場景的擬人化對話設計

根據不同的情境,我們的工具會輸出不同的擬人化訊息。例如,當成功收集到提交記錄時:

await sayLikeHuman([
  `📦 今日 Git log 已成功保存至 logs/git/${DATE}.json!`,
  `📖 今天共記錄了 ${commits.length} 筆 commit,小心翼翼地封裝在日誌裡了喔~`,
  `🧸 請問您要來點……「推進世界的程式碼」嗎?`,
]);

當需要刪除舊的摘要檔案時:

await sayLikeHuman([
  `🔍 咦?我發現今天的摘要已經存在了耶。`,
  `🧹 為了讓日誌乾乾淨淨,我來幫你把它收拾掉吧~`,
]);
// 刪除操作
await sayLikeHuman([
  `🗑️ 嗯哼,舊的摘要已經被我丟進回收桶囉!`,
  `✨ 我們可以重新寫下一段更棒的歷史了呢~`,
]);

當當天沒有提交記錄時:

await sayLikeHuman([
  `☁️ 咦……今天還沒有任何 commit 呢。`,
  `📭 沒關係,靈感總是在悠閒時降臨~`,
  `🐰 請問您要來點……寫程式的魔法嗎?`,
]);

這些不同場景下的擬人化訊息讓工具更加生動有趣,同時也提供了清晰的狀態反饋。

個人風格定製與本地化

工具的擬人化風格可以根據個人喜好進行定製。我們在腳本中使用了一種輕鬆、活潑的風格,添加了表情符號和擬態語氣詞,營造一種可愛的助手形象。但這種風格可以根據需要調整為更專業、更嚴肅,或者完全不同的個性。

此外,我們還加入了用戶名稱的獲取和使用:

const user = execSync("git config user.name", { encoding: "utf-8" }).trim();
console.log(`🌸 ${user} にゃっはろ〜 我是你的寫程式小幫手!`);

這種個人化的問候使得工具感覺更加親近和貼心。你可以根據自己的喜好調整問候語和對話風格,甚至可以加入不同語言的元素,如這裡的日語問候語「にゃっはろ〜」。

完整原始碼

// scripts/collectGitlog.ts
import { execSync } from "child_process";
import { writeFileSync, existsSync, unlinkSync } from "fs";
import moment from "moment";
import path from "path";

async function sleep(ms: number) {
  return new Promise((r) => setTimeout(r, ms));
}

async function sayLikeHuman(lines: string[], delay = 1000) {
  for (const line of lines) {
    console.log(line);
    await sleep(delay);
  }
}

async function main() {
  const DATE = moment().format("YYYY-MM-DD");

  const user = execSync("git config user.name", { encoding: "utf-8" }).trim();

  console.log(`🌸 ${user} にゃっはろ〜 我是你的寫程式小幫手!`);

  await sleep(500);

  const raw = execSync(
    `git log --since=midnight --date=iso-strict --pretty=format:'__SPLIT__%H|%ad|%s|%b' --name-only`,
    { encoding: "utf-8" }
  );

  if (raw.trim()) {
    const commits: any[] = [];
    const lines = raw.split("\n");

    let current: any = null;
    for (const line of lines) {
      if (line.startsWith("__SPLIT__")) {
        if (current) commits.push(current);
        const [hash, date, subject, body] = line.slice(9).split("|");
        current = { hash, date, subject, body, files: [] };
      } else if (line.trim()) {
        current?.files.push(line.trim());
      }
    }
    if (current) commits.push(current);

    writeFileSync(
      path.join("logs", "git", `${DATE}.json`),
      JSON.stringify(commits)
    );
    await sayLikeHuman([
      `📦 今日 Git log 已成功保存至 logs/git/${DATE}.json!`,
      `📖 今天共記錄了 ${commits.length} 筆 commit,小心翼翼地封裝在日誌裡了喔~`,
      `🧸 請問您要來點……「推進世界的程式碼」嗎?`,
    ]);

    if (existsSync(path.join("logs", "summary", `${DATE}.md`))) {
      await sayLikeHuman([
        `🔍 咦?我發現今天的摘要已經存在了耶。`,
        `🧹 為了讓日誌乾乾淨淨,我來幫你把它收拾掉吧~`,
      ]);
      unlinkSync(path.join("logs", "summary", `${DATE}.md`));
      await sayLikeHuman([
        `🗑️ 嗯哼,舊的摘要已經被我丟進回收桶囉!`,
        `✨ 我們可以重新寫下一段更棒的歷史了呢~`,
      ]);
    }
  } else {
    await sayLikeHuman([
      `☁️ 咦……今天還沒有任何 commit 呢。`,
      `📭 沒關係,靈感總是在悠閒時降臨~`,
      `🐰 請問您要來點……寫程式的魔法嗎?`,
    ]);
  }
}

main();

實用場景與擴展應用

在團隊開發環境中,這個 Git 日誌工具可以發揮更大的價值。首先,它能夠輔助每日站立會議,自動生成每位成員的日報內容,節省溝通時間。此外,在版本發布準備階段,工具能快速彙整特定時間段內的所有變更,便於撰寫發布說明。對於代碼審查,提供清晰的提交歷史脈絡,幫助審查者理解代碼變更背景。新成員入職時,工具則能幫助他們快速了解項目的最近變更和開發方向。

我們的工具可以與現代開發流程和工具無縫整合。它能夠融入 CI/CD 流程,在持續集成時自動執行,生成每次構建的變更摘要,並將日誌摘要發送到 Slack 或 Discord 等團隊通訊渠道,保持團隊同步。此外,工具還可以與 VuePress、Docusaurus 等文檔系統集成,自動更新變更日誌頁面,並與 Jira、Trello 等項目管理工具連接,自動關聯提交與任務。

雖然我們的基礎工具已經能夠滿足日常需求,但還有許多方向可以進行擴展和改進。首先是智能分類與分析,使用自然語言處理技術對提交訊息進行分類和主題提取。其次是圖表視覺化,生成提交頻率、檔案修改熱圖等視覺化報表。也可以考慮提交品質檢查,評估提交訊息的質量並提供改進建議。工具還可以設計多種互動「人格」,如可愛助手、嚴肅顧問、幽默朋友等,根據心情切換,並支持多語言,適應國際團隊需求。

使用技巧

為了充分發揮工具的價值,建議設置定時任務或整合到工作流程中。首先,可以使用 cron 任務在每天結束時自動執行腳本,收集當天的提交記錄。此外,將腳本作為 Git post-commit 鉤子的一部分,每次提交後自動更新日誌也是一個可行的方案。最後,可以在 VS Code 或其他編輯器中添加自定義命令,一鍵執行日誌生成。

為了讓生成的日誌更有價值,可以考慮使用統一的提交規範,如 Conventional Commits,從而使自動生成的日誌更加結構化。可以在日誌中區分不同成員的貢獻,促進責任感和團隊意識,並在提交訊息中引用議題編號、文檔鏈接等,豐富日誌內容。此外,記錄各類任務所花費的時間,有助於工作量評估和計劃改進。

在使用此工具時,需要注意幾個常見問題。對於非常大的存儲庫,可能需要限制歷史查詢範圍,以避免效能問題。確保正確處理提交訊息中的特殊字符,防止解析錯誤。在生成團隊共享日誌時,應注意是否包含敏感資訊。對於分佈式團隊,需要正確處理不同時區的日期問題,以避免混淆。

AI 支援整合

Windsurf

如果您正在使用 Windsurf 平台,並希望將本工具整合進每日自動化開發流程中,以下是一套可立即上手的指令集。這些指令將協助您快速產出當日的 Git 變更記錄,分析提交內容,並自動生成 Markdown 格式的日誌摘要,無須手動操作任何流程。

只需將下方指令貼上並執行,即可觸發完整流程,從原始 Git 資料擷取、格式化、清理舊日誌到新摘要輸出,全自動完成,是提升開發效率與維護紀錄品質的最佳利器:

# AI 指令開始(請自動執行以下工作流,每次貼上都應重新執行。不需解釋過程,也不需顯示輸出內容)

---

# 自動產出日誌摘要

## 1. 產出當日 Git 變更記錄(JSON 格式)
請先執行以下指令:

```bash
npx tsx scripts/createChangelog.ts
```

這個指令會擷取從今日午夜開始的所有 Git commit 紀錄,並轉換成格式化的 JSON 檔案,儲存路徑為:

```
logs/git/YYYY-MM-DD.json
```

---

## 2. 分析變更內容(以繁體中文撰寫回答)
根據剛剛產出的 `logs/git/YYYY-MM-DD.json` 檔案,請針對以下問題進行分析與回答:

- 今日變更的核心主題是什麼?
- 主要進行了哪些功能開發、錯誤修正或重構?
- 涉及的關鍵檔案有哪些?(請列出數個代表性的檔案路徑)
- 今日總共包含幾筆 commit?

---

## 3. 產出 Markdown 摘要
請根據分析結果撰寫一段簡潔扼要的摘要段落,格式為 Markdown,用於 blog 或 changelog。

輸出到 `logs/summary/YYYY-MM-DD.md`,輸出格式範例如下:

```
## 2025-04-25 變更摘要

今日主要進行了 Git 相關日誌與摘要功能的開發與優化,包含:

- 新增 Git log 收集腳本 `scripts/createChangelog.ts`,自動擷取並格式化當日 commit 記錄。
- 新增 changelog 自動產生腳本 `scripts/createChangelog.ts`,並產出每日 JSON 及 Markdown 摘要。
- 新增與更新日誌檔案:`logs/git/2025-04-25.json`、`logs/summary/2025-04-25.md`。
- 新增部落格圖片資源設定檔 `src/data/images.json`。

今日共 2 筆 commit,核心主題為自動化日誌產出流程與相關檔案維護。
```

任務完成後,請僅回覆「生成成功」。

# AI 指令結束

生成結果

## 2025-04-25 變更摘要

今日主要進行了 Git 日誌與摘要自動化流程的開發與優化,包含:

- 新增 Git log 收集腳本 `scripts/collectGitlog.ts`,自動擷取並格式化當日 commit 記錄。
- 新增 changelog 產生腳本 `scripts/createChangelog.ts`,並產出每日 JSON 及 Markdown 摘要。
- 新增與更新日誌檔案:`logs/git/2025-04-25.json``logs/summary/2025-04-25.md`
- 新增部落格圖片資源設定檔 `src/data/images.json`
- 新增部落格文章:`src/content/blog/2025/2025-04-25.md`

今日共 4 筆 commit,核心主題為自動化日誌產出流程、相關檔案維護與部落格內容更新。

結論

我們通過這篇文章,從零開始打造了一個有溫度、會說話的 Git 日誌工具。它不僅能自動收集和整理提交記錄,還能以擬人化的方式與使用者互動,為日常開發工作增添儀式感和樂趣。這個工具雖然簡單,但卻體現了「技術服務人性」的理念,讓我們在數字化工作流程中保留人文關懷。

未來,隨著人工智能技術的發展,我們可以期待這類工具進一步進化:自動總結代碼變更的內容和影響;根據歷史數據預測項目風險和開發節奏;甚至能夠理解開發者的工作狀態和情緒,提供更個性化的互動體驗。這些進步將使得開發工具不僅僅是冰冷的生產力工具,更成為開發者工作中的智能夥伴。

最後,希望本文能夠啟發你在日常工作中尋找技術與人性的平衡點,用創意和關懷改進開發體驗。無論是團隊協作還是個人項目,一個會說話、有個性的工具往往能帶來意想不到的價值和樂趣。

感謝您閱讀我的文章。歡迎隨時分享你的想法。
關於 Calpa

Calpa 擅長使用 TypeScriptReact.jsVue.js 建立 Responsive Website。

他積極參與開源社區,曾在 2019 年的香港開源大會上擔任講者,提供工作經驗和見解。此外,他也在 GitHub 上公開分享個人博客程式碼,已獲得超過 300 顆星星和 60 個分支的支持。

他熱愛學習新技術,並樂意分享經驗。他相信,唯有不斷學習才能跟上快速演變的技術環境。

熱門文章

最新文章