GitHub 与 Git 概念及协作操作对照
# GitHub 与 Git:知识点地图
Git 管理提交对象、引用、历史和文件差异;GitHub 在远程 Git 仓库之上提供 Compare、Pull Request、Review、Checks、Release 等协作功能。学习时先分清“查看什么”“改变哪条引用”“是否生成新提交”,再对应网页操作和命令。
本文集中整理概念关系和官方入口;本地命令细节见 Git 文档,平台操作的命令行入口见 GitHub CLI 工作流。推荐顺序:引用与历史 → Compare → PR → Merge → 同步与撤销。
两层能力的边界
| 层次 | 核心知识点 | 查询入口 |
|---|---|---|
| Git 数据模型 | commit、parent、tree、branch、tag、HEAD;提交构成有向无环图,分支是可移动引用 | Pro Git:Git 对象 (opens new window)、Git 引用 (opens new window) |
| Git 本地状态 | 工作区、暂存区、已提交历史;本地分支与远程跟踪引用 | Pro Git:记录更新 (opens new window)、远程分支 (opens new window) |
| GitHub 协作对象 | PR、Review、Issue、Checks、Rules;这些信息不是普通 Git 提交对象 | GitHub 官方文档首页 (opens new window)、Pull requests (opens new window) |
# 引用、仓库与版本
| GitHub 中看到的概念 | Git 对应概念/命令 | 需要区分的边界 | 官方文档 |
|---|---|---|---|
| Branch | refs/heads/NAME;git branch、git switch | GitHub 上的 main、本地 main、本地 origin/main 可以指向不同提交 | GitHub Branches (opens new window)、git-branch (opens new window) |
| Commit / SHA | 提交对象;git show SHA、git rev-parse REF | SHA 标识具体对象;分支名会随新提交移动 | Git revisions (opens new window)、git-show (opens new window) |
| base / head | 比较或合并的方向:head 提出变更,base 接收变更 | PR 的 head 分支不是“你此刻本地检出的 HEAD”;base 也不一定是 main | GitHub PR (opens new window) |
| Fork / Clone | Fork 是 GitHub 上的派生仓库关系;Clone 是 git clone URL 创建本地仓库 | 没有原生 git fork;克隆不会自动创建 GitHub fork | Fork a repository (opens new window)、git-clone (opens new window) |
| Tag / Release | Tag 对应 git tag;Release 是围绕 tag 的发布说明、附件等平台对象 | 推送 tag 不等于已创建 Release,clone 也不会下载全部 Release 附件 | About releases (opens new window)、git-tag (opens new window) |
本地 HEAD 通常指向当前分支,分离头指针时直接指向提交;origin、upstream 是约定名称,不是 Git 内置的特殊服务器。origin/main 是本地保存的远程状态记录,不是每次读取都会联网查询的远程分支。
# Compare、Diff 与提交历史
网页与命令对照
/compare/ 是 GitHub 的网页路由,完整格式为 https://github.com/OWNER/REPO/compare/BASE...HEAD_REF。表中的 A、B 可以是远端可访问的分支、标签或 SHA。格式参考 GitHub Comparing commits (opens new window)。
| 想回答的问题 | Git 命令 | GitHub 对应视图/路径 | 比较语义 |
|---|---|---|---|
| 两个版本的文件最终差多少? | git diff A B 或 git diff A..B | /OWNER/REPO/compare/A..B | 比较 A 与 B 的文件快照 |
| B 从分叉点以来改了什么? | git diff A...B | /OWNER/REPO/compare/A...B;PR 的 Files changed 使用三点比较 | 比较 merge base 与 B 的文件快照 |
| B 比 A 多了哪些提交? | git log A..B | Compare 中查看提交列表时,需按页面实际 base/head 核对 | B 可达、A 不可达的提交集合 |
| 两边各自有哪些独有提交? | git log --left-right A...B | 分支 ahead / behind 信息可作为入口 | 两侧提交集合的对称差,不是文件 diff |
| 两边各领先多少提交? | git rev-list --left-right --count A...B | ahead / behind | 输出依次为 A 独有、B 独有的提交数 |
| 某次提交改了什么? | git show SHA | /OWNER/REPO/commit/SHA | 单次提交视图;合并提交有多个父提交,比较方式需要另看 |
| 未提交文件改了什么? | git diff、git diff --staged | 没有直接对应的远程页面 | 工作区、暂存区内容只存在本地 |
文件比较定义见 git-diff (opens new window) 与 GitHub 两点、三点比较 (opens new window);提交集合定义见 gitrevisions 的范围语法 (opens new window)。同样的点号在 diff 和 log 中回答不同问题。
merge base 是 Compare 与 Merge 的共同基础
假设分支历史如下,M 为共同祖先:
A1---A2 main(A)
/
M---+
\
B1---B2 feature(B)
2
3
4
5
| 操作 | 实际比较/用途 |
|---|---|
git merge-base A B | 找出共同祖先;此例为 M |
git diff A..B | A2 的文件快照 → B2 的文件快照 |
git diff A...B | M 的文件快照 → B2 的文件快照 |
git diff B...A | M 的文件快照 → A2 的文件快照;三点比较有方向 |
| 将 B 合并到 A | 典型三方合并以 M、A2、B2 为基础,整合两边改动;仅看三点 diff 不能证明合并无冲突 |
A 是 B 的祖先时,两点、三点的文件差异相同。复杂历史可能存在多个最佳共同祖先,不能把所有历史都简化成唯一分叉点;进一步见 git-merge-base (opens new window)。
让远程链接与本地范围一致
本地 git diff A...HEAD 对应网页 /compare/A...B,其中 B 应替换为 git rev-parse HEAD 得到的 SHA,并确认已推送。只有本地 HEAD 与远端 main 指向同一提交时,才能用 main 代替 B;main 继续前进后链接结果会变化。需要固定结果时,两端都用固定 SHA。
网页 diff 可能受显示限制、空白忽略和文件隐藏规则影响;这里对齐的是比较端点,不承诺输出逐字一致。Compare 只是查询,不会自动创建 PR,也不会执行 merge。
# Pull Request、Review 与合并条件
| GitHub 操作/状态 | 与 Git 的关系 | 关键知识点 | 官方文档 |
|---|---|---|---|
| Open PR | 提出把 head 合入 base 的协作请求;不是 git pull | 包含讨论、审查、检查;创建 PR 不会移动 base | About pull requests (opens new window) |
| 向 PR 追加提交 | 向同一 head 分支继续 commit、push | PR 随 head 更新;它不是创建时冻结的一份补丁 | Committing changes to a PR branch (opens new window) |
| Approve / Request changes | 平台审查结果,没有同名原生 Git 命令 | 审查通过、检查通过和可自动合并是不同条件 | PR reviews (opens new window) |
| Checks / Required checks | CI 等外部系统对提交上报结果 | CI 成功不代表无冲突,也不代表已满足全部仓库规则 | Status checks (opens new window) |
| Merge conflict | Git 无法自动整合部分内容,需要解冲突后提交或继续 rebase | 无冲突也可能因权限、审查或规则而不能合并 | Resolving a merge conflict (opens new window) |
| Close PR | 关闭协作请求 | 不等于撤销提交;不会自动删除远程分支 | Closing a PR (opens new window) |
| Branch protection / Rulesets | GitHub 限制远端引用如何更新 | 本地 git merge 成功不代表远端允许 push | Protected branches (opens new window)、Rulesets (opens new window) |
# Merge:三种方式与 Git 的对应关系
下面假定当前检出 base,feature 为来源分支。命令用于解释历史结构,不代表 GitHub 后端逐字执行这些命令,也不包含权限、CI、审查和服务器端元数据处理。
| GitHub 合并方式 | Git 对应思路 | base 上的历史结果 | 适合关注的知识点 |
|---|---|---|---|
| Create a merge commit | git merge --no-ff feature | 保留来源提交,新增一个通常有两个父提交的 merge commit | 保留分支拓扑;可追溯一组提交在哪里合入 |
| Squash and merge | git merge --squash feature,再 git commit | 将本次 PR 改动汇为 base 上的一个新提交 | 原提交不会逐个成为 base 的祖先;内容已合入不等于 SHA 已合入 |
| Rebase and merge | 类似先 git rebase base feature,再切回 base 执行 git merge --ff-only feature | 保留逐条提交的粒度,形成线性历史,无 merge commit | 此本地类比会改写 feature;不能视为 GitHub 后端步骤。GitHub 会创建新 SHA |
| 无独立网页 PR 按钮对应的 fast-forward | git merge --ff-only feature | 只移动分支引用,不创建提交;发生分叉则失败 | 与 --no-ff、squash、重放提交分别区分 |
三种平台方式见 GitHub Pull request merges (opens new window);本地细节见 git-merge (opens new window) 和 git-rebase (opens new window)。GitHub 的 Rebase and merge 总会更新 committer 信息和 SHA,与某些情况下本地 rebase 不生成新提交的行为不同。
比较、合并、历史是三个问题
| 判断 | 能说明什么 | 不能直接推出什么 |
|---|---|---|
git diff A B 没有输出 | 两个提交的文件快照一致 | 两个提交的 SHA 或祖先链相同 |
git merge-base --is-ancestor A B 成功 | A 在 B 的祖先链中 | 之后没有提交修改或撤销 A 的内容 |
| PR 已 squash / rebase 合入 | 变更以该方式进入 base | 原 feature 的全部 SHA 都已成为 base 的祖先 |
因此 squash 后继续复用旧 feature,可能在新 PR 中看到已处理过的提交或再次出现冲突。短期分支合并后,从最新 base 创建下一条 feature 通常更容易保持比较范围清晰。
# 同步、更新、删除与撤销
先分清同步方向
| 操作/按钮 | Git 对应思路 | 方向及影响 | 官方文档 |
|---|---|---|---|
| Fetch | git fetch origin | 远端 → 本地对象及远程跟踪引用;不自动合并当前分支 | git-fetch (opens new window) |
| Pull | git pull --ff-only 或显式选择 merge / rebase | fetch 后整合到当前本地分支;具体方式取决于参数与配置 | git-pull (opens new window) |
| Push | git push origin feature | 本地 → 远端;受非快进检查及仓库规则约束 | git-push (opens new window) |
| PR 的 Update branch | 在 feature 上 merge base,或把 feature rebase 到 base | base → head,目的是更新待审分支;不是把 PR 合入 base | Keeping a PR in sync (opens new window) |
| Fork 的 Sync fork | 获取 upstream 并整合到 fork 的对应分支 | 原仓库 → fork;本地 clone 仍需另行 fetch / pull | Syncing a fork (opens new window) |
区分删除引用与改变历史
| 操作 | Git 对应思路 | 实际效果 | 官方文档 |
|---|---|---|---|
| PR 合并后 Delete branch | git push origin --delete feature | 删除远程分支引用;不会反向撤销已合入 base 的提交,本地分支也不会自动删除 | git-push (opens new window) |
| Revert PR | 新增反向改动并通过新 PR 合入;普通提交可用 git revert SHA 理解 | 保留原历史,不是把 base 移回旧提交 | GitHub Reverting a PR (opens new window)、git-revert (opens new window) |
| Revert merge commit | git revert -m N MERGE_SHA,N 指定主线父提交 | 需要理解父提交方向,也会影响后续再次合并的判断;不能随意填 1 | git-revert (opens new window) |
| Reset / 强推 | reset 移动本地引用;强推尝试改变远端引用历史 | 与新增反向提交不同;共享分支不能把它当成 Revert 按钮的等价操作 | git-reset (opens new window)、git-push (opens new window) |
# 官方文档检索入口
| 需要查什么 | 优先查哪里 |
|---|---|
| 网页按钮、PR、Compare、权限和仓库规则 | GitHub Docs (opens new window);站内搜功能名,如 Comparing commits、Pull request merges |
| 命令参数、引用与范围的精确定义 | Git Reference (opens new window);本机 git help diff、git help merge、git help revisions |
| 分支、远程、对象模型的系统学习 | Pro Git 官方书 (opens new window);从 Git Basics、Git Branching 到 Git Internals |
| 将 GitHub 平台操作放到终端执行 | GitHub CLI Manual (opens new window);gh pr、gh repo 对应平台对象,不能与原生 Git 命令混为一谈 |
# workflows
命令行创建 PR、查看 CI 日志和下载检查报告,见 GitHub CLI(gh)工作流与 CI 排查。
# trigger workflow
官网是最全面的, 建议直接查看
https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows
# schedule
通过 schedule 出发 workflow, 更多内容可见trigger a workflow by schedule (opens new window)
POSIX cron 语法
POSIX cron 是一种用于调度任务的时间表达式语法, 它由五个字段组成, 分别表示分钟、小时、日期、月份和星期几
下面是每个字段的取值范围及其对应的含义:
- 分钟(0-59): 表示一小时中的哪一分钟触发任务
- 小时(0-23): 表示一天中的哪个小时触发任务
- 日期(1-31): 表示一个月中的哪一天触发任务
- 月份(1-12): 表示一年中的哪个月触发任务
- 星期几(0-7, 其中 0 和 7 都表示周日): 表示一周中的哪一天触发任务
使用这五个字段的组合, 我们可以创建出各种不同的时间表达式来调度任务。下面是一些示例:
* * * * *: 每分钟触发一次任务0 * * * *: 每小时的 0 分钟触发一次任务0 0 * * *: 每天的 0 点整触发一次任务0 0 * * 1: 每周一的 0 点整触发一次任务0 0 1 1 *: 每年的 1 月 1 日的 0 点整触发一次任务
通过指定这些时间表达式, 你可以在 GitHub Actions 中使用 POSIX cron 来定时执行你的工作流程
# Reuse workflows
coming soon
# workflow commands
# multiline strings
使用方式:
{name}<<{delimiter}
{value}
{delimiter}
2
3
示例:
steps:
- name: Set the value in bash
id: step_one
run: |
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
echo "JSON_RESPONSE<<$EOF" >> "$GITHUB_ENV"
curl https://example.com >> "$GITHUB_ENV"
echo "$EOF" >> "$GITHUB_ENV"
2
3
4
5
6
7
8
# other
# IDEA online
项目首页按., 会自动打开: https://github.dev/<username>/<project>/tree/<branch>。 就可以有一个简易的 vscode 打开, 对于简易的修改非常方便
# QQ 邮箱授权
qq 邮箱的授权码更多内容可见链接: SMTP/IMAP 服务 (opens new window)
IMAP/SMTP 设置方法
用户名/帐户: 你的 QQ 邮箱完整的地址
密码: 生成的授权码
电子邮件地址: 你的 QQ 邮箱的完整邮件地址
接收邮件服务器: imap.qq.com, 使用 SSL, 端口号 993
发送邮件服务器: smtp.qq.com, 使用 SSL, 端口号 465 或 587
2
3
4
5
6
7
8
9
10