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

访问博客查看 本文 最新内容,排版更美观ヾ(•ω•`)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. 只有一条分支;或者有多条分支,但当前分支与上游分支同名并绑定。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,110评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,443评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,474评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,881评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,902评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,698评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,418评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,332评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,796评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,968评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,110评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,792评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,455评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,003评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,130评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,348评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,047评论 2 355

推荐阅读更多精彩内容