简介:GitHub是全球流行的代码托管与开发者协作平台,依托Git提供分布式版本控制、云端仓库、历史版本管理及团队协作能力。这份PDF教程聚焦GitHub基础实操,面向刚接触版本控制的新手开发者,旨在解决代码版本混乱、多人协作流程不清晰等问题。教程从注册账户、创建仓库开始,逐步演示使用Git命令行或GitHub Desktop克隆仓库、添加并提交文件、编写描述性提交说明,再讲解创建分支进行独立开发、发起与审核合并请求,最终将分支合入主分支的完整流程。除基础操作外,文档还覆盖仓库问题追踪、团队讨论、探索开源项目并贡献代码的常见方式,读者按照步骤实际操作,可形成从本地开发到远程协作的完整闭环。资源仅含1个PDF文件,压缩包整体91KB,内容精炼、便于随时查阅;目前已有3458人学习下载,适合编程初学者、在校学生与需要规范代码管理的工程师学习使用。
1. GitHub 使用教程到底在解决什么问题
从零开始用 GitHub,卡住的往往不是代码,而是流程:账号怎么配,密钥要不要生成,克隆和下载到底有什么区别,提交完之后为什么远程仓库纹丝不动。GitHub 使用教程要解决的正是这些最日常却最容易被跳过的问题。它适合两类人:一类是刚写完第一个项目、想把代码放进 GitHub 存下来并写进简历的新手;另一类是用过 GitHub 但每次全靠搜索救急、对分支和 Pull Request 只有模糊印象的半熟手。下面这份操作路线,从账号配置一路走到协作闭环,再把深度使用时的踩坑和排查手段一并讲清楚,照着敲一遍就能跑通。
2. 从账号到首次 push:SSH 密钥与最小提交闭环
2.1 git 全局配置:先告诉 Git“你是谁”
GitHub 使用教程里最容易跳过的一步,是git config。很多新人直接开始建仓库,commit 完之后发现提交者信息是一串乱码,甚至 push 的时候因为身份不一致被拒绝。其实只要在终端里跑三条命令,后续所有仓库都会带上正确身份。
git config --global user.name "你的名字" git config --global user.email "you@example.com" git config --global init.defaultBranch main git config --global pull.ff only第一条把用户名写进~/.gitconfig,第二条填邮箱,这两项会作为每个 commit 的作者信息。user.name不要求跟 GitHub 账号一致,但建议一致,方便别人在 GitHub 上通过 commit 头像点进你的主页。init.defaultBranch main是让本地的git init默认生成 main 分支而不是老旧的 master,和 GitHub 新建仓库的默认分支保持一致,省掉后面git branch -M main的麻烦。pull.ff only是我比较偏好的一个设置:它让git pull在执行合并时只接受快进合并,当本地领先远程时会直接报错而不是自动生成一个 merge 提交,对新手来说历史更干净,出问题也能一眼看懂。
2.2 SSH 密钥:生成、注册到 GitHub 并验证
在 GitHub 上认证有两种主流方式:HTTPS 加 Personal Access Token,以及 SSH 密钥。我一般推荐 SSH,因为配置一次之后,push 和 pull 都不需要再输入任何密码。生成密钥用这条命令:
ssh-keygen -t ed25519 -C "you@example.com" -f ~/.ssh/github_ed25519-t ed25519指定使用 Ed25519 算法,比传统的 RSA 短且安全性更高,GitHub 也支持。-C是注释,建议填你的邮箱,方便日后辨认这把钥匙属于谁。-f指定生成文件的位置和名字,按你的习惯改就行。执行后会提示输入 passphrase,直接回车表示不设置,后续使用更方便;如果在意安全,也可以设一个,每次 push 时输入一次。
密钥生成后,需要让本机 SSH 客户端知道“访问 github.com 时用这把钥匙”。在~/.ssh/config文件里加一段:
Host github.com HostName github.com User git IdentityFile ~/.ssh/github_ed25519 IdentitiesOnly yesIdentitiesOnly yes这个参数很关键。如果你的电脑上有多个密钥,SSH 默认会轮询所有密钥,GitHub 只要发现其中任意一把不匹配就会拒绝连接。加上这行之后,SSH 只会提交你指定的那把,不会乱试。
然后把公钥粘贴到 GitHub 网页:进入 Settings → SSH and GPG keys → New SSH key,把~/.ssh/github_ed25519.pub文件里的内容整段复制进去。最后验证连通性:
ssh -T git@github.com第一次执行会提示确认指纹,输入yes回车。如果配置成功,终端会输出Hi 用户名! You've successfully authenticated, but GitHub does not provide shell access.看到这句话,说明 SSH 通道已经通了,后面所有仓库操作都不需要再输入 GitHub 密码。
2.3 用命令行走通首次 push
我经常遇到的情况是:网页上已经点了一个 New repository,却不知道怎么把本地代码推上去。其实完全不需要图形工具,四步命令就够了。
mkdir github-demo && cd github-demo git init git branch -M main git remote add origin git@github.com:你的用户名/github-demo.git echo "# github-demo" > README.md git add README.md git commit -m "docs: init readme" git push -u origin main逐条说:git init在当前目录生成.git元数据目录,把它变成一个本地仓库;git branch -M main强制把当前分支改名成 main,因为新安装的 git 可能还在用 master,而 GitHub 新仓库默认分支名是 main,两边不同名会导致 push 失败。git remote add origin把远程仓库地址起了一个别名origin,之后 push 只写origin main就行。git add把 README 文件加入暂存区,git commit -m生成一条提交。最后git push -u origin main推到远程,-u是--set-upstream的简写,把本地 main 和远程 main 绑定,之后直接敲git push或git pull就能同步。
这里有一个高概率踩坑点:如果你创建远程仓库时勾选了“Add a README file”或“.gitignore”,远程仓库就多了一个本地没有的提交。推送时 git 会拒绝,提示fetch first。正确做法是:
git pull origin main --rebase git push origin main用--rebase拉取,会把远端的初始提交接到你本地提交之前,使历史是一条直线。这也是我第一次带新人时最常帮他们处理的错误。
3. 日常协作流程:clone、分支操作与 Pull Request 前的自查
3.1 Clone 一个仓库:HTTPS 和 SSH 怎么选
把别人的开源项目复制到本地,叫 clone。GitHub 上每个仓库首页的绿色 Code 按钮里会同时给出 HTTPS 和 SSH 两个地址。很多教程只写其中一个,导致新人复制错了适配自己的地址,忙活半天还是认证失败。
git clone git@github.com:用户名/仓库名.git用 SSH 地址的前提是,你已经按 2.2 的流程配置过密钥。好处是一劳永逸,clone、push 都不会再要密码。HTTPS 地址形式是https://github.com/用户名/仓库名.git,首次 push 时会要求输入 GitHub 用户名和 Personal Access Token,Token 的创建入口在 Settings → Developer settings → Personal access tokens,勾选repo和workflow权限后生成一串字符串,复制一次后就看不到了。
clone 命令本身有两个参数值得新手记住:
git clone git@github.com:owner/repo.git my-repo仓库名后面跟的第一个参数是本地目录名,不写默认用远程仓库名。遇到仓库特别大、或者你只是想读代码的场景,在后面加--depth 1只拉最新一条提交,速度会快很多,这个留在第 4 章细讲。
3.2 分支操作:从建分支到推送的完整链路
分支是 GitHub 协作的核心,也是最容易被理解成“玄学”的部分。实际上分支就是一条独立的提交线,你在里面随便改,不会影响 main,等改完再合并回去。
我一般建议新人养成这样的习惯:每次做新功能或改 bug,不要直接在 main 上改,先开一个名字清晰的分支。
git checkout -b feat/add-logincheckout -b意思是创建分支并切换过去,feat/add-login是我常用的命名风格:feat表示功能性改动,fix表示修复,docs表示文档。在这个分支里改完代码后:
git status git diff git add docs/login.md git commit -m "docs: add login guide" git push -u origin feat/add-logingit status查看当前改了哪些文件,git diff逐行看改动内容。我见过太多人 commit 之后才发现把调试用的临时文件也提交了,就是因为跳过了 diff。git add只加入指定文件,比git add .更可控。git push -u origin feat/add-login推送新分支到远程,-u同样建立上下游关联。
推送成功后,GitHub 页面会自动出现一个黄色横幅,上面写着Compare & pull request,点击进入 PR 创建页。
3.3 Pull Request 前要做完的三步自查
把分支代码合进 main,在 GitHub 上不是直接点到即止,而是通过 Pull Request 让别人 review。但很多新人刚点完 Compare 就提交 PR,结果 CI 挂掉、冲突一片,最后只能憋着一个 rebase 收场。我自己的流程是提交前先做三步自查。
第一步,把 main 的最新代码同步进当前分支:
git checkout main git pull origin main --ff-only git checkout feat/add-login git rebase maingit pull origin main --ff-only用快进方式拉取,如果本地 main 有分叉会直接报错,防止自动产生 merge 提交。回到功能分支后执行git rebase main,把当前分支的提交“重放”到 main 的最新提交之后。这样 PR 里就不会有历史分叉,diff 也更清晰。
第二步,检查差异范围:
git log --oneline main..HEAD git diff main...HEAD --stat第一条列出当前分支比 main 多出的提交,第二条看差异涉及哪些文件。如果出现不该改的文件,赶紧在推送前用git restore --staged撤掉。
第三步,rebasing 之后推送时要小心:
git push --force-with-lease origin feat/add-loginrebase 会改写提交哈希,普通 push 会被拒绝。--force-with-lease是一个比--force安全的强制推送:如果远程分支在这期间被别人推进过,它会拒绝覆盖,防止把别人的提交弄丢。PR 描述不用写长篇大论,把“改动背景、改动范围、验证方式、关联 issue”四块写清楚就够了。
4. 仓库下载与代码拉取:浅克隆、稀疏检出和 ZIP 兜底
4.1 为什么 git clone 有时候“卡死”
不少教程只告诉你git clone会把整个仓库拉下来,却不说它默认的行为是拉取全部历史提交和每个版本里所有的文件。如果仓库本身就大,比如包含视频、PDF、训练数据集,或者作者把编译好的二进制文件直接提交进了历史,clone 就会慢得让人以为电脑坏了,甚至时不时报RPC failed。
这时候别急着怀疑 GitHub 本身不稳定,先认清一个事实:git clone拉的是“仓库历史”,不是“当前代码”。网页上那个绿色 Code 按钮里的Download ZIP,拉的是“当前分支最新文件快照”,不包含任何历史。理解了这个区别,下载问题就解决了一半。
4.2 只拉最近的历史:浅克隆与按需加深
如果只需要看代码、编译运行,或者把仓库弄进一个报告里做展示,用浅克隆就够了:
git clone --depth 1 https://github.com/octocat/Spoon-Knife.git--depth 1表示只保留最近 1 条提交记录,其他历史全部丢弃。这样下载量通常只有完整仓库的几十分之一,而且因为传输数据少,clone 失败的几率也大幅下降。
浅克隆之后如果你想逐步查看更多历史,可以用这两条命令按需加深:
git fetch --depth 100 git fetch --shallow-since=2024-01-01--depth 100表示加深到最近 100 条提交,--shallow-since表示取某个日期之后的所有提交。这两条执行完后,仓库会变厚一点,但比全量克隆还是小很多。注意:这些命令在浅克隆仓库里才有效,完整仓库里不能这么用。
4.3 稀疏检出:只拉你需要的目录
还有一种场景:仓库不一定是历史多,而是文件结构巨大,比如 monorepo 里同时放着前端、后端、移动端整套代码。你只关心其中某个目录,全量克隆纯属浪费。Git 提供了 sparse-checkout 功能,我之前用它在几秒钟内拉下了原本可能要下载半天的仓库。
git clone --filter=blob:none --no-checkout https://github.com/org/large-repo.git cd large-repo git sparse-checkout init --cone git sparse-checkout set packages/sdk docs git checkout main命令拆开看:--filter=blob:none让 git 先不下载文件内容,只下载提交结构和目录树;--no-checkout防止 clone 后立刻把所有文件检出;sparse-checkout init --cone启用 cone 模式,这是较新 Git 版本推荐的稀疏模式,语法简单;git sparse-checkout set packages/sdk docs把packages/sdk和docs两个目录加入白名单;最后git checkout main触发按需下载,git 只会拉取这两个目录对应的文件。
- 边界提醒:如果仓库结构很深或者目录名有空格,建议先用
git ls-tree -d HEAD确认真实的目录层级再写白名单。 - 参数适用性:
--filter需要在服务端支持的情况下工作,GitHub 支持,部分自建 GitLab 实例则可能不完整。
4.4 下载 ZIP 与 release 资产:什么时候放弃 clone
虽然 Git 官方建议尽量用 clone,但读代码型用户往往更适合用 ZIP。GitHub 仓库首页 Code 按钮里选Download ZIP,拿到的就是当前 main 分支的最新文件,不用配置任何密钥,也不用等历史下载。另一种常见情况是仓库发布区 Release 页面里的Source code (zip)和Source code (tar.gz)附件,这两种包不考虑 Git 历史,适合当作一次性资料。
| 方式 | 包含内容 | 携带历史 | 适合场景 |
|---|---|---|---|
| git clone | 全部提交和文件 | 是 | 开发协作、需要看历史 |
| git clone --depth 1 | 当前分支最近一次提交 | 否 | 读代码、跑项目 |
| Download ZIP | 当前分支最新快照 | 否 | 临时下载、交作业 |
| sparse-checkout | 指定目录及其历史 | 取决于参数 | monorepo 部分拉取 |
如果 clone 时确实报了网络类错误,比如RPC failed; curl 56,先做一次配置调整再重试:
git config --global http.version HTTP/1.1 git config --global http.postBuffer 524288000http.version HTTP/1.1是把 git 的 HTTP 协议版本从 HTTP/2 降为 HTTP/1.1,某些网络环境对 HTTP/2 的流式传输处理得并不好,降级后能绕开不少半路断连的问题。http.postBuffer把单次 POST 的数据缓冲上限调到 500 MB,解决大文件传输时缓冲区溢出导致的空响应。这两项改完不需要重启,直接重新 clone 即可。
5. GitHub 使用避坑:认证失败、大文件与误操作的后悔药
5.1 push 老是要密码,还可能直接 403
现象:运行git push时提示输入用户名和密码,输了之后又报Authentication failed。
原因:两种情况最常碰见。一是你没有配置 SSH 密钥,而远程地址用的是 HTTPS;GitHub 从 2021 年起已经取消了密码推送,必须用 Personal Access Token 当密码,你输密码自然失败。二是远程地址虽然是 SSH 形式,但系统中没有可用的密钥,或者~/.ssh/config里没有做 Host 映射。
解决:
git remote -v先看输出里的 URL 类型。如果是https://github.com/...,改成git@github.com:...:
git remote set-url origin git@github.com:你的用户名/仓库名.git改完后再执行ssh -T git@github.com验证密钥是否可用。如果提示Permission denied (publickey),说明密钥没注册到 GitHub 网页,或者IdentitiesOnly yes没配对。
5.2 超过 100MB 的大文件推不上,删了还照样报错
现象:git add一个超过 100 MB 的文件后执行git push,被远程仓库拒绝,报remote: error: File ... is 123.45 MB; this exceeds GitHub's file size limit of 100.00 MB。即使你把文件删掉再重新 commit,push 依然失败。
原因:git 的每一次提交都是一次快照,被加入过历史的大文件不会因为后续删除而消失,它仍然存在于 .git 对象库中,还会被 push 出去。GitHub 对单文件 100 MB 的限制是硬性的。
解决:如果文件只存在于最近一次提交,最简单是撤销提交重来。如果已经在历史里,就要重写历史。我常用 Git 官方推荐的git filter-repo:
pip install git-filter-repo git filter-repo --strip-blobs-bigger-than 10M --force--strip-blobs-bigger-than 10M表示把所有大于 10 MB 的文件对象从全部历史中移除,--force是因为它默认拒绝在非全新克隆的仓库里运行。执行后此文件从每个提交中被剥离,再重新添加远程并强制推送:
git remote add origin git@github.com:你的用户名/仓库名.git git push --force origin main注意:这会重写所有提交哈希,仓库里的所有协作者都需要重新 clone 或执行 fetch 重置本地分支。操作前务必做一份完整备份,这是最实用的一条“后悔药”。
5.3 Windows 上提交后,Linux 里 diff 一片红
现象:同一个文件在 Windows 下编辑提交,再拉到 macOS 或 Linux 上看 diff,每一行都显示被修改,状态栏提示几百个文件被改动。
原因:Windows 默认使用 CRLF(\r\n)作为行尾,Linux/macOS 使用 LF(\n)。git 的core.autocrlf设置不一致时,就会把行尾转换当成内容变更。整屏红色的 diff 让不少人初次相遇时以为代码损坏了。
解决:在仓库根目录放一个.gitattributes文件,把行尾策略写死:
# .gitattributes * text=auto *.sh text eol=lf *.bat text eol=crlf* text=auto让 git 根据每个文件猜测是文本还是二进制,文本文件统一转换;*.sh text eol=lf明确要求 shell 脚本始终用 LF,防止在 Windows 上被转成 CRLF 后无法在 Linux 执行;.bat文件则反向固定用 CRLF。加入该文件后,对已有文件执行一次归一化:
git add --renormalize . git commit -m "chore: normalize line endings"之后再跨平台拉取就不会再出现大面积假 diff 了。
5.4 误删分支或 reset 错了,代码能不能找回
现象:执行了git branch -D feature/temp想删掉一个不要的分支,或者在 rebase 冲突中git reset --hard到错误节点,然后发现一部分提交丢了,代码消失了。
原因:git 不会立刻物理删除对象,git branch -D删除的只是分支指向的引用,真正的 commit 对象还在 .git 对象库里,直到git gc清理。reflog 会记录 HEAD 过去每次移动位置,相当于 git 自己的“操作日志”,给了一颗后悔药。
解决:找回被删分支,先看 reflog:
git reflog输出类似:
b8a2fce HEAD@{0}: checkout: moving from main to recover-branch a3f9d21 HEAD@{1}: branch: Created from mainHEAD@{1}是删除前分支的位置,创建一个新分支指向它即可:
git branch recover-branch HEAD@{1} git checkout recover-branch如果是 reset 错了,同样通过 reflog 找到 reset 前最近一次提交的哈希,重新git reset --hard 哈希即可。我的习惯是:在删除分支或做任何--hard操作前,先git tag backup/今天日期打一个轻量备份标签,成本几乎为零,但能省下不少血泪经验。
5.5 密钥文件被 commit 进了仓库
现象:把.env、id_rsa或云厂商的 AccessKey 不小心 add 并 push 到了 GitHub 公开仓库,发现后立刻删除文件并重新提交一次,以为事情结束了。
原因:和历史大文件同理,误提交的密钥不会因为删除而消失,公开仓库中的历史任何时间都能被人翻出来。你删除后重新提交,泄露仍然存在。
解决:先别只跟仓库较劲。第一,立刻去对应的服务商平台撤销这个密钥(比如云厂商控制台里删除 AccessKey,GitHub 的 Personal Access Token 直接 Regenerate 或 Delete),这是最关键一步,因为密钥本身已经不属于你。第二,再重写仓库历史,把包含该密钥的提交清掉:
git filter-repo --replace-text <(echo "密钥字符串==>REDACTED")--replace-text会把历史所有出现该关键字的内容替换成REDACTED占位符。第三,如果仓库是公开的且历史里有过其他敏感信息,很多时候更稳妥的方案是直接删除仓库重建,或者用 GitHub 支持渠道申请删除缓存副本。密钥泄露这种事,认错要快,处理要狠。
6. 把 GitHub 当知识库用:搜索语法、项目评估和自动联动 issue
平时除了提代码,GitHub 还是我用来找开源方案和评估项目质量的第一入口。直接说三个我觉得最实用的操作习惯。
第一个是搜索语法。GitHub 搜索框支持限定符,比如stars:>500 language:python能筛出 Python 语言里 star 超过 500 的项目;topic:cli stars:>1000找特定主题的成熟工具。看某个库的文档时,path:docs in:readme 关键词能直接定位到文档相关位置。这个技巧在找低代码平台、组件库和 sample 项目时特别好用,比在搜索引擎里翻强得多。
第二个是项目评估。我不再只看 star 数,而是按一套固定动作快速判断:先看最近一次 commit 时间,超过半年没更新的仓库默认有维护风险;再看 LICENSE 文件是否存在,没有许可证的代码即使能用,商用和二次分发也存在法律隐患;最后去 issues 页面看看别人提的 bug 有没有人回应、有没有 close 记录。这套判断在选型阶段能省下不少后期维护成本。
第三个是我最想强调的小技巧:在 commit 或 PR 描述里写closes #12,GitHub 会自动在该 PR 合并时关闭对应 issue。这个联动让 issue 追踪完全自动化,团队成员不用手动去关标签。我现在的习惯是每个 PR 都带上关联 issue 编号,保持仓库的 issue 列表干净,也方便后来的人追溯某个改动是为了解决什么问题。这三个习惯帮我避免过很多次“选了 star 很高但已经坟头草三米高的仓库”的翻车,希望帮到你。
本文还有配套的精品资源,点击获取