分支
Git 的分支,其实本质上仅仅是指向提交对象的可变指针。 Git 的默认分支名字是 master。 在多次提交操作之后,你其实已经有一个指向最后那个提交对象的 master 分支。 master 分支会在每次提交时自动向前移动。
几乎所有的版本控制系统都以某种形式支持分支。 使用分支意味着你可以把你的工作从开发主线上分离开来,以免影响开发主线。
创建
# 创建分支
$ git branch test
# 切换分支
$ git checkout test
# 创建分支并切换至分支
$ git checkout -b test
当创建分支时,会产生一个新的指针指向当前记录。Git通过HEAD
这个特殊的指针来区分当前的项目是指向的master
主分支还是其他分支。
示例:
由运行结果可以看到现在的工作目录为test分支,即HEAD
指针指向了test分支。
此时我们在test分支修改文件时,test分支的指针就会继续向前移动,而master主分支依旧停留在原地,示例:
$ vim README.md
$ git add README.md
$ git commit -m "modify readme on branch"
[test 8a40260] modify readme on branch
1 file changed, 4 insertions(+)
此时切换回master分支,再次查看被修改的文件时,该文件的内容会停留在创建分支前的内容。
$ git checkout master
Switched to branch 'master'
$ vim README.md
这与过去大多数版本控制系统形成了鲜明的对比,它们在创建分支时,将所有的项目文件都复制一遍,并保存到一个特定的目录。 完成这样繁琐的过程通常需要好几秒钟,有时甚至需要好几分钟。所需时间的长短,完全取决于项目的规模。 而在 Git 中,任何规模的项目都能在瞬间创建新分支。 同时,由于每次提交都会记录父对象,所以寻找恰当的合并基础(译注:即共同祖先)也是同样的简单和高效。
合并
# 切换回主分支
$ git checkout master
# 合并指定分支
$ git merge [branchName]
由于某些大型项目需要多人合作,每个开发人员都会创建自己的分支并修改代码,所以在提交的过程中,可能会发生一下几种情况
单分支合并
当master主分支的指针未移动,即主分支没有做任何修改的情况下提交分支后,会使主分支的指针向前移动至该分支的位置上
由日志可以看出在未合并分支时,master指向8c9df48
地址,test分支指向8a40260
的地址,当test分支被合并后,master的指向就到了8a40260
并获得了test分支的提交信息。
当你试图合并两个分支时, 如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候, 只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进(fast-forward)”。
多分支合并
仓库中存在两个或以上分支时,它们都指向同一个master的地址,当其中一个分支test1提交后再去提交另一个分支test2时,由于test1使得master向前移动,所以test2提交时指向的是一个更靠前的版本,出现这种情况的时候,Git 会使用两个分支的末端所指的快照(test1 和 test2)以及这两个分支的公共祖先(master),做一个简单的三方合并。
在两个分支各自完成修改并提交后,指针指向对应的地址,此时我们提交test1分支
可以看到master的指针指到了test1的地址,继续合并test2
合并时会自动打开默认的文本编辑器,填写该次合并的提交信息,此时Git会自动创建一个地址用于保存此次合并的结果,并且两次master的提交中间包含两次分支提交的信息。
多分支修改相同文件
若两次分支同时修改了某个文件在提交时就会产生冲突,此时就需要我们手动或通过软件进行手动解决冲突文件,在进行提交和合并。
此时 Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。 你可以在合并冲突后的任意时刻使用 git status 命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件。此时我们再查看有冲突的文件时,可以看到主分支和带提交分支的内容,此时我们通过手动修改内容,来解决冲突
当按照实际情况解决冲突后,我们再次提交冲突的文件,两个分支就能够顺利合并。
# 将冲突文件添加至暂存区
$ git add README.md
# 提交冲突文件
$ git commit -m "modify README.md to merge branch"
[master d780068] modify readme to merge branch
分支
当分支被提交到主分支后,我们不再需要在分支上工作时,可以选择删除分支
# 删除分支
$ git branch -d [branchName]