Git简记
1.前言
用过一段时间的git,但玩的不是很溜,为了适应新工作的要求,所以打算再学一学。
推荐2个教程,本文所记录的知识点大部分来自这2个博客:
廖雪峰的git教程;
阮一峰的git教程;
2.Git基础工作流程
该图涵盖git的基本结构;
-
工作区
即我们想进行版本控制的本地目录。 -
版本库
基于工作区进行版本管理,即我们平时项目目录下的那个隐藏的.git文件夹。里边记录了很多关于版本管理的信息。主要包括暂存区和分支。 -
暂存区,stage
一般我们从本地工作区提交到仓库都是先add再commit到对应分支,如果要推到远程仓库还需要push,这个暂存区的主要意义在于多一次撤销缓冲,等暂存区稳定了之后一波commit,相当于是git安全性的一种手段吧。 -
分支,master
一般我们初始化了一个版本库时,Git默认为我们创建一个主干分支,即master分支。 -
Head指针
Head指针指向哪个分支就表示当前处于哪个分支。
3.Git好在哪?
Git是一个开源的分布式版本控制系统(SVN是非分布式的),关键词,分布式;
先不着急说什么是分布式,先看看svn这种集中式的版本管理有什么缺陷;
集中式的版本控制,有个严重的缺陷。就是中央服务器的单点故障。如果服务宕机一个小时,在这期间,没有任何人可以在正在工作的版本上很好的合作或者去保存某一个版本的改变。另外如果中央数据库的磁盘坏了,并且可能没有保存备份,那么将丢失所有的东西。你失去了绝对一切 - 除了单一的任何人的快照恰好有在本地计算机上项目的整个历史。当然本地的版本控制系统也有相同的问题。虽然,你能够把每个人的本地代码,进行合并得到一个相对完整的版本,但是当你把这个相对完整的版本重新部署到服务器的新仓库时,将会丢失所有的历史版本包括日志。
分布式Git的演进就是为了解决这个问题,我们每次clone,pull或是push代码时不光是更新了文件,也更新了整个完整的版本库,这也就是为什么说Git下每台电脑都是服务器,不是说要让A往B提代码,B往C提代码,(实际工作过程中会有一台远程仓库服务器,比如Github),而是每台电脑上都拥有完整的仓库镜像(来源于远程仓库服务器),所谓分布式,是指代码仓库,版本库的分布式。
与svn对比:
- 1.git是分布式的scm,svn是集中式的。(最核心)
- 2.git是每个历史版本都存储完整的文件,便于恢复,svn是存储差异文件,历史版本不可恢复。(核心)
- 3.git可离线完成大部分操作,svn则不能。
- 4.git有着更优雅的分支和合并实现。
- 5.git有着更强的撤销修改和修改历史版本的能力
- 6.git速度更快,效率更高。
4.分支
分支很重要,Git的核心之一。
4.1.分支基本理解
理解分支这个概念可以将其想象为一条线。多个分支就是多条线,每一条分支线在合并之前都互不影响,一般来说,规范的项目都是2条线必要的,master和dev,master就是用来上线的,dev就是用来做开发的,开发完事之后预发布稳定了就合并到master里进行上线,在dev之下的分支就是看个人的需求,或基于版本,或基于功能,而展开的分支线,这类分支是可以藏在本地的,合并完了就可以删除的。
更细致的可以去看下廖雪峰或者阮一峰的git教程。
4.2.本地分支和远程分支
另外分支还有个比较重要的概念是:远程分支和本地分支这个概念。
先前已经说了,初始化一个Git版本库的时候,Git会默认为我们创建一个master分支。
在单机环境下,这个概念无法体现,若是多人协作的联网环境,比如我在github上开一个项目P/master,同学A克隆一份,现在就是俩份master,在Git服务器上的那一份可以叫做“远程master(术语:origin/master,origin表示远程的意思)”,被同学A克隆到本地的那一份就是本地master。他们之间相互映射关联,这是自动关联,还可以手动进行关联。
手动关联的命令是:
git remote add origin master
当然关联就涉及到发起方和被关联的对象。不做特殊配置或是单分支情况下:
发起方就是默认的本地master分支,目标对象就是origin/master。
4.3.多分支的切换
当然实际工作中不可能就这么简单的场景,假设你面对的工作环境是多个本地分支,多个远程分支,那么时候就涉及到一些问题:
“我想在自由切换本地哪个分支上进行开发”
“我想修改本地分支所映射的远程分支以便达到精准提交到某个分支的目的”
“我想知道本地分支和远程分支的映射关系”
“我想新建/删除某个分支,并同步到远程库”
这里实操一波,我在github上新建了一个仓库叫做
GitTest
A>.我clone下来之后先看看它上面有哪些分支:git branch -a
$git branch -a
* master
remotes/origin/master
B>创建并切换到dev分支git branch dev
git checkout dev
$ git branch -a
* dev
master
remotes/origin/master
可以看到这时候只有本地有dev分支
PS:
上面2句可以合并成一句,创建并切换一个分支:git checkout -b dev
但是会有一个错误,如果当前分支存在的话会报:fatal: A branch named 'dev' already exists.
C>将本地分支同步到远程库git push origin dev
或者git push origin dev:dev2
第一个箭头处可以看到本地新建的dev还没有发布到远程仓库库。
第二个箭头处将本地dev分支分布到远程仓库,并以本地分支名称为名创建一个同名远程分支。
第三个箭头以别名形式(dev2)发布本地分支dev的内容,并在远程仓库新建dev2分支。
第四个箭头表示若远程分支已经存在,同名的分支是无法发布到远程库了的。
D>删除一个远程分支
刚才我故意多创建了一个dev2分支来试试别名发布功能,现在我不需要了于是这里我把它删除。git push origin --delete dev2
E>查看分支的映射关系git branch -vv
$ git branch -vv
* dev 91b96db 首次提交
master 91b96db [origin/master] 首次提交
此刻dev分支并没关联的远程分支,虽然远程库已经存在origin/dev了,但还需要关联一下;(不关联的后果是push不上去)git branch -vv
F>本地分支关联远程分支git branch --set-upstream dev origin/dev
第一个箭头处可以看到本地分支是没有对应的远程分支关联的,这种情况下去push也是不行的。
第二个箭头就是执行该命令去关联,并在第三个箭头进行查看发现关联上了,最后第四个箭头处push也成功了。
4.4.merge,合并分支
前面我们实操了一波,情况是:
master上提交了一个txt文档,内容是1。
dev上修改了这个txt文档,内容是2。
这时候我想要将来dev合并到master上,该怎么操作呢?
git merge dev
第一个箭头告诉我当前处于master分支,这是我所预期的,因为,我想把dev的修改merge进master分支。
第二个箭头就是正式开始merge了,在第二箭头之上我查看了下当前的文本内容,是1(比较隐蔽,在命令前缀之前一格)。
第三个箭头是merge之后的文案。
然后去服务器上检查发现这只是本地merge,服务器上的内容并没有改变,这时候还需要将merge之后的内容push到origin master。
5.fetch和pull
pull和fetch都是从服务器远程仓库拉代码到本地,pull可能用的比较熟,fetch可能用的比较少,pull的意思就是将远程仓库的代码拉下来并且合并到当前分支,而fetch只拉代码并不合并,在阮一峰的git教程里是这么说的:
git fetch命令通常用来查看其他人的进程,因为它取回的代码对你本地的开发代码没有影响。
默认情况下,git fetch取回所有分支(branch)的更新。如果只想取回特定分支的更新,可以指定分支名
git fetch <远程主机名> <分支名>
比如,取回origin主机的master分支。git fetch origin master
取回远程主机的更新以后,也可以在它的基础上,使用git checkout命令创建一个新的分支。
6.其他
本文权且到此为止,有不足之处还请支出。
git命令大全
git merge的撤销
git merge 合并分支-mergetools
git-merge完全解析-ff