为了真正理解 Git
处理分支的方式,我们需要回顾一下Git
是如何保存数据的。
Git 保存的不是文件的变化或者差异,而是一系列不同时刻的文件快照。在进行提交操作时,Git
会保存一个提交对象(commit object
)。知道了Git
保存数据的方式,我们可以很自然的想到——该提交对象会包含一个指向暂存内容快照的指针。 但不仅仅是这样,该提交对象还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针。首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象,而由多个分支合并产生的提交对象有多个父对象。
Git
的分支,其实本质上仅仅是指向提交对象的可变指针。 Git
的默认分支名字是 master
。 在多次提交操作之后,你其实已经有一个指向最后那个提交对象的 master
分支。 它会在每次的提交操作中自动向前移动。
Git
的 “master” 分支并不是一个特殊分支。它就跟其它分支完全没有区别。 之所以几乎每一个仓库> 都有 master 分支,是因为git init
命令默认创建它,并且大多数人都懒得去改动它。
- 分支创建
Git
是怎么创建新分支的呢? 很简单,它只是为你创建了一个可以移动的新的指针。 比如,创建一个 testing
分支, 你需要使用 git branch
命令:
git branch testing
- 分支切换
git checkout testing
上面的创建分支和切换分支命令可以合起来用下面这个命令来替代。
git checkout -b testing
现在我们切换回 master
分支看看:
git checkout master
这条命令做了两件事。 一是使 HEAD 指回 master
分支,二是将工作目录恢复成 master
分支所指向的快照内容。 也就是说,你现在做修改的话,项目将始于一个较旧的版本。 本质上来讲,这就是忽略testing
分支所做的修改,以便于向另一个方向进行开发。
可以使用 git branch
命令查看当前分支,注意前面带*
的表示当前分支
分支切换会改变你工作目录中的文件
在切换分支时,一定要注意你工作目录里的文件会被改变。 如果是切换到一个较旧的分支,你的工作目> 录会恢复到该分支最后一次提交时的样子。 如果Git
不能干净利落地完成这个任务,它将禁止切换分支。
- 合并分支
假如我们在testing
上的工作完成了,就可以把testing
合并到master
上。Git
怎么合并呢?最简单的方法,就是直接把master
指向testing
的当前提交,就完成了合并,这里你需要使用git merge
命令。
git merge
命令用于合并指定分支到当前分支。合并后,再查看内容,就可以看到,和testing
分支的最新提交是完全一样的。
注意到上面的Fast-forward
信息,Git
告诉我们,这次合并是“快进模式”,也就是直接把master
指向testing
的当前提交,所以合并速度非常快。
- 删除分支
合并完分支后,甚至可以删除dev
分支。删除dev
分支就是把dev
指针给删掉,删掉后,我们就剩下了一条master
分支,这里需要使用git branch -d
命令来删除分支
git branch -d testing
- 合并分支冲突
git status
可以告诉我们冲突的文件,必须手动解决冲突后再提交。
- 分支管理策略
实际公司开发的时候一般3个分支就可以了:
- master 主分支用来发布
- dev 日常开发用的分支
- bug 修改bug用的分支
首先,master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
干活都在dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本,你和你的小伙伴们每个人都在dev
分支上干活,每个人都有自己的分支,时不时地往dev
分支上合并就可以了;bug
分支用来处理日常bug,搞定后合到dev分支即可;
假设远程公共仓库,有一个master
和一个dev
分支,进行多人协作开发时候(每个人的公钥必须加入到远程账号下,否则无法push
), 每个人都应该clone
一份到本地。 但是clone
的只是master
,如果远程的master
和dev
一样,没关系;如果不一致,则需要clone
出dev
分支 git checkout -b dev origin/dev
之后每个人在本地的dev
分支上独自开发(最好不要在mastst
上开发), 开发完成之后push
到远程dev
, git push origin dev
。 之后审核人再确定是否合并dev
到master
。
- 团队多人开发
当你从远程仓库克隆时,实际上Git自动把本地的master
分支和远程的master
分支对应起来了,并且,远程仓库的默认名称是origin
。
要查看远程库的信息,用git remote
,或者用git remote -v
显示更详细的信息。
上面显示了可以抓取和推送的origin
的地址。如果没有推送权限,就看不到push的地址。
推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git
就会把该分支推送到远程库对应的远程分支上:
git push origin branch-name
多人协作的工作模式通常是这样:
- 首先,可以试图用
git push origin branch-name
推送自己的修改; - 如果推送失败,则因为远程分支比你的本地更新,需要先用
git pull
试图合并; - 如果合并有冲突,则解决冲突,并在本地提交;
- 没有冲突或者解决掉冲突后,再用
git push origin branch-name
推送就能成功!
如果git pull
提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to branch-name origin/branch-name
。
这就是多人协作的工作模式,一旦熟悉了,就非常简单。
- 总结
git branch 查看当前分支 git branch -v 查看每一个分支的最后一次提交 git branch -a 查看本地和远程分支的情况 git branch --merged 查看已经与当前分支合并的分支 git branch --no-merged 查看已经与当前分支未合并的分支 git branch -r 查看远程分支 git branch dev 创建分支 dev git checkout dev 切换到分支dev git checkout -b dev 创建并切换分支dev git merge dev 名称为dev的分支与当前分支合并 git branch -d dev 删除分支dev git push origin --delete dev 删除远程分支dev