Git的分支

Git 基础

Git 和其他版本控制系统的主要差别在于,Git 只关心文件数据的整体是否发生变化,而大多数其他系统则只关心文件内容的具体差异。

 

Git 并不保存这些前后变化的差异数据。实际上,Git 更像是把变化的文件作快照后,记录在一个微型的文件系统中。每次提交更新时,它会纵览一遍所有文件的指纹信息并对文件作一快照,然后保存一个指向这次快照的索引。为提高性能,若文件没有变化,Git 不会再次保存,而只对上次保存的快照作一链接。Git 的工作方式就像图 1-5 所示。

 

 

在Git 中的绝大多数操作都只需要访问本地文件和资源,不用连网。

 

 

在保存到 Git 之前,所有数据都要进行内容的校验和(checksum)计算,并将此结果作为数据的唯一标识和索引。

在Git 内都只有三种状态:已提交(committed),已修改(modified)和已暂存(staged)。已提交表示该文件已经被安全地保存在本地数据库中了;已修改表示修改了某个文件,但还没有提交保存;已暂存表示把已修改的文件放在下次提交时要保存的清单中。

由此我们看到 Git 管理项目时,文件流转的三个工作区域:Git 的工作目录,暂存区域,以及本地仓库。

 

基本的 Git 工作流程如下:

  1. 在工作目录中修改某些文件。
  2. 对修改后的文件进行快照,然后保存到暂存区域。
  3. 提交更新,将保存在暂存区域的文件快照永久转储到 Git 目录中。

 

 

Git分支

何为分支

 

Git 中的分支,其实本质上仅仅是个指向 commit对象的可变指针。Git 会使用 master 作为分支的默认名字。在若干次提交后,你其实已经有了一个指向最后一次提交对象的 master 分支,它在每次提交的时候都会自动向前移动。

 

Git 是如何知道你当前在哪个分支上工作的呢?其实答案也很简单,它保存着一个名为 HEAD 的特别指针。HEAD指向当前所在的分支

 

要切换到其他分支,可以执行git checkout 命令。

 

 

每次提交后 HEAD 随着分支一起向前移动

 

 

$ git checkout master
 

这条命令做了两件事。它把 HEAD 指针移回到 master 分支,并把工作目录中的文件换成了 master 分支所指向的快照内容。也就是说,现在开始所做的改动,将始于本项目中一个较老的版本。它的主要作用是将 testing 分支里作出的修改暂时取消,这样你就可以向另一个方向进行开发。

我们作些修改后再次提交:

$ vim test.rb

$ git commit -a -m 'made other changes'

 

由于 Git 中的分支实际上仅是一个包含所指对象校验和(40 个字符长度 SHA-1 字串)的文件,所以创建和销毁一个分支就变得非常廉价。说白了,新建一个分支就是向一个文件写入 41 个字节(外加一个换行符)那么简单,当然也就很快了。

 

分支的新建与合并

 

上面已经简述分支的新建,下面简述分支的合并

情况一:直接就是合并到上游分支中去,直接移动指针就可以

 

现在需要合并C2和C4两个分支

$ git checkout master
$ git merge hotfix

合并时出现了“Fast forward”的提示。由于当前master 分支所在的提交对象是要并入的hotfix 分支的直接上游,Git 只需把master 分支指针直接右移。换句话说,如果顺着一个分支走下去可以到达另一个分支的话,那么 Git 在合并两者时,只会简单地把指针右移,因为这种单线的历史分支不存在任何需要解决的分歧,所以这种合并过程可以称为快进(Fast forward)。

 

 

情况二,两个分支修改的部分互不相关,直接使用merge命令就可以。

现在C4和C5两个部分都是在C2的基础上修改的,而且两个修改的部分互不干扰

 

$ git checkout master
$ git merge iss53
 
 
Git 为分支合并自动识别出最佳的同源合并点。
 

这次,Git 没有简单地把分支指针右移,而是对三方合并后的结果重新做一个新的快照,并自动创建一个指向它的提交对象(C6)(见图 3-17)。这个提交对象比较特殊,它有两个祖先(C4 和 C5)。

值得一提的是 Git 可以自己裁决哪个共同祖先才是最佳合并基础

 

有时候合并操作并不会如此顺利。如果在不同的分支中都修改了同一个文件的同一部分,Git 就无法干净地把两者合到一起(译注:逻辑上说,这种问题只能由人来裁决。)

 

如果想给将来看这次合并的人一些方便,可以修改该信息,提供更多合并细节。比如你都作了哪些改动,以及这么做的原因。有时候裁决冲突的理由并不直接或明显,有必要略加注解。

 

 

 

分支的管理

关于删除分支:

git branch 命令不仅仅能创建和删除分支,如果不加任何参数,它会给出当前所有分支的清单

若要查看各个分支最后一个提交对象的信息,运行git branch –v

 

要从该清单中筛选出你已经(或尚未)与当前分支合并的分支,可以用--merged--no-merged 选项

 

git branch --merged 查看哪些分支已被并入当前分支(译注:也就是说哪些分支是当前分支的直接上游。):(前面有*则表示不符合查找的过滤条件)

$ git branch --merged

  iss53

* master

之前我们已经合并了 iss53,所以在这里会看到它。一般来说,列表中没有 * 的分支通常都可以用git branch -d 来删掉。原因很简单,既然已经把它们所包含的工作整合到了其他分支,删掉也不会损失什么。

另外可以用 git branch --no-merged 查看尚未合并的工作:

$ git branch --no-merged

  Testing

 

远程分支

 

远程分支(remotebranch)是对远程仓库中的分支的索引。它们是一些无法移动的本地分支;只有在 Git进行网络交互时才会更新。远程分支就像是书签,提醒着你上次连接远程仓库时上面各分支的位置。

 

 

远程分支和本地分支只有在联网并同步的时候才可以保持同步,所以常常的情况是本地仓库和远程仓库并不同步

 

假设你们团队有个地址为git.ourcompany.com 的 Git 服务器。如果你从这里克隆,Git 会自动为你将此远程仓库命名为origin,并下载其中所有的数据,建立一个指向它的master 分支的指针,在本地命名为origin/master,但你无法在本地更改其数据。接着,Git 建立一个属于你自己的本地master 分支,始于originmaster 分支相同的位置,你可以就此开始工作(见图 3-22):

 

 

图 3-22. 一次 Git 克隆会建立你自己的本地分支 master 和远程分支 origin/master,并且将它们都指向origin 上的master 分支。

 

如果你在本地master 分支做了些改动,与此同时,其他人向git.ourcompany.com 推送了他们的更新,那么服务器上的master 分支就会向前推进,而于此同时,你在本地的提交历史正朝向不同方向发展。不过只要你不和服务器通讯,你的origin/master 指针仍然保持原位不会移动(见图 3-23)


图 3-23. 在本地工作的同时有人向远程仓库推送内容会让提交历史开始分流。

可以运行 git fetch origin 来同步远程服务器上的数据到本地。该命令首先找到 origin是哪个服务器(本例为 git.ourcompany.com),从上面获取你尚未拥有的数据,更新你本地的数据库,然后把origin/master 的指针移到它最新的位置上(见图 3-24)。


图 3-24. git fetch 命令会更新 remote 索引。

 

要想和其他人分享某个本地分支,你需要把它推送到一个你拥有写权限的远程仓库。你创建的本地分支不会因为你的写入操作而被自动同步到你引入的远程服务器上,你需要明确地执行推送分支的操作。换句话说,对于无意分享的分支,你尽管保留为私人分支好了,而只推送那些协同工作要用到的特性分支。

 

 

如果你有个叫 serverfix 的分支需要和他人一起开发,可以运行git push (远程仓库名) (分支名)

 

这里其实走了一点捷径。Git 自动把 serverfix分支名扩展为refs/heads/serverfix:refs/heads/serverfix,意为“取出我在本地的serverfix 分支,推送到远程仓库的serverfix 分支中去”。我们将在第九章进一步介绍refs/heads/ 部分的细节,不过一般使用的时候都可以省略它。也可以运行git push origin serverfix:serverfix来实现相同的效果,它的意思是“上传我本地的serverfix 分支到远程仓库中去,仍旧称它为serverfix分支”。通过此语法,你可以把本地分支推送到某个命名不同的远程分支:若想把远程分支叫作awesomebranch,可以用git push originserverfix:awesomebranch 来推送数据。

接下来,当你的协作者再次从服务器上获取数据时,他们将得到一个新的远程分支origin/serverfix,并指向服务器上 serverfix 所指向的版本:

 

值得注意的是,在fetch 操作下载好新的远程分支之后,你仍然无法在本地编辑该远程仓库中的分支。换句话说,在本例中,你不会有一个新的serverfix 分支,有的只是一个你无法移动的origin/serverfix 指针。

 

如果要把该远程分支的内容合并到当前分支,可以运行git merge origin/serverfix。如果想要一份自己的 serverfix 来开发,可以在远程分支的基础上分化出一个新的分支来:

 

$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch refs/remotes/origin/serverfix.
Switched to a new branch "serverfix"

git checkout –b新建并转到该分支)

 

 

 

这会切换到新建的serverfix 本地分支,其内容同远程分支origin/serverfix 一致,这样你就可以在里面继续开发了。

 

从远程分支 checkout 出来的本地分支,称为跟踪分支 (tracking branch)。跟踪分支是一种和某个远程分支有直接联系的本地分支。在跟踪分支里输入git push,Git 会自行推断应该向哪个服务器的哪个分支推送数据。同样,在这些分支里运行git pull 会获取所有远程索引,并把它们的数据都合并到本地分支中来。

在克隆仓库时,Git 通常会自动创建一个名为 master 的分支来跟踪origin/master这正是git pushgit pull 一开始就能正常工作的原因。当然,你可以随心所欲地设定为其它跟踪分支,比如origin 上除了master 之外的其它分支。刚才我们已经看到了这样的一个例子:git checkout -b [分支名] [远程名]/[分支名]。如果你有 1.6.2 以上版本的 Git,还可以用--track 选项简化:

$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch refs/remotes/origin/serverfix.
Switched to a new branch "serverfix"

要为本地分支设定不同于远程分支的名字,只需在第一个版本的命令里换个名字:

$ git checkout -b sf origin/serverfix
Branch sf set up to track remote branch refs/remotes/origin/serverfix.
Switched to a new branch "sf"

现在你的本地分支 sf 会自动将推送和抓取数据的位置定位到 origin/serverfix 了。

删除远程分支

如果不再需要某个远程分支了,比如搞定了某个特性并把它合并进了远程的 master 分支(或任何其他存放稳定代码的分支),可以用这个非常无厘头的语法来删除它:gitpush [远程名] :[分支名]。如果想在服务器上删除serverfix 分支,运行下面的命令:

$ git push origin :serverfix
To git@github.com:schacon/simplegit.git
 - [deleted]         serverfix

咚!服务器上的分支没了。你最好特别留心这一页,因为你一定会用到那个命令,而且你很可能会忘掉它的语法。有种方便记忆这条命令的方法:记住我们不久前见过的git push [远程名][本地分支]:[远程分支] 语法,如果省略[本地分支],那就等于是在说“在这里提取空白然后把它变成[远程分支]”。

 

分支的衍合

http://git-scm.com/book/zh/Git-%E5%88%86%E6%94%AF-%E5%88%86%E6%94%AF%E7%9A%84%E8%A1%8D%E5%90%88

就是在合并文件后,删除其中一部分合并“基础”,在不熟练时候不推荐使用。

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值