Lite Git (V) - Remote

Lite Git (V) - Remote

前言

本专栏名为Lite Git。主要想与Pro Git对应,后者为Git官方指南,有兴趣,或者想了解更多细节的同学,请移步官网下载PDF版

本专栏主要为了让初出茅庐的同学更快、更合理地掌握Git的基本运用;

同时,本专栏也会介绍一下作为Android开发人员关心的:repo的运用;

本篇是该专栏的第五篇,主要介绍Git的远端与本地的概念,属于比较重要的一节,刚开始了解Git的同学强烈建议了解一下;

远端(Remote)仓库

何为远端仓库?

顾名思义,是相对于本地仓库而言的:远端仓库指本地仓库设置的,可进行进度同步的目标仓库;

本地仓库与远端仓库的同步通过git pull/git fetch,git push完成,示意图如下:
在这里插入图片描述

这里延用Working Directory的概念作为本地仓库,因为本地仓库并不包含本地工作区和暂存区

这是非常重要的一点,理解了这里,才可以理解为什么git fetchgit push都不涉及工作区、暂存区的修改了;(git pull本质上是git fetch与其他指令的组合,因此会操作暂存区、工作区。但其git fetch部分也是不涉及工作区、暂存区的修改,特此注明)

远端仓库的查看

在包含本地仓库的目录下,使用git remotegit remote -v命令即可查看;

还是以demo_client仓库为例:

# 显示当前仓库设定的所有远端仓库
ryan ~/git_demo/demo_client (master) $ git remote
origin
# 显示当前仓库设定的所有远端仓库,及其路径
ryan ~/git_demo/demo_client (master) $ git remote -v
origin  /home/ryan/git_demo/demo_bare (fetch)
origin  /home/ryan/git_demo/demo_bare (push)

这里再强调一点,所谓远端,是相对于本地的概念,并不一定是本机以外的路径,比如此例就是本机内另外一个路径的裸仓库为远端

此外,我们可以通过git remote addgit remote remove指令对当前本地仓库设定的远端仓库进行修改;

# 显示当前仓库设定的所有远端仓库,及其路径
ryan ~/git_demo/demo_client (master) $ git remote -v
origin  /home/ryan/git_demo/demo_bare (fetch)
origin  /home/ryan/git_demo/demo_bare (push)
# 删除名为origin的远端仓库引用
ryan ~/git_demo/demo_client (master) $ git remote remove origin
# 再次查看已设定的远端仓库,内容为空
ryan ~/git_demo/demo_client (master) $ git remote -v
ryan ~/git_demo/demo_client (master) $ git remote
# 添加名为new_origin 的远端仓库引用,地址为/home/ryan/git_demo/demo_bare
ryan ~/git_demo/demo_client (master) $ git remote add new_origin /home/ryan/git_demo/demo_bare
# 再次查看已设定的远端仓库,出现new_origin,且对应路径为设定的路径
ryan ~/git_demo/demo_client (master) $ git remote
new_origin
ryan ~/git_demo/demo_client (master) $ git remote -v
new_origin      /home/ryan/git_demo/demo_bare (fetch)
new_origin      /home/ryan/git_demo/demo_bare (push)

或许有人有疑问,如果在git remote add时,我输入了一个不合法的路径,会发生什么,答案是,什么报错都不会出现:

# 添加一个名为wrong_origin 的远端仓库引用,指向http://www.baidu.com,后者显然不是一个git仓库
ryan ~/git_demo/demo_client (master) $ git remote add wrong_origin http://www.baidu.com
# 再次查看已设定的远端仓库,发现可以添加成功
ryan ~/git_demo/demo_client (master) $ git remote
new_origin
wrong_origin
ryan ~/git_demo/demo_client (master) $ git remote -v
new_origin      /home/ryan/git_demo/demo_bare (fetch)
new_origin      /home/ryan/git_demo/demo_bare (push)
wrong_origin    http://www.baidu.com (fetch)
wrong_origin    http://www.baidu.com (push)

因此,为了校验我们添加的远端仓库是否可及(是否是合法的git仓库,且权限足够),我们需要在git remote add以后,执行git fetch来检验:

# 拉取名为new_origin的远端仓库的进度,可以正常拉去,并发现有dev与master两个分支
ryan ~/git_demo/demo_client (master) $ git fetch new_origin
From /home/ryan/git_demo/demo_bare
 * [new branch]      dev        -> new_origin/dev
 * [new branch]      master     -> new_origin/master
# 拉取名为wrong_origin的远端仓库,发现未能在对应路径上找到git仓库,即表明路径不合法
ryan ~/git_demo/demo_client (master) $ git fetch wrong_origin
fatal: repository 'http://www.baidu.com/' not found
# 故将其删除
ryan ~/git_demo/demo_client (master) $ git remote remove wrong_origin

此外,通过上面一个例子,我们也不难得出一个结论:本地仓库与远端仓库的关系设定是弱绑定的,添加时甚至不会进行合法性校验。并且,在设定好远端仓库后,两者并不会立即同步,需要手动调用git fetch/git pull/git push完成同步;

远端仓库的进度

既然远端仓库与本地仓库的进度不会实时同步,那么我们如何来确定两者的进度差异呢?答案仍然是git statusgit log

这部分对初学者来说比较难,为了方便理解,我们引入一个之前有展示,但是没有介绍的功能:git配置文件中的别名

所谓别名,就是为了简化而将一整串命令通过一个词来代替的功能,例如我们常用的git status,通过如下设置以后,我就可以通过git st这一剪短的指令来完成git status的调用;

同时,我们引入一个带树状结构的git log命令变体,这对于我们后续理解git的树状结构有很大的帮助:

# 文件路径:~/.gitconfig
...
[alias]
		st   = status
		...
        lg   = log --pretty=format:\"%C(yellow)%h %C(red)%d %C(white)%s  %C(blue)%an/%C(blue)%cn  %C(magenta)%ad/%C(magenta)%cd%C(reset)\" --graph --color=always --date=iso
        ...
...

设置完后我们验证一下:

# git status与git st结果一致
ryan ~/git_demo/demo_client (master) $ git status
On branch master
nothing to commit, working tree clean
ryan ~/git_demo/demo_client (master) $ git st
On branch master
nothing to commit, working tree clean

# git lg通过每行的*来显示树状结构,由于当前仓库没有分叉,因此没有体现,后面遇到会再提及一下
ryan ~/git_demo/demo_client (master) $ git lg
* 7a0a4ff  (HEAD -> master) [demo_client]update FileB  Ryan_ZHENG/Ryan_ZHENG  2021-10-28 13:23:30 +0800/2021-10-28 13:23:30 +0800
* 91a45d2  (new_origin/master) [demo_client]add FileA FileB FileC FileD FileE  Ryan_ZHENG/Ryan_ZHENG  2021-10-28 10:57:51 +0800/2021-10-28 10:57:51 +0800
* 0b64004  [demo_client]delete FileA  Ryan_ZHENG/Ryan_ZHENG  2021-10-27 14:19:08 +0800/2021-10-27 14:19:08 +0800
* 0dbaef0  [demo_client]add FileA  Ryan_ZHENG/Ryan_ZHENG  2021-10-27 13:58:48 +0800/2021-10-27 13:58:48 +0800

上面例子中,我们发现git lg的结果中有这么几个字段:

  • (HEAD -> master) 表示当前本地仓库的HEAD指向master分支;
  • (new_origin/master) 表示当前设定的名为new_origin的远端仓库引用,截至目前的进度在91a45d2这笔提交上;

这里是初学者不容易理解的地方:

  • (new_origin/master)这种[远端仓库名/分支名]的结构,表示远端仓库的这个分支,在当前状态下的本地仓库记录的进度节点;
    注意:这里强调当前状态下的本地仓库记录的进度节点 ,是因为上面讲的”本地仓库与远端仓库的同步不是实施的,因此从本地仓库通过git lg查看的,只能是从上次git fetch/git pull后同步的节点,不代表当前远端仓库的真实节点;
  • master这种纯[分支名]的标记,表示本地仓库的这个分支的进度节点;
  • HEAD -> master这种[HEAD -> 分支名]的结构,表示当前HEAD指向的本地分支名;

理解了上面的信息,我们来看这个现象:

HEAD指向的master分支,即本地当前所处的分支,是领先于远端new_origin的master分支的;

这是因为上一节我们分别在demo_clientdemo_client_2仓库对FileB进行了不同的修改后,通过git commit提交进了本地仓库,但demo_client_2将提交推送到了远端仓库的dev分支,而demo_client未执行git push来将其推送至远端仓库;那么我们现在来进行提交:

# 由于我们修改了远端仓库的引用,因此这里不再是origin,而是新的远端仓库的名称new_origin
# 由于我们推送的仍是master分支的进度,那么第二个参数不变
ryan ~/git_demo/demo_client (master) $ git push new_origin master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 6 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 301 bytes | 301.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To /home/ryan/git_demo/demo_bare
   91a45d2..7a0a4ff  master -> master
# 查看当前分支的提交历史树,发现HEAD->master与new_origin/master完成了同步;
ryan ~/git_demo/demo_client (master) $ git lg
* 7a0a4ff  (HEAD -> master, new_origin/master) [demo_client]update FileB  Ryan_ZHENG/Ryan_ZHENG  2021-10-28 13:23:30 +0800/2021-10-28 13:23:30 +0800
* 91a45d2  [demo_client]add FileA FileB FileC FileD FileE  Ryan_ZHENG/Ryan_ZHENG  2021-10-28 10:57:51 +0800/2021-10-28 10:57:51 +0800
* 0b64004  [demo_client]delete FileA  Ryan_ZHENG/Ryan_ZHENG  2021-10-27 14:19:08 +0800/2021-10-27 14:19:08 +0800
* 0dbaef0  [demo_client]add FileA  Ryan_ZHENG/Ryan_ZHENG  2021-10-27 13:58:48 +0800/2021-10-27 13:58:48 +0800

本地仓库与远端仓库引用的绑定

也许你在其他地方见过,git pullgit push不带任何参数就完成了远端仓库与本地仓库的同步,而此时如果你在demo_client仓库下输入git pull,会发现如下报错:

ryan ~/git_demo/demo_client (master) $ git pull
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.

    git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=new_origin/<branch> master

原因是我们在创建新的名为new_origin的远端仓库时,并未指定本地的任何分支与之对应,因此无参的git pull不知道该同步哪个分支的进度。

按照提示,我们要么使用git pull <remote> <branch>这种完整指令,要么将本地一个分支的上游设置为远端的对应分支;

比如我们希望本地仓库的master分支上游为new_origin的master分支(即master分支进度默认与new_origin/master同步)

# 设置本地master分支自动追踪远端仓库new_origin的master分支
ryan ~/git_demo/demo_client (master) $ git branch --set-upstream-to=new_origin/master master
Branch 'master' set up to track remote branch 'master' from 'new_origin'.
# 再次执行git pull,无报错
ryan ~/git_demo/demo_client (master) $ git pull
Already up to date.
# git push同理,无报错
ryan ~/git_demo/demo_client (master) $ git push
Everything up-to-date

由于此处本地仓库的master分支已经与远端分支new_origin/master进度一致,因此此处没有任何同步的行为,直接显示up to date

总结

远端仓库与本地仓库之间的关系具有如下特点:

  1. 远端仓库的概念是相对于本地仓库的,并不一定存在于本机磁盘以外;
  2. git remote -v可以查看当前本地仓库设定的远端仓库引用信息;
  3. git remote add/git remote remove可以添加、删除远端仓库引用,但git remote add指令并不会验证其添加的远端仓库引用是否合法,需要手动调用git fetch验证;
  4. 并非实时同步,需要手动调用git fetch/git pull/git push完成同步;
  5. 通过git branch --set-upstream-to=<remote>/<remote_branch> <local_branch>可以为本地分支与远端分支建立追踪关系,使后续git pullgit push命令无需追加额外参数;(学习过程中建议使用完整指令,以加深理解)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值