Git学习记录(三)(正在持续更新)
作者:下里巴人
远程仓库Github
Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。怎么分布呢?最早,肯定只有一台机器有一个原始版库,此后,别的机器可以“克隆”这个原始版本库,而且每台机器的版本库其实都是一样的,并没有主次之分。
你肯定会想,至少需要两台机器才能玩远程库不是?但是我只有一台电脑,怎么玩?
其实一台电脑上也是可以克隆多个版本库的,只要不在同一个目录下。不过,现实生活中是不会有人这么傻的在一台电脑上搞几个远程库玩,因为一台电脑上搞几个远程库完全没有意义,而且硬盘挂了会导致所有库都挂掉,所以我也不告诉你在一台电脑上怎么克隆多个仓库。
实际情况往往是这样,找一台电脑充当服务器的角色,每天24小时开机,其他每个人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。
(引自廖雪峰)
这一部分的操作需要我们拥有一个Github账号。从名字就可以看出,这个网站就是提供Git仓库托管服务的,所以,只要注册一个GitHub账号,就可以免费获得Git远程仓库。具体可以参考我们之前的文章(点这里直达哦),在这里已经较为详细的叙述了如何将自己的ssh密钥部署在Github上,请先完成这些步骤才能继续操作喔(*^▽^*)
添加远程库
在完成上述设置后,我们需要在Github中新建一个库(repo),库的名称随意,我就先建立一个名为learngit的远程库。
在我们建立好仓库后,GitHub告诉我们,可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到GitHub仓库。现在,我们根据GitHub的提示,在本地的learngit仓库下运行命令:
1 | $ git remote add origin https://github.com/Yourname/Yourreponame.git |
添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。
注意,这里的“Yourename”和“Yourreponame”分别是你Github账号的用户名和你新建仓库的名字。
下一步,就可以把本地库的所有内容推送到远程仓库上:
1 | $ git push -u origin master |
把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。
由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
这时候你登录查看该远程库,就会发现已经和自己本地的版本库一模一样啦!!从现在开始,我们只要本地提交了,就可以通过一下命令将本地的master分支的最新修改推送至远程库:
1 | $ git push origin master |
删除远程库
有了添加远程库,那我们肯定也会有删除远程库的需要,一共分两步,演示如下
解除本地与远程仓库的绑定关系
首先,我们先使用如下指令查看远程库信息:
1 | $ git remote -v |
然后根据名字删除:
1 | $ git remote rm origin |
删除远程库
要真正删除远程库,需要登录到GitHub,在后台页面找到删除按钮再删除。
从远程库克隆
我们之前是在现有本地库的情况下建立远程库,假设我们从零开始,那么最好的方式是先创建远程库,然后从远程克隆,我们先建立一个新的远程仓库gitskills,并且勾选Initialize this repository with a README,这样GitHub会自动为我们创建一个README.md文件。
这时,一个远程库我们已经建立好了,输入以下指令来克隆一个本地库:
1 | $ git clone git@github.com:Yourname/Yourreponame.git |
1 | $ git clone git@github.com:Motherlesssss/gitskills.git |
注意,这里的“Yourename”和“Yourreponame”分别是你Github账号的用户名和你已经建立好的仓库的名字。
这时你就会发现本地的gitskills目录中已经出现README.md啦!!
分支管理
关于分支管理的作用以及解释,在廖雪峰老师的网站已经有详细解释了,可以自行前往观看,这里便不再赘述,直接进入正题(*^▽^*)
创建并切换分支
创建并切换至dev分支:
1 | $ git switch -c dev |
git switch命令加上-c参数表示创建并切换,相当于以下两条命令:
1 | $ git branch dev |
查看当前分支
1 | $ git branch |
这个命令会列出所有分支,当前分支前会加一个 * 号
合并分支(快合并)
当我们在dev分支上做出修改后,我们此时想合并两个分支,可以如下操作:
注意,在进行合并操作前,该分支的修改必须已经提交添加至版本库!
切换至master分支:
1 | $ git switch master |
我们会发现在这个分支下我们刚刚修改的文件并没有改变,是因为刚刚的修改在dev分支上,而master分支的提交点并没有变,所以接下来合并:
1 | $ git merge dev |
git merge命令用于合并指定分支到当前分支 。
注意到上面的Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。
当然,也不是每次合并都能Fast-forward,我们后面会讲其他方式的合并。
删除分支
当你完成合并后,你就可以删除这个分支了,指令如下:
1 | $ git branch -d dev |
冲突情况下的合并
在前面我们已经演示过的合并中,dev分支提交的修改内容与master分支完全不同,修改内容不起冲突。因此Git会默认快合并,就像下面这张图所描述的一样:
而如果我们此时新建并切换到一个feature1的分支,在这个分支下我们修改readme.txt添加最后一行并提交:
1 | its a test |
紧接着,我们切换回master分支,并且将最后一行添加如下,并且提交:
1 | it's a test |
此时,master分支与feature1分支都分别各自有了新的提交,变成了如下图:
这时候我们若执行合并,会出现以下情况:
1 | $ git merge feature1 |
很显然,此时出现了冲突,必须手动解决,当然,使用git status指令查看状态,也会告诉我们哪里起冲突了:
1 | $ git status |
当然,此时我们直接直接查看readme.txt内容:
Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,我们直接在该文件中修改如下后保存并且提交:
1 | its a test |
1 | $ git add readme.txt |
现在,master分支与feature1分支变成了如下图所示:
也可使用该指令查看分支合并情况:
1 | git log --graph --pretty=oneline --abbrev-commit |
或者该指令查看分支合并图:
1 | git log --graph |
最后别忘了删除feature1分支哦!!
当然,这里的情况是修改量较小的情况下,如果修改量太大,想要放弃合并,可以使用以下指令来让你的代码恢复到合并之前的状态:
1 | git merge --abort |
禁用快合并,保留分支历史
大部分情况下,我们的分支不会起冲突,因此绝大多数的合并都是快合并,但是在这种模式下,删除分支后,会丢掉分支信息。因此,我们可以选择强制禁用快分支,这样,我们就能保留分支信息了:
1 | $ git merge --no-ff -m "commit描述" 分支名 |
这时就会如下图,分支信息就得以保留:
分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。所以,团队合作的分支看起来就像这样:
(引自廖雪峰)
Bug分支
我们设想如下场景:我们正在dev分支上进行工作,此时我们突然发现我们此前的版本库中有一个文件存在问题,我们想要创建分支去修改它,但是我们手头的dev分支工作还没有提交,我们该怎么办?不用慌,我们可以输入以下指令来“储藏”当前的工作现场:
1 | $ git stash |
接着,我们确定从哪个分支来修复,假设在master分支上创建临时分支:
1 | $ git switch master |
此时可以用下图描述:
在此分支上完成修改后,切换至master分支,并完成合并,最后记得删除bug分支:
1 | $ git add readme.txt |
请注意这里的4c805e2 !!后续非常重要。
这是我们切换回dev分支,查看工作区却发现是干净的:
1 | $ git switch dev |
用如下命令查看我们刚刚存好的工作区:
1 | $ git stash list |
接着,用如下命令恢复并删除stash内容:
1 | $ git stash pop |
当然可以stash多次,恢复时先用git stash list查看,然后恢复指定stash:
1 | $ git stash apply stash@{0} |
由于我们的dev分支是早期master分支分出来的,所以我们需要将这个改动重放一遍:
1 | $ git branch |
这里的4c805e2 ,便是上文标红的编号啦!!



