本文出处:http://robinnagpal.wordpress.com/2012/08/05/git-internals-branches/
通过阅读本文,您将了解到:
- 一些有用的技术:
- Master
- HEAD
- Branch
- Git 中的分支的概念,以及为什么在 Git 中创建分支是如此简单和快速
- 本地分支和远程分支是什么意思
- 帮助我们创建和使用分支的命令
以下几点能够帮助我们在我们的项目中理解 GIT 的分支。
Master
当你初始化一个 GIT 仓库的时候,这将成为初始化的分支。你可以将它理解成 SVN 中的 trunk。
HEAD
这指向你签出的当前分支的引用,由 .git 文件夹中的 HEAD 文件表示。如果你查看这个文件的内容,应该类似下面:
ref: refs/heads/master
上面的内容指出,我们当前工作的副本指向的是 master 分支的最新提交版本。假设现在正在 branch_1 分支,那么 HEAD 内容应该是
ref: refs/heads/branch_1
Branch
在 GIT 中,我们的每次提交都包含以下信息:
- 一个指向唯一的父提交对象的引用;如果是合并提交的话,则应该是一个指向两个父提交对象的引用;
- 一个树对象的引用,这个对象会在以后包含多个 blob 或者树对象;
- 有关本次提交的信息,例如作者名字、email 以及提交信息等。
所以,每次独立提交都能够表示一个快照,这个快照是本工程当前提交对象的完整快照。这种设计使得 GIT 的分支十分简单、廉价以及健壮。
一个分支只是一个包含 40 个字符的字符串,该字符串指向这个提交对象,除此之外什么都不是。
我能理解你会觉得这种说法很难理解。给我一段时间,我将告诉你,一旦你明白了 GIT 的分支模型,你将不可救药的爱上她!
现在我们用图形表示分支。
假设我们有三个提交 mc_1、mc_2 和 mc_3,它们都位于 master 分支:
现在,我们决定从 master 分支创建一个分支 branch_1。我们使用如下命令:
git branch branch_1 git checkout branch_1
这两个命令可以合并为:
git checkout -b branch_1
现在我们的仓库看上去是这样的:
我们将会发现,现在的 HEAD 指向 branch_1。如果我们查看 HEAD 文件的内容,我们就会发现这一事实:
$ cat .git/HEAD ref: refs/heads/branch_1
如果我们查看 .git/refs/heads 文件夹中的内容,我们会发现以下文件:
branch_1 master
当我们创建该分支时,就会创建一个新的文件 branch_1。这个文件包含了 mc_3 提交的 SHA1 值。这就是分支的含义,也就是,一个指向了该分支的最新提交的 40 个字符的字符串。
现在,我们向该分支添加并提交一些内容:
$ echo "Greeting !!" > greeting.txt git add greeting.txt git commit -m "Our first commit to the branch"
现在我们有了该分支的第一次提交。我们的仓库应该如下表示:
现在,bc_1 是新分支上的新的提交对象。如果我们检查 .git/refs/branch_1 文件的内容,我们将会发现它就是指向我们新的提交对象的指针,也就是提交对象 bc_1 的 SHA1 值。
现在,我们回到 master 分支,添加一些东西:
git checkout master $ echo "Happy Birthday" > wishes.txt git add wishes.txt git commit -m "Our first commit in master after creation of the branch"
这次提交以后,我们的仓库类似:
现在,我们可以看出 GIT 中创建和管理分支是多么的简单。一旦你开始基于这些分支工作,你就会爱上 GIT 处理分支的这种方式。
现在我们试着修改欢迎文件,然后切换到 branch_1:
$echo “Merry Christmas”>greeting.txt git checkout branch_1
在我们试图执行第二个命令的时候,我们会得到下列错误:
error: The following untracked working tree files would be overwritten by checkout: greeting.txt Please move or remove them before you can switch branches. Aborting
GIT 会要求你,在切换到其它任意分支之前提交或者移除你所做的修改。这种设计看起来很琐碎,我们可以选择自动提交归档,然后切换到另外的分支。但是考虑一下真实用例,我们会有多个文件,有可能存在你即不想提交又不想回滚的改变。GIT 提供了 stash 的概念,用于处理这种情况。
本地分支和远程分支
本地分支就是我们上面看到的;远程分支是当你开始使用一个分布式方式时,你不得不接触到的东西。因为 GIT 是一个分布式版本控制系统,你可以简单地从拥有同一仓库的不同团队的机器上 pull 或者 push 内容。所有这些都是通过远程分支实现的。
通过上面的例子,你应该明白,为什么 GIT 中创建分支是如此快速、简单和廉价。