GitHub 从入门到进阶:把一个人的代码,变成可协作、可验证的项目
把本地仓库接到 GitHub,走通远程推送、Issue、PR、自动测试和版本发布,建立能协作、能验证的项目。
会在电脑上创建 Git 提交以后,新的问题来了:换一台电脑怎么接着做?别人怎样提出修改?AI 帮我写完一个功能,怎样知道它可以合进主分支?
GitHub 把仓库、讨论、审阅和自动检查放在一起。对我来说,一个好项目应该让后来的人看得懂:它解决什么问题,怎样运行,当前哪些能力可靠,修改为什么被接受。
这篇接续 Git 教程,按“放上去 → 能协作 → 能检查 → 能交付”的顺序走。入门部分可以边读边做;进阶部分适合带着自己的项目逐项实践。精通来自多次完整交付,不来自一次性打开所有功能。
一、先认清仓库里的几个入口
| 入口 | 解决的问题 | 记账项目里的例子 |
|---|---|---|
| Code | 源码和历史放在哪里 | HTML 页面、后端接口、README |
| Issues | 需要解决什么 | 空月份合计显示错误 |
| Pull requests | 这次修改能否合入 | 修复金额计算,等待审阅 |
| Actions | 可以自动验证什么 | 每次修改运行记账计算测试 |
| Releases | 哪个版本可以交付 | v0.1.0 练习版及使用说明 |
| Settings | 谁能改、怎样约束 | 仓库可见性、分支规则、凭据配置 |
GitHub 是协作平台。能看到仓库、能 clone、能创建分支、能 push 到某个仓库,是不同权限;不要把一次登录成功理解为拥有所有操作权限。
二、把已有练习仓库连接到 GitHub
先注册并登录 GitHub,开启适合自己的账户保护,保存好恢复方式。创建一个名为 git-ledger-practice 的仓库。第一次练习可以设为私有,等确认内容适合公开后再考虑开放。
如果你已经完成上一篇的本地仓库,这里创建一个空远程仓库:不要再额外初始化 README、License 或 .gitignore。否则两边都会有各自的初始历史,第一次推送还要先处理它们的关系。空仓库建好后,复制仓库页面提供的 HTTPS 地址。
回到本地练习目录,先检查已有配置:
git status
git remote -v
确认还没有 origin,再把下面的 YOUR-ACCOUNT 替换成自己的 GitHub 用户名:
git remote add origin https://github.com/YOUR-ACCOUNT/git-ledger-practice.git
git push -u origin main
-u 设置当前分支的上游,之后在这条分支上通常可以直接 git push。命令结束后还要打开 GitHub 仓库,确认文件和最新提交确实出现。如果 origin 已存在,先核对地址,不要重复添加,也不要把别人的远程地址随意覆盖。
如果你的起点是一个已经有内容的 GitHub 仓库,直接使用 git clone 仓库地址,不要再走上述空仓库初始化流程。官方入门:Hello World
登录方式该选什么
通过 HTTPS 操作时,可以按 Git Credential Manager 的浏览器流程完成授权;也可以使用权限适当的个人访问令牌。SSH 则需要生成密钥,把公钥添加到账户,私钥留在自己控制的设备。GitHub 不接受用账户密码进行 Git 的 HTTPS 身份验证。官方:GitHub 身份验证
令牌和私钥不要放进项目、截图或聊天。多个 GitHub 账号并用时,提交邮箱与认证账号还可能不一致,应分别核对。遇到 permission denied,先检查“我用谁的身份、在访问哪个仓库”。
三、README 是项目的第一条使用路径
只有源码,别人并不知道该从哪里开始。我会在 README 里回答六个问题:
- 这个项目解决什么具体问题,适合谁?
- 现在确实能做什么,还不能做什么?
- 需要什么运行环境,怎样启动?
- 怎样用一组最小数据验证它正常?
- 数据保存在哪里,停止服务后会怎样?
- 怎样反馈问题,采用什么许可证?
例如,HTML 记账页应该明确它的数据保存在当前浏览器;引入后端的版本则要说明数据库位置与启动方式。不要只写“功能强大、开箱即用”,却让用户猜端口、目录和密码从哪里来。
公开仓库还需要认真选择许可证。能下载到源码并不等于可以任意复制、修改和商业使用。也不要把真实账单、数据库副本或访问密钥当作演示材料。演示数据应该明确标注为虚构。
四、从一个 Issue 开始,把需求说清楚
“修一下记账”很难验收。我会把 Issue 写成下面这样:
现象:选择没有任何记录的月份时,合计显示为空白。预期:显示 0 元,同时给出“暂无记录”。复现:创建一笔本月记录,切换到下个月。验收:有记录、无记录、删除最后一笔这三种情况都显示正确。本次不修改数据表结构。
这让开发者和 AI 都有明确的工作边界。Issue 记录的是问题和判断依据,PR 记录的是为解决它做出的代码修改。两者关联后,未来回看一个提交,才有机会知道背后的需求。
对于两三个待办,用 Issues 就足够。任务和参与者增加后再考虑 Projects 看板;不要为了管理工具先制造一套额外工作。
五、用 Pull Request 完成一次协作
在工作区干净、main 已与远程同步后,创建一个功能分支:
git switch main
git pull --ff-only
git switch -c docs/usage-guide
Add-Content -Encoding utf8 README.md 'Practice data only; see ledger.txt.'
git diff
git add README.md
git diff --staged
git commit -m "Document the practice data file"
git push -u origin docs/usage-guide
打开 GitHub,创建 PR。核对 base 是准备合入的 main,compare 是自己的 docs/usage-guide。标题说清行为变化,正文写原因、改动和验证。尚未准备好合并时,可以先创建 Draft PR。
审阅时我会先读 Files changed,再看自动检查和讨论。只看绿色按钮,会漏掉“代码没有报错,但解决错了问题”的情况。别人要求修改时,通常继续在同一分支提交、推送,这些提交会进入同一个 PR。官方:PR 快速入门
合并后回到本地 main 拉取更新。GitHub 页面删除远程分支,不会自动删除你本机的同名分支;本地清理前仍应确认有没有未提交工作。
六、选择合并方式,不要只认默认按钮
| 方式 | 合并后的历史 | 我的选择依据 |
|---|---|---|
| Merge commit | 保留分支提交,并增加合并节点 | 需要保留完整协作过程 |
| Squash and merge | 将 PR 的修改汇成一个新提交 | 一个功能里有很多修正小提交 |
| Rebase and merge | 把提交接到基础分支,形成线性历史 | 每个提交都整理得清楚、值得独立保留 |
没有适用于所有项目的唯一选择。个人练习项目可以从一种简单约定开始,例如一个问题一个 PR,再按需要 squash。重要的是后来的人能理解历史。
Squash 之后,本地分支的原提交未必是 main 的祖先,所以 git branch -d 可能提示尚未合并。不要因此立刻加 -D,先核对 GitHub 的合并结果、最终文件及是否还有未推送改动。
七、用一个真正检查结果的 Actions 工作流
自动化的价值在于重复执行已有验证标准。第一步不必自动部署,可以先让每次推送和 PR 都运行一个小测试。
例如在练习仓库加入 ledger.py:
def total_cents(amounts):
return sum(amounts)
再加入 test_ledger.py:
import unittest
from ledger import total_cents
class LedgerTests(unittest.TestCase):
def test_empty_month(self):
self.assertEqual(total_cents([]), 0)
def test_multiple_expenses(self):
self.assertEqual(total_cents([2300, 800]), 3100)
if __name__ == '__main__':
unittest.main()
金额使用整数分:2300 表示 23 元,避免这个最小例子直接用浮点数处理金额。在本机先运行 python -m unittest discover -v,应得到两个测试通过。这个示例只验证求和函数,不代表整个记账产品已验收。
在 .github/workflows/check.yml 放入:
name: ledger-check
on: [push, pull_request]
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: python -m unittest discover -v
这些版本标签用于说明最小工作流,并不表示它们是当前最新版本。正式项目应核对 Action 的维护状态和兼容要求,并评估固定完整提交 SHA。提交后去 Actions 查看触发分支、具体提交和日志;只有检查对应的是本次修改,它才有参考价值。官方:Actions 快速入门
可以在练习分支里故意把求和写错,确认测试会失败,再恢复。一个永远绿灯却不检查行为的工作流,只是装饰。真实项目还应根据影响增加接口、权限或浏览器验证。
八、把主分支约束和安全放在合适的位置
当 main 代表相对稳定的版本,可以配置分支保护或 Rulesets,要求通过 PR、完成检查后再合并。个人开发者未必有第二名审阅者,不要设置自己无法完成的审批流程。规则可用范围受套餐、仓库可见性和组织设置影响,以当前仓库可配置项为准。官方:Rulesets
Actions 的权限应围绕任务授予。仅运行测试的工作流通常不需要写仓库权限;涉及部署凭据时,要明确触发条件和使用范围。不熟悉安全边界时,不要照搬可以读取高权限凭据、执行外部 PR 代码的工作流。官方:Actions 安全使用
也不要把“已经放在 Secrets 里”等同于永远安全:被授权使用它的工作流仍可能误用。依赖告警和更新工具可以提供线索,但安全问题是否真正修复仍需核验。
成本方面,先了解账户当前 Actions 用量和计费范围,再增加自动任务;入门并不需要购买服务器。可用额度和功能按账户、仓库及所用运行环境变化,不应把网上的旧额度当长期承诺。官方:GitHub 套餐
九、Release、Pages 和部署,是三件不同的事
Tag 给历史中的一个位置命名。Release 基于标签组织版本说明和可下载产物。网站部署则是让一个经过选择的版本实际运行。仓库里出现 v0.1.0,不能证明用户访问到的就是它。
在干净且验证过的 main 上,可以创建带说明的标签:
git tag -a v0.1.0 -m "First verified practice version"
git push origin v0.1.0
然后在 GitHub 的 Releases 中选择该标签,说明版本包含什么、如何运行、已知限制是什么。如果之前已存在同名标签,不要覆盖它。官方:Releases
GitHub Pages 适合托管静态 HTML、CSS 和 JavaScript,也可以部署构建后的静态站点。它不能直接运行你写的常驻 Python 后端或 PostgreSQL 数据库。因此,第一集的纯页面和第二集的前后端应用,部署方式可能不同。官方:GitHub Pages
对我来说,一次发布至少要留下:对应的提交、验证结果、用户访问地址和恢复方式。页面能打开以后,还要实际完成关键操作;访问首页成功并不能证明保存数据正常。
十、参与别人的项目:先了解规则,再提出小改动
没有目标仓库写权限时,可以通过 Fork 建立自己名下的副本,在自己的分支提交修改,再向原仓库提 PR。Fork 是平台上的仓库副本;clone 是把某个仓库下载到本地,两者不是一回事。
先读 README、CONTRIBUTING 和已有 Issues,确认维护者接受怎样的贡献。第一次贡献可以选择一个能复现、能说明、影响范围小的问题,而不是顺手重构整个工程。官方:参与开源项目
提交前解释问题、修改方式和验证证据。维护者要求调整时,围绕证据讨论;PR 被接受也不等于已经发布到用户使用的版本。遇到安全漏洞,应按项目安全报告流程处理,避免在公开 Issue 暴露可利用细节。
十一、让 GitHub 成为 AI 工作的可核对记录
我希望 AI 交付一个功能时,不只是回复“完成了”,还要能指出:对应哪个 Issue,改动在哪个 PR,检查的是哪个提交,有没有留下尚未解决的问题。
可以这样下任务:
根据这个 Issue 修复空月份显示。先确认仓库和分支,保留已有未提交修改。实现后运行相关验证,准备 PR,写明用户可见变化、测试结果和限制。不要自动修改仓库权限或部署设置。
这类约束不会替代思考,但能让判断留下证据。一个红色检查可能是代码问题,也可能是运行环境或额度问题;一个绿色检查也可能缺少关键场景。读日志、看差异、亲自体验仍然必要。
十二、从入门走向熟练的练习路线
第一轮:创建练习仓库,成功推送,换一个空目录 clone,确认文件和历史一致。
第二轮:写一条可复现 Issue,用分支完成修改,创建 PR,审阅差异并合并。
第三轮:加入自动测试,亲手制造一次失败,从 Actions 日志中找到原因,再修复。
第四轮:为确认可用的版本创建标签和 Release。若项目适合静态托管,再尝试 Pages,核对线上实际内容。
第五轮:阅读一个真实开源项目的贡献要求,提交一个范围清楚的小改动,经历反馈与修改。
走完这些过程,你学到的就不只是“把代码放到 GitHub”。你会逐渐建立一条自己能解释的交付流程:为什么做、改了什么、如何验证、交付了哪一个版本。需要回顾本地版本管理时,可以返回 Git 篇。
夏末