Git基本知识一讲了一些关于Git的基本概念,但是这些都是在本地仓库操作的,没有连接到远程仓库,但是Git最重要的就是可以连接到远程仓库进行版本控制,那么第二讲就讲一些关于Git远程的一些知识。
1、Git的协作模型
首先讲下在Git中,基本的协作模型是怎样的,如下图
图不是特别好看,这只是Git协作模型中最基础的一个。首先,我们会有一个远程的代码仓库origin,用户A和用户B都在各自的本地维护着本地的代码仓库,用户A和用户B要进行代码开发的时候,首先用户A将从远程代码仓库origin拉取(pull)最新的代码,在自己的本地开发完成后,再将修改好的代码推送(push)到远程代码仓库,同理(这里不考虑推送时候的冲突),用户B进行代码开发之前也是要从远程代码仓库拉取最新的代码,并将修改好的代码推送到远程代码仓库。
了解了Git的协作模型后,下面就是如何跟远程仓库进行关联。
1.1远程仓库信息
我们可以使用git add remote <仓库名> <远程地址>来将远程仓库地址添加进来,并且可以使用git remote show <仓库名>来查看远程仓库的信息。
如上图,显示出了远程仓库的详细信息,首先remote origin是你远程仓库的名字origin,Fetch URL是当你使用git pull是拉取的远程仓库的地址,Push URL则是当你使用git push的时候推送的远程仓库的地址。HEAD branch意味着你目前所在的分支时maaster,Remote branch这个是你远程的分支,master tracked意味着远程的master分支已经被追踪,之后的几句就是被追踪的解释,即被追踪,就是当我在master分支上的时候,使用git pull或者git push的时候,是将我本地的master分支上的信息推送到远程master的分支上。
1.2 origin/master
当添加好了远程仓库之后,这时,我在工作区中修改一个test.txt文件,使用git status进行查看状态的时候,这时会出现如下图所示的信息
这里与本地操作不同的是第二行的信息,即“Your branch is up to date with ‘origin/master’ ”,意思是我现在的分支是领先于origin/master分支的,这里的origin/master是什么呢?我们都知道master是本地分支,所以origin/master是远程分支,是远程版本库所对应的分支。
这里我们在解释下git pull和git push。我们都知道,Git其实在每次提交的时候都会对应一个40位的SHA-1值,也就是commit id。当我们使用git pull操作的时候,其是将远程修改全部拉取到本地,实质是将origin/master分支的commit id对应到远程的master分支上的最新的commit id,而git push则是将origin/master的commit id指向本地的master的最新commit id,再将代码推送到远程。说到这里,其实就差不多能明白,其实origin/master相当于你本地master和远程仓库master的一个中转站。
所以,在我们的本地仓库,其实是有一个master分支,一个origin/master分支,origin/master分支对应远程master分支,origin/master追踪远程master。origin/master可以在.git/refs/remotes/origin中看到,其中的HEAD文件就是当前所在的远程分支,origin/master是只读的,不能进行修改,由git自己维护,如果使用git checkout origin/master,则会进入detached head状态。
1.3 冲突
项目工作中,推送都不是一帆风顺的,会遇到一些问题推送不成功,这里介绍一下冲突的产生。
冲突产生的原因很简单,就是在你推送代码的时候修改了最新代码的同一个文件的同一行,这是git就不知道到底应该采用哪个,就会将决定权交给用户。
这里我修改了test.txt文件,修改了同一行的内容,进行推送时,就直接被拒绝了,如下图
这时候,就需要手动解决冲突,并进行再次的推送,使用git pull将代码拉取下来,在本地进行修改之后,在进行推送。
1.4 refspec
refspec,在我的理解就是引用规范,其本质就是在本地的远程分支与远程仓库的远程分支的一种对应关系。
在这里,我们使用git branch -av查看所有分支的详细信息
可以从图中看到,这里远程有一个origin/master分支,而本地有三个分支develop,master,test。目前所在的分支是develop,这时如果如果直接使用git push,则会出现如下报错信息
这里提示,当前的develop是没有上游分支的,使用git push --set-upstream origin develop来进行关联,这句命令就是将当前所在分支develop推送到远程origin/develop,并且在远程仓库中创建一个develop分支,并将远程的develop分支与本地develop分支进行对应,也即上游分支。也可以使用git push -u origin develop进行关联,这种做法git不推荐使用。
上述情况是本地分支存在,但远程分支不存在的情况,下面介绍当远程分支存在,本地分支不存在的情况。
这里的情况是,远程有develop和master分支,但本地只有master分支,要进行远程分支与本地分支的关联,可以使用git checkout -b develop origin/develop,该命令是先创建本地develop分支,并与origin/develop保持对应关系,也可以使用git checkout --track origin/develop。
1.5 分支不同名
一般的建议是最好将远程分支的名称与本地分支的名称保持一致,这样会省去很多麻烦。比如说,本地分支名为develop分支,但远程分支为develop2,这时进行推送的时候,就会出现错误。
当前分支与远程分支不匹配,使用git push origin HEAD:develop2命令推送,所以一般将名称都命名为相同的,会省去一些麻烦。
2、rebase
rebase,称为变基,是对分支进行合并的时候,改变分支的根基。
我们知道merge也是有合并分支的功能,使用merge进行三方合并的时候,一般会产生一个新的提交。
在上述图中,使用merge进行操作的时候,会将C2、C4和C6进行三方合并,生成一个新的提交C7,这是merge的原理。
而同样的提交方式,如果使用rebase,则是如下所示
rebase操作会讲C5和C6的提交在C4上在重新进行一遍,其是将一个分支的修改直接应用到另一个分支上,rebase的操作重要的一点就是其会修改提交历史,从图中可以看到C5和C6的历史提交就会被修改,所以一般建议,不要对master分支使用rebase操作。