记录一次 Fork 代码随想录仓库并提交 PR 的经历
前言
最近我一直跟着《代码随想录》刷 LeetCode。在学习图论章节时,我发现部分题目的 Go 版本存在缺失或代码与题解主题不一致的情况。
例如,卡码网第 0099 题的广度优先搜索题解中,Go 示例实际写的是递归 DFS;官网的深搜页面中,Go 标题下面也没有正常显示代码。后来做到第 0100 题时,我又发现原题解中没有 Go 的 BFS 版本。
刚好卡尔哥也一直鼓励大家共同维护项目,于是我决定不只是自己在本地改一改,而是尝试 Fork 仓库、修正代码并提交 Pull Request。这也是我第一次完整参与开源仓库的贡献流程,所以把操作步骤和遇到的问题记录下来。
一、Fork 原仓库
首先进入代码随想录的 GitHub 仓库,点击右上角的 Fork,将项目复制一份到自己的 GitHub 账号下。
Fork 完成后,会得到一个属于自己的远程仓库。页面上通常会显示:
1 | forked from youngyangyang04/leetcode-master |
这里需要理解两个远程仓库的概念:
origin:自己账号下的 Fork 仓库,拥有推送权限。upstream:代码随想录的原仓库,用来获取上游最新代码。
我本地的远程仓库配置类似这样:
1 | origin https://github.com/自己的用户名/leetcode-master.git |
可以使用以下命令查看:
1 | git remote -v |
如果克隆后还没有添加 upstream,可以执行:
1 | git remote add upstream https://github.com/youngyangyang04/leetcode-master.git |
二、同步上游并创建修改分支
开始修改前,先同步原仓库的最新代码:
1 | git fetch upstream |
然后从最新的 master 创建一个本次修改专用的分支。以修复第 0099 题为例:
1 | git switch -c fix/kamacoder-0099-go |
这里不需要提前在 GitHub 网页上创建分支。本地创建分支并推送后,远端会自动创建同名分支。
分支名可以自己决定,但最好让人一眼看懂修改内容,例如:
1 | fix/kamacoder-0099-go |
三、一个 PR 使用一个独立分支
我一开始容易混淆“分支”和“commit”的关系。正确的理解不是每次 commit 都要创建分支,而是每个独立任务或者 PR 使用一个分支:
1 | 一个修改任务 / PR |
例如,第 0099 题的两项修改属于同一个任务,所以可以放在同一个分支中,并拆成两个 commit:
1 | 修正0099岛屿的数量 Go 广搜版本 |
而第 0100 题新增 Go BFS 是另一个任务,应从最新的 master 新建分支:
1 | git switch -c feat/kamacoder-0100-go-bfs |
这样做可以避免第 0100 题的修改自动混入第 0099 题已经创建的 PR。
四、在错误分支修改后,使用 stash 转移
我在修改第 0100 题时,忘记切换分支,仍然停留在第 0099 题的分支上。因为修改还没有提交,可以先使用 stash 暂存工作区内容,再切换到正确分支:
1 | git stash push -m "添加0100 Go BFS版本" -- "problems/kamacoder/0100.岛屿的最大面积.md" |
第一次执行时我还遇到了下面的错误:
1 | fatal: not a git repository (or any of the parent directories): .git |
原因是终端位于 D:\Github-Fork,而真正的仓库目录是 D:\Github-Fork\leetcode-master。进入仓库后再执行 Git 命令即可:
1 | cd "D:\Github-Fork\leetcode-master" |
五、修改代码和 Markdown 时需要注意什么
1. 算法实现要与题解主题一致
广搜应该使用队列,而不是递归调用自身。一个典型的 Go BFS 结构如下:
1 | queue := [][2]int{{x, y}} |
节点应在加入队列时立即标记为已访问,防止同一节点重复入队:
1 | if grid[nextx][nexty] == 1 && !visited[nextx][nexty] { |
遍历每个岛屿的入口也要判断是否访问过:
1 | if grid[i][j] == 1 && !visited[i][j] { |
2. Go 代码应保持统一格式
需要注意变量名、空格、缩进和注释格式,例如:
1 | var n, m int |
尽量使用符合 Go 习惯的写法:
1 | !visited[i][j] |
而不是:
1 | visited[i][j] == false |
3. Markdown 代码块要完整
添加 Go 代码时,需要使用带语言标识的代码块,并确认开头与结尾成对出现:
1 | ```go |
修改完成后,还要确认后面的 Rust、JavaScript 等章节没有被错误包含进 Go 代码块。
4. 清理行尾空格
普通空行可以保留,但空行中不应包含空格或 Tab,代码行末尾也不应留下多余空格。可以使用下面的命令检查:
1 | git diff --check |
如果没有输出,就说明没有检测到这类空白问题。
Windows 下有时会看到:
1 | LF will be replaced by CRLF the next time Git touches it |
这通常只是换行符提醒,并不等于代码出错。
六、检查、暂存与提交
修改完成后,先查看状态和差异:
1 | git status |
确认只修改了目标文件后,将文件加入暂存区:
1 | git add "problems/kamacoder/0100.岛屿的最大面积.md" |
然后检查真正准备提交的内容:
1 | git diff --cached --check |
git status --short 中常见的状态有:
1 | M 文件名 工作区已修改,但尚未暂存 |
如果出现 MM,保存文件后重新执行一次 git add 即可更新暂存区。
七、规范填写 commit 信息
代码随想录要求 commit 信息说明本次提交具体修改了什么。如果不同文件对应不同目的,可以拆分提交。
第 0099 题我使用了两个 commit:
1 | git add "problems/kamacoder/0099.岛屿的数量广搜.md" |
第 0100 题新增 BFS 版本则可以使用:
1 | git commit -m "添加0100岛屿的最大面积 Go BFS版本" |
提交后检查:
1 | git status |
正常情况下,工作区应显示:
1 | nothing to commit, working tree clean |
八、推送分支到自己的 Fork
以第 0100 题为例:
1 | git push -u origin feat/kamacoder-0100-go-bfs |
这条命令会:
- 将本地分支推送到自己的 Fork。
- 如果远端不存在同名分支,则自动创建。
- 通过
-u建立本地分支与远端分支的跟踪关系。
建立跟踪关系后,后续在该分支继续修改时,通常直接执行 git push 即可。
九、创建 Pull Request
推送完成后,进入自己的 Fork,点击 GitHub 页面提示的 Compare & pull request。
创建 PR 时需要仔细确认方向:
1 | base repository: youngyangyang04/leetcode-master |
也就是说,请求将自己分支中的代码合入代码随想录原仓库的 master,不要把目标错误地选成自己 Fork 的 master。
如果一个 PR 只有一个 commit,PR 标题可以与 commit 信息相同:
1 | 添加0100岛屿的最大面积 Go BFS版本 |
如果一个 PR 包含多个 commit,PR 标题和描述应该对所有修改进行汇总。例如第 0099 题:
1 | 修正0099岛屿的数量 Go 广搜版本,优化 Go 深搜版本 |
PR 描述可以写成:
1 | - 修正0099岛屿的数量 Go 广搜版本,将误用的递归深搜实现改为队列广搜 |
建议保留勾选 Allow edits by maintainers,方便维护者在必要时直接调整代码。
确认无误后,点击 Create pull request。创建 PR 并不会直接修改原仓库,而是向维护者发起合并请求,之后等待代码审查即可。
十、这次贡献让我记住的几点
第一次完整走完 Fork 和 PR 流程,真正容易出错的不只是代码,还有分支、暂存区和提交范围。对我来说最重要的是以下几点:
origin是自己的 Fork,upstream是原仓库。- 每个独立任务或者 PR 使用一个单独分支,而不是每个 commit 都创建分支。
- 开始新任务前,先回到
master并同步上游。 - 在错误分支上产生未提交修改时,可以使用
git stash转移。 git diff查看工作区修改,git diff --cached查看准备提交的修改。- 提交前使用
git diff --check清理行尾空格。 - commit 描述单次修改,PR 描述汇总本次所有 commit。
- 创建 PR 时一定确认 base 和 compare 的方向。
这次尝试也让我意识到,参与开源维护并没有想象中那么遥远。发现问题、确认问题、在独立分支完成修改、认真检查并提交 PR,本身就是一次完整的贡献。即使只是补充一种语言的实现或者修正一个小错误,也能让后来阅读题解的人少踩一个坑。
后面如果继续在刷题过程中发现 Go 版本缺失或实现有问题,我也会继续尝试提交修改,并逐渐熟悉更规范的协作流程。








