美文网首页
『Git 干货』#3 远程仓库使用(简明)

『Git 干货』#3 远程仓库使用(简明)

作者: Hwcoder | 来源:发表于2021-10-20 09:27 被阅读0次

    访问博客查看 本文 最新内容,排版更美观ヾ(•ω•`)o 如有错误欢迎指出~

    Git 系列学习笔记:

    接上文,本文介绍了 Git 在远程仓库的使用,以及合作开发的简易教程。

    本文大部分内容参考了 RCY 同学的教程,部分参考了 廖雪峰教程-Git菜鸟教程-Git,以及 Git 官网文档 Git-Documentation

    远程的 Git

    尽管 Git 本身是分布式的,但我们通常需要一个服务器来同步、传递我们的本地仓库数据,处于一种「伪集中式」的状态。但服务器上的内容不一定是最新的内容,只是一个用于传递的中间态而已。

    因此有了一系列的相关网站,通常来说我们用以下两个:

    • GitHub:⼀个基于 Git 的代码托管服务平台,开源社区交流代码的重要网站,参考 https://www.github.com/
    • GitLab:类似 Git,有完善的管理界面和权限控制,一般用于在企业、学校等内部网络搭建 Git 私服,参考 https://www.gitlab.com/

    从代码的私有性上来看,GitLab 是一个更好的选择。但是对于开源项目而言,GitHub 依然是代码托管的首选。

    鉴权

    在使用远程仓库之前,我们要先解决鉴权问题:云服务器需要知道你是否有权力访问这个仓库。

    鉴权有两种方法:

    1. 用户名 + 密码
    2. SSH 密钥对

    通常来说,使用密钥对比用户名密码更安全,这里不介绍相关原理,先简单讲下密钥对的配置。

    $ ssh-keygen -t rsa -C "631670924@qq.com" # 获取 SSH Key
    # 参数 -t 代表 type 设置,默认使用 SSH2d 的 rsa
    # 参数 -C 代表 Comment 设置,提供一个新注释
    # 其他参数用于生成更多功能的密钥,请自行查阅相关网站
    $ cat ~/.ssh/id_rsa.pub # 代表 concatenate,用于连接文件并打印到标准输出
    

    密钥对生成时会需要设置密码,但由于其本身就是加密的,密码只是为了适应更特殊的情景,这里可以直接回车跳过

    cat 命令会把公钥放到标准输出,复制到 GitHub 或 GitLab 上的对应位置即可。注意 id_rsa.pub 是可以公开的,而私钥存储在 id_rsa 文件,用于在每次操作远程仓库时与公钥进行匹配。

    克隆远程仓库

    远程仓库通常是由 clone 或 push 开始的,这里假设我们已经在 GitHub 上有了一个仓库,现在要将其克隆到本地。

    常见的克隆方法有两种:

    $ git clone <仓库的 HTTPS URL 地址>
    $ git clone <仓库的 SSH Key>
    

    前者不需要配置 SSH 也能完成,但是每次操作远程仓库都需要用户名和密码。后者是在配置完 SSH Key 后使用的,可以省去填写用户名和密码的步骤,也能帮助你克隆私有仓库。如果前面生成密钥对时设置了密码,这里就需要输入。

    此外,如果要克隆一个较大的仓库(仓库有很长的提交历史或大量二进制文件),常用的一个方法是限制 clone 的深度,只克隆最新的版本:

    $ git clone --depth=1 https://github.com/hewei2001/HITSZ-OpenCS
    

    远程分支

    现在对本地仓库查看 log,会发现除了 HEAD、main 这些原有的指针,还多了 origin/ 的字样,这是远程仓库分支的默认标识。

    这些远程分支与本地分支并存,反映了远程仓库在你上次和它「通信」时的状态,可以用前面的命令查看:

    $ git branch --all  # 参数 --all 代表所有分支,包括远程分支
    

    同样,也可以用 git checkout 切换到任意一个远程分支,只需要加上 origin/

    远程分支有一个特别的属性,在你检出时自动进入一个「分离 HEAD 状态」。在此状态下,不会有 HEAD -> origin/main -> node,而是直接有 HEAD -> node。这样做是因为 Git 不能直接在远程分支上进行操作,必须在本地操作后将 main 分支同步到远程,origin/main 才会发生变动。

    一旦发生了分离 HEAD 并提交修改,下次 push 时本地仓库将与远程仓库发生分歧,可能需要 Rebase 操作。

    在实际操作中,我们只需要检出到本地分支即可。当克隆一个仓库时,它通常会自动地创建一个跟踪 origin/main 的 main 分支。

    但如果一个远程分支 origin/test 在本地没有对应分支 test,我们却要检出 test,该命令会自动复制一个「跟踪分支」作为本地分支。

    本地与远程的交互

    下载 (Fetch)

    所谓的拉取通常可由两个操作来完成,初学者往往分不清两个操作究竟分别做了什么:

    $ git fetch  # 下载--下载远程分⽀到本地
    $ git pull   # 拉取--使本地分支与远程分支同步
    

    下面我们用一组图来解释 git fetch 操作:

    使用fetch前的仓库

    在这个例子中,虚线的结点代表远程仓库,它有两个我们本地仓库中没有的提交。而此时本地的远程分支 origin/main 还停留在你上次和它「通信」时的状态。如果此时使用 git fetch,则会出现:

    使用fetch后的仓库

    可以发现,本地仓库缺失的结点 C2 和 C3 被下载到了本地仓库,同时远程分支 origin/main 也被更新,反映到了这一下载,但是本地分支 main 依旧不变!

    因此,我们可以知道:git fetch 并不会改变本地仓库的状态。它不会更新你的 main 分支,也不会修改你磁盘上原有的文件使其与远程「同步」,它只是将「同步」这一操作所需要的数据都下载下来了。

    拉取 (Pull)

    那么,如何将这些数据真正完成「同步」呢?实际上有很多方法,上一节提到的 git merge origin/maingit rebase origin/main 等命令都可实现。

    实际上,由于先抓取更新再合并到本地分支这个流程很常用,因此 Git 提供了一个专门的命令来完成这两个操作。它就是我们要讲的 git pull

    这里我们先用一个分叉的例子来演示:

    使用pull前的仓库

    分叉 (Branch Diverged) 是由于不同开发者进行了时空错位的提交导致的。观察该图,我们可以猜测本地开发者是在 C1 时刻克隆的仓库,并再克隆后完成了一次 C2 提交,而与此同时,另一个开发者在远程完成了 C3 提交。

    此时如果想提交代码到远程,会提示 main 分支发生了分歧——因为远程仓库包含了本地尚不存在的结点,无法通过快速前移直接合并。Git 会提示你先将远程仓库拉取到本地解决分叉。

    使用pull后的仓库

    可以看到,git pull 其实就是 git fetchgit merge origin/main 两个指令的缩写。

    需要注意的是,如果此时 C2 和 C3 有冲突,则 git pull 不完全执行,需要手动维护后再 merge,这个维护的过程对另一开发者是不可见的。

    在实际操作中,我们偶尔会用 git fetchgit rebase origin/main 来避免一个不必要的合并。

    推送 (Push)

    相比于拉取,推送操作就尤为简单:

    $ git push
    

    如果无分歧发生,远程仓库将会接收本地新增的结点,而远程仓库中的 main 也会指向本地仓库中 main 的位置。此外,本地仓库的远程分支 origin/main,会在这次「通信」的过程中,也移动到本地 main 的位置。

    再回顾一下上面的分叉的例子,如果我们已经 merge 解决了冲突,这时再用 git push 则会有:

    分叉的第一种解决方案

    可以看到,远程仓库清楚地记录了这次 merge 的历程!

    而如果我们用 git fetchgit rebase origin/main 的组合(虽然很繁琐),但是远程仓库历史将变得十分整洁,并且能清楚地体现提交顺序

    分叉的第二种解决方案

    Push 的参数

    上文介绍了最简单的 Push 命令,但这个命令看似简单,实际上却是最「模糊」的,很容易出现报错。完整的 Push 指令应该是:

    $ git push <远程仓库名> <本地分支名>:<远程分支名>  # 冒号前后无空格
    # 例如:
    $ git push origin main:test  # 将本地 mian 推送到 origin 的 test
    

    这个命令显式地指出了远程仓库名,如果只关联了一个远程,这个参数就可以缺省。但是如果关联了多个仓库(如 GitHub 和 Gitee),则必须用这个参数指明。

    此外,它还指出了本地分支及其映射的上游分支,该命令可以用于不同名分支的推送,但实际工程中我们倾向于用本地远程同名分支(避免分歧),因此命令可以简化为:

    $ git push origin test  # 将本地 test 推送到 origin 的 test
    

    但是,如果远程仓库 origin 没有一个同名的 test 分支,又会报错,此时我们需要为 test 建立上游分支,并将其跟踪绑定

    $ git push --set-upstream origin test # 推送同时绑定上游分支
    $ git push -u origin test  # 参数 -u 为上述命令的缩写
    

    注意,一次 Push 默认只推送一个分支,因此如果不加分支名,会默认推送当前 HEAD 所在的分支。因此指令还可以逐步缺省:

    $ git push -u origin  # 表示将 当前分支 推送并绑定 同名上游分支
    $ git push origin  # 表示将 当前分支 推送 到 同名上游分支(需先绑定)
    $ git push  # 表示将 当前分支 推送 到 <默认远程>/同名分支(需先绑定)
    

    最后一条指令就是我们最早提及的推送命令,它需要满足:

    1. 只有一个远程仓库;或者有多个仓库,但用 -u 绑定其中一个。
    2. 只有一条分支;或者有多条分支,但当前分支与上游分支同名并绑定。

    相关文章

      网友评论

          本文标题:『Git 干货』#3 远程仓库使用(简明)

          本文链接:https://www.haomeiwen.com/subject/pwxtaltx.html