远程仓库和 GitHub


本手册中到目前为止的每个仓库都存在于一个地方:你自己的机器上。这在你想要一个能在笔记本电脑损坏时幸存下来的备份、想从第二台计算机上继续开发项目,或想让其他人接触代码之前都没问题。你需要的是一个仓库副本存放在所有涉及的机器都能访问的地方。这个副本称为远程仓库,GitHub 是大多数开发人员放置它的地方。
什么是远程仓库(以及 GitHub 如何融入其中)
远程仓库 是托管在你自己机器以外某处的仓库副本,通常在 GitHub 上。当你克隆一个仓库时,Git 已经为你设置了一个,默认命名为 origin。运行 git remote -v(-v 参数要求显示 URL 以及名称)来查看它:
$ git remote -v
origin https://github.com/mara-chen/weather-app.git (fetch)
origin https://github.com/mara-chen/weather-app.git (push)Git 知道的每个远程仓库都列出两次,一次用于获取,一次用于推送,因为理论上这两个操作可能指向不同的地址。实际上它们几乎总是相同的。origin 是 Git 在克隆时自动分配的昵称。你可以重命名它或添加指向其他地方的第二个远程仓库,但你接触的几乎每个项目都会将其主要远程仓库称为 origin。
现在是重申一个容易混淆的区别的好时机:Git 和 GitHub 不是同一个东西。Git 是在你机器上运行的版本控制工具,无论你是否连接到任何东西都会记录提交。GitHub 是一个托管你仓库副本的网站,并为你提供推送和拉取的远程仓库。git remote、git push 和 git pull 是连接两者的命令:它们是你笔记本电脑上运行的 Git 与坐在 GitHub 服务器上的仓库通信的方式。
origin。随时运行 git remote -v 查看你的仓库知道的远程仓库。Git 和 GitHub 不是同一个东西:Git 是你机器上的工具,GitHub 是你的远程仓库通常所在的地方。早期明确这个区别可以避免之后许多困惑。 在何处托管你的远程仓库:GitHub 和替代方案
远程仓库所做的一切都是普通的 Git,这有一个早期值得了解的后果:另一端的主机是可互换的。对于 Git,每个主机都是你配置中的一个 URL,git push、git pull 和 git fetch 对所有主机的行为都相同。主机添加的东西在更高的一层:你的代码的网络视图、审查流程、问题跟踪和访问控制。以下是景观,权衡阐述明确:
- GitHub 是目前最大的,托管了绝大多数开源工作。它的优势是网络效应:你想贡献的项目已经在那里,教程假设使用它,雇主在上面寻找你的资料。权衡是它是一个封闭平台(由 Microsoft 拥有),你对它在 Git 托管之外的功能依赖越多,你与它的绑定就越紧密。
- GitLab 是最接近的完整替代方案,具有相同的核心功能但名称略有不同(拉取请求在那里称为"合并请求")。它的优势是自管理版本,你可以在自己的服务器上运行,这就是为什么保持代码内部的公司经常选择它。权衡是它捆绑了很多东西,平台的感觉可能比你来的代码托管更沉重。
- Bitbucket 是来自 Atlassian 的主机,构建用于与其项目跟踪和文档工具 Jira 和 Confluence 并肩放置。如果你的团队已经在这些工具中,它直接适配。在该生态系统之外,它在三大中拥有最小的社区,且几乎没有开源存在。
- Codeberg 是开源项目的非营利主机,运行在开源平台 Forgejo 上。吸引力在于没有公司拥有你的主机,且平台本身是开源的。权衡是规模:更少的集成,更小的社区,以及对开源而非私人团队工作的关注。
- 自托管 是所有这些的基础:在你控制的硬件上运行 Forgejo 或 Gitea(两者都是免费和开源的),或 GitLab 的自管理版本。你获得完全的控制和隐私;权衡是保持它运行成为你的工作。
本手册在其示例中使用 GitHub,因为它托管了大多数开源工作,是你最可能首次协作的地方。本章中的每个命令都无更改地转移到任何其他主机:交换 URL,日常循环保持不变。差异在于更高的一层,在每个网站审查和合并工作的网络界面中,这是下一章的 拉取请求流程 发挥作用的地方。
发送和获取你的工作:git push 和 git pull
配置了远程仓库后,两个命令覆盖了大部分日常工作。git push 将你的本地提交发送到远程仓库。git pull 拉取在其他地方做出的提交,并将它们合并到你所在的分支中。
$ git push origin main
Enumerating objects: 5, done.
Writing objects: 100% (3/3), 312 bytes | 312.00 KiB/s, done.
To https://github.com/mara-chen/weather-app.git
9f8e7d6..a1b2c3d main -> mainorigin 是远程仓库,main 是你发送的分支。最后一行是值得阅读的部分:它显示远程仓库上的 main 从一个提交移动到下一个。
拉取的工作方式相同,但反向:
$ git pull origin main
remote: Enumerating objects: 4, done.
Unpacking objects: 100% (4/4), done.
Updating a1b2c3d..b7c9e21
Fast-forward
src/index.js | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)这是与其他人在一个项目上协作的完整循环:在你开始之前拉取任何改变的内容,完成你自己的工作并提交它,将其推送回来。当你与任何人共享一个分支时,在推送之前总是拉取。跳过拉取,你的推送可能会落在你从未看过的提交之上,Git 将拒绝而不是冒险丢失某人的工作。
git push 将你的提交发送到远程仓库,git pull 拉取在其他地方做出的提交并将它们合并到你的分支中。在你开始工作之前拉取,在你完成时推送,你就与接触项目的任何人保持同步。跳过拉取是推送被拒绝的最常见原因。 git fetch 与 git pull
git pull 在一步中做两件事:它下载远程仓库上的任何改变,然后立即将那些改变合并到你所在的分支中。git fetch 只做第一部分。它下载新的提交,但从不将它们合并到你的分支中。你的当前分支和你的工作文件保持完全相同,直到你告诉 Git 合并或拉取。
这是几乎每个人至少会遇到一次的陷阱:运行 git fetch,在任何地方看不到可见的改变,并假设远程仓库上没有发生任何事情。有事情发生了:fetch 还没有接触你的工作分支。要查看下来的内容,请看本章前面的远程跟踪分支:git log origin/main 显示坐在远程仓库上的提交,还没有到达你的本地 main。当你准备好将它们引入时,git merge origin/main 进行合并,或 git pull 在一个命令中运行获取和那次合并。
git pull 下载新提交并在一步中将它们合并到你的分支。git fetch 只下载它们并更新 Git 对远程仓库位置的记忆;你的分支保持不动直到你合并。在获取后立即在你的文件中看不到改变是预期的,新提交在远程跟踪分支上等待。 这给你留下什么
推送、拉取和获取让你的提交到达共享远程仓库并返回,这覆盖了 Git 中日常协作所需的大部分内容。这里的一切都建立在 提交循环 上:你仍然首先在本地暂存和提交,远程仓库只改变这些提交可以传输的地方。下一部分是通过 GitHub 本身进行该协作,在它合并之前提出更改并进行审查。拉取请求流程 正好从这里开始。如果本章中的一个术语仍然感到不稳定,远程跟踪分支、refspec、上游,术语表 对每个都有清晰定义,而 什么是 Git 值得再看一眼,单独查看 Git 与 GitHub 的区别。

