美文网首页
14.Git 远程版本库

14.Git 远程版本库

作者: 一只奋斗的菜鸟 | 来源:发表于2023-09-26 14:17 被阅读0次

Git 作为分布式版本控制系统,每个人都可以在本地的版本库中随意创建分支和标签。如果多人协作时,问题就出现了。

思考以下几个问题

  1. 如何避免因用户把所有的本地分支都推送到共享版本库,从而造成共享版本库分支的混乱?

  2. 如何避免不同用户针对不同特性开发创建了相同名字的分支而造成分支名称的冲突?

  3. 如何避免用户随意在共享版本库中创建标签而导致标签名称上的混乱和冲突?

  4. 有没有办法在执行 fetch 和 push 操作时,不用输入长长的版本 URL ?

  5. 如果不带任何其他参数执行 git fetchgit pullgit push ,到底是和哪个远程版本库的哪个分支进行交互?

一、 远程分支介绍

之前介绍分支时,每个版本库只和一个远程共享版本库进行交互,实际上 Git 允许一个版本库和任意多的远程共享版本库进行交互。首先执行下面的命令,基于 hello-world.git 版本库再创建两个新的版本库。

origin1.png

现在共有三个共享版本库: hello-world.githello-user3.githello-user4.git ,先看看 hello-world 远程版本库中包含的分支有哪些:

origin2.png

共有三个分支,现在重新克隆一下该版本库到 user5/workspace 目录:

origin3.png

执行 git branch 命令查看一下本地分支:

origin4.png

发现只有一个 master 分支 ,远程版本库的其他分支在哪里呢?执行 git show-ref 命令可以看到全部的本地引用:

origin5.png

输出显示:有些引用以 refs/remotes/origin 为前缀,并且名称和远程版本库的分支名一一对应,这些引用实际上就是从远程版本库的分支复制过来的,称为远程分支。

通过 git branch 加上 -r 参数,能够查看远程分支,如果是 -a 参数,则能够查看本地和远程所有分支:

origin6.png

实际上,在从远程版本库中执行获取操作时,不是把远程版本库的分支原封不动地复制到本地版本库的分支中,而是复制到另外的命名空间 .git/refs/remotes/origin/ 下,这样从不同的远程版本库执行获取操作,因为命名空间的相互隔离,从而避免了分支在本地的相互覆盖。

至于为什么远程分支都有一个名为 origin/ 的前缀,原因就在于配置文件:

origin7.png

说明 :

  1. 第 1 行表示以 origin 为名注册了一个远程版本库。

  2. 第 2 行表示该远程版本库的地址。

  3. 第 3 行表示执行 git fetch orgin 操作时使用的默认引用表达式。该表达式以 + 号开头,含义是强制进行引用的替换,即使将进行的替换是非快进式的。引用表达式中使用了通配符,冒号左侧表示匹配通配符规则的所有远程版本库分支,右侧表示复制到本地的远程分支(refs/remotes/origin/)目录。

  4. 执行 git fetch origin 命令时,相当于执行了:git fetch origin +refs/heads/*:refs/remotes/origin/* ,将远程版本库所有的分支复制到本地的远程分支中。

注意:远程分支不是真正意义上的分支,是类似于标签一样的引用。如果针对远程分支执行 checkout 命令,会看到大段的警告,告诉我们处于分离头状态。实际上,除了以 refs/heads 为前缀的引用之外,检出任何其他引用,都将使工作区处于分离头状态。如果要对远程分支进行修改,就需要创建新的本地分支。

二、分支追踪

如果想在分支 helper/v1.x 上进行工作,那么需要基于该远程分支创建本地分支,远程分支可简写为: origin/helper/v1.x 。在 Git 较高版本(高于 1.6.6)时,可直接使用下面命令同时完成本地分支的创建和切换:git checkout helper/v1.x 。在低版本中或注册了多个远程版本库(可能存在多个同名的远程分支),就不能使用上面简洁的分支创建和切换命令了,需要通过如下命令来创建:

origin8.png

输出显示,已经切换到对应分支了,并且本地分支和远程分支建立跟踪了。此时的本地分支有下列特征:

  1. 检查工作区状态时,会显示本地分支和关联的远程分支提交之间的关系。

  2. 当执行 git pull 时,如果两者出现版本偏离的话,会和关联的远程分支进行合并(或者变基)。

  3. 当执行 git push 时,会推送到远程版本库的同名分支中。

下面进行操作演示:

  1. 先将本地 helper/v1.x 分支回退两个提交版本,再查看一下状态:
origin9.png

输出显示:本地分支落后于远程分支 origin/helper/v1.x 两个提交,并提示可以通过 git pull 来更新到最新的提交状态。

  1. 执行 git pull 命令,会自动与关联的远程分支进行合并,相当于找回了最新的两个提交:
origin10.png

三、基于本地分支创建另一个本地分支

基于本地分支创建另一个本地分支,是没有分支跟踪功能的,来演示一下:

  1. 从本地分支 helper/v1.x 创建新的本地分支 helper/v1.y
origin11.png

只有一行输出,看不到分支间建立跟踪的提示。

  1. helper/v1.y 分支回退两个版本,再查看一下状态:
origin12.png
  1. 执行 git pull 命令,会报错:
origin13.png

输出表示:当前分支并没有跟踪信息,需要指定要和哪个分支进行合并操作。可通过 git pull {remote} {branch} 的方式指定拉取远程的指定分支,或者通过 git branch --set-upstream-to=origin/{branch} helper/v1.y 命令进行远程分支的跟踪,再进行拉取操作。

  1. 再查看一下配置文件:
origin14.png

会发现 masterhelper/v1.x 都有配置信息,但是 helper/v1.y 并没有相关的配置。

四、基于本地分支创建另一个本地分支(具备跟踪)

如果希望在基于一个本地分支创建另一个本地分支时,建立分支间的跟踪功能,需要加上 --track 参数,具体演示一下:

  1. 先检出 helper/v1.x ,再删除之前的 helper/v1.y 分支。
origin15.png
  1. 通过 --track 参数重新创建分支。
origin16.png
  1. 查看一下配置文件,因为这里跟踪的是本地分支,所以 remote 中的远程版本库的名字为一个点。
origin17.png

五、注册新的版本库

名为 origin 的远程版本库是在克隆时就已经自动注册了,下面再注册一个新的远程版本库:

  1. e/git_study/repos/hello-user3.gitnew-remote 为名进行注册:git remote add new-remote file:///e/git_study/repos/hello-user3.git

  2. 查看一下配置文件:

origin18.png

可以看到配置的分支信息 , remote 默认都是 origin ,所以不加参数,直接运行 git fetch 命令,并不会从新注册的 new-remote 远程版本库中获取,需要指定远程版本库。

  1. 执行 git remote -v 命令,可以查看已经注册的远程版本库:
origin19.png
  1. new-remote 远程版本库进行获取,并查看一下远程分支:
origin20.png

可以看到在 new-remote 目录下的三个远程分支。

六、更改远程版本库的地址

如果远程版本库的地址改变了,怎么修改呢?第一种:直接打开 .git/config 文件修改。第二种:使用 git config 命令进行更改。第三种:用 git remote 命令:git remote set-url new-remote file:///e/git_study/repos/hello-user4.git

再观察一下远程版本库信息:

origin21.png

输出显示:每个远程版本库都有两个 URL 地址,分别是执行 git fetchgit push 命令时用到的,这就意味着两个地址是可以不一样的,通过加上 --push 参数可以单独设置推送地址,如下图:

origin22.png

当单独为远程推送设置 URL 后,配置文件的 remote 节点也会增加一条名为 pushurl 的配置,如下:

origin23.png

七、更改远程版本库的名称

将远程 new-remote 的名称修改为 user4

origin24.png

重命名之后,相应的远程分支的名称也会自动更改。

八、远程版本库更新

当注册了多个远程版本库并希望所有远程版本库一起更新时,可通过如下命令:git remote update 。

如果某个版本库不想通过 git remote update 自动更新,可以使用如下命令进行关闭:git config remote.user4.skipDefaultUpdate true

九、删除远程版本库

user4 远程版本库进行删除,命令为:git remote rm user4

origin25.png

十、push 和 pull 操作远程版本库

pushpull 操作的重点在于配置文件,配置文件指定了合并的远程版本库名称、远程推送和获取的地址、引用表达式、远程分支信息等等,根据如下的配置图,我们来分析一下执行过程:

origin23.png

不带参数执行 git push 命令的执行过程:

  1. 如果为当前分支设置了 {remote} ,则不带参数执行 git push 相当于执行了 git push {remote} 。如果没有为当前分支设置 {remote} ,则相当于执行了 git push origin

  2. 要推送的远程版本库的 URL{remote}.pushurl 指定,如果没有配置,则使用 {remote}.url 配置的 URL 地址。

  3. 如果为注册的远程版本库设置了 push 参数,即通过 {remote}.push 配置了一个引用表达式,则使用该引用表达式执行推送。否则,使用 ":" 作为引用表达式。该表达式的含义是同名分支推送,即对所有在远程版本库中有同名分支的本地分支执行推送。

总结:在一个本地新建分支中执行 git push 推送操作,是不会推送也不会报错的,因为远程分支不存在同名分支,所以根本就没有对该分支执行推送。如果需要在远程版本库中创建分支,可以执行 git push {remote} {new_branch} 。通过将本地分支推送到远程版本库的方式在远程版本库中创建分支。但是,不能通过 git pull(不带参数)将远程版本库中其他人推送的提交获取到本地,因为没有建立本地分支和远程分支的追踪。

不带参数执行 git pull 命令的执行过程:

  1. git push 一样,如果配置了 {remote} ,则使用配置的 {remote} 名称,否则使用 origin ,即不带参数的 git pull 相当于执行了 git pull origin

  2. 要获取的远程版本库的 URL 由地址 {remote}.url 指定。

  3. 如果为注册的远程版本库设置了 fetch 参数,即通过 {remote}.fetch 配置了一个引用表达式,则使用该引用表达式执行获取操作。

  4. 如果配置了 branch.merge ,则对其设定的分支执行合并操作,否则报错。

总结:在执行 git pull 操作时,可以通过使用参数 --rebase 设置使用变基而非合并操作。可通过使用: git config branch.{branchname}.rebase true 命令设置使用变基操作,而不是默认的合并操作。

十一、标签和远程版本库

远程版本库中的 tag 同步到本地版本库时,会使用相同的名称,不会像分支那样复制到另外的命令空间(远程分支)中,这可能会给本地版本库的标签带来混乱,特别是和多个远程版本库交互时。

之前讲过,执行 git fetch 命令时,如果有新建的 tag ,这些 tag 会被获取到本地版本库中。当删除远程版本库时,远程分支会被删除,但是已经引入到本地的 tag 并不会被删除(删除远程不影响本地),这也使本地版本库中的 tag 变得混乱。如果不想管理 tag ,可以进行如下操作:

  1. 在执行 git fetch 命令时,可以加上 -n--no-tags 参数不获取 tag 而只获取分支和提交。

  2. 在注册远程版本库的时候,也可以使用 --no-tags 参数,避免将远程版本库的 tag 引入到本地版本库。

实际上 Git 版本库本身也提供了一些安全机制避免对版本库的破坏:

  1. reflog 对分支的操作历史进行记录。

默认创建的带工作区的版本库都会包含 corelogallrefupdatestrue 的配置,这样在版本库中建立的每个分支都会创建对应的 reflog 。但是创建的裸版本库默认不包含这个设置,也就不会为每个分支设置 reflog 。如果团队的规模较小,可能因为分支误操作导致数据丢失,可以考虑为裸版本库添加corelogallrefupdates 的相关配置。

  1. 关闭非快进式推送。

如果将配置 receivedenyNonFastForwards 设置为 true ,则禁止一切非快进式推送。但这个配置有些矫枉过正,更好的方法是搭建基于 SSH 协议的 Git 服务器,通过钩子脚本更灵活地进行配置。允许来自某些用户的强制提交,而其他用户不能执行非快进式推送。

  1. 关闭分支删除功能。

如果将配置 receivedenyDeletes 设置为 true ,则禁止删除分支。同样更好的方法是通过架设基于 SSH 协议的 Git 服务器,配置分支删除的用户权限。

相关文章

  • Git-初次使用Bitbucket及问题解决

    初次使用Bitbucket及问题解决 建立远程版本库 创建一个远程版本库其实非常简单如下: 创建完成的远程版本库如...

  • Git 常用命令 更新与提交

    取得Git仓库 初始化一个版本仓库 Clone远程版本库 添加远程版本库origin 查看远程仓库 提交你的修改 ...

  • Git 一些常用指令

    创建版本库 git clone //克隆远程版本库 git clone -b //克隆远程指定分支 g...

  • Git 常用命令速查表

    创建版本库 $ git clone #克隆远程版本库 $ git init ...

  • Git常用命令速查表

    创建版本库 $ git clone #克隆远程版本库 $ git init #初始化本地版本库 修改和提交...

  • git命令总结

    Git 命令总结: 创建版本库 克隆远程版本库 $ git clone 初始化本地版本库 $ git init #...

  • Git常用命令

    配置 版本库 时光机穿梭 远程仓库 1. 添加远程库 2. 从远程库克隆 分支

  • 备份版本问题ERROR

    实际上是由版本问题引起的本地版本 远程版本 更新本地数据库版本 备份远程数据

  • git提交代码到远程分支

    1、添加文件到版本库缓存区 2、添加文件到版本库 3、把本地库与远程库关联(已关联可忽略) 4、push到远程仓库

  • 简单理解使用git

    git是一个版本管理方式,本地库和远程库是一样的,但是远程库可以一直存在(除非新的版本管理方式出现),远程库一般是...

网友评论

      本文标题:14.Git 远程版本库

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