Git历险记(5):Git里的分支与合并(1)
Git历险记(5):Git里的分支与合并(1)
51CTO编者按:本文是《Git历险记》系列的第五篇,译者刘辉通过翻译《Git Community Book》为我们具体讲解Git里的分支与合并以及如何处理冲突的方法。如果你对Git还不了解,可以参看《Git历险记(1):初识版本控制系统Git》。以下是正文。
分支与合并
在Git里面我们可以创建不同的分支,来进行调试、发布、维护等不同工作,而互不干扰。下面我们还是来创建一个试验仓库,看一下Git分支运作的台前幕后:
$rm -rf test_branch_proj $mkdir test_branch_proj $cd test_branch_proj $git init Initialized empty Git repository in /home/test/test_branch_proj/.git/
我们如以往一样,创建一个“readme.txt”文件并把它提交到仓库中:
$echo "hello, world" > readme.txt $git add readme.txt $git commit -m "project init" [master (root-commit) 0797f4f] project init 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 readme.txt
我们来看一下工作目录(working tree)的当前状态:
$git status # On branch master nothing to commit (working directory clean)
大家如果注意的话,可以看到“# On branch master”这么一行,这表示我们现在正在主分支(master)上工作。当我们新建了一个本地仓库,一般就是默认处在主分支(master)上。下面我们一起看一下Git是如何存储一个分支的:
$cd .git $cat HEAD ref: refs/heads/master
“.git/HEAD”这个文件里保存的是我们当前在哪个分支上工作的信息。
在Git中,分支的命名信息保存在“.git/refs/heads”目录下:
$ls refs/heads master
我们可以看到目录里面有一个名叫“master”文件,我们来看一下里面的内容:
$cat refs/heads/master 12c875f17c2ed8c37d31b40fb328138a9027f337
大家可以看到这是一个“SHA1哈希串值”,也就是一个对象名,我们再看看这是一个什么类型的对象:
$cat refs/heads/master | xargs git cat-file -t commit
是的,这是一个提交(commit),“master”文件里面存有主分支(master)最新提交的“对象名”;我们根据这个“对象名”就可以可找到对应的树对象(tree)和二进制对象(blob),简而言之就是我能够按“名”索引找到这个分支里所有的对象。
读者朋友把我们文章里的示例在自己的机器上执行时会发现,“cat refs/heads/master”命令的执行结果和和文章中的不同。在本文里这个提交(commit)的名字是: “12c875f17c2ed8c37d31b40fb328138a9027f337”,前面我讲Git是根据对象的内容生成“SHA1哈希串值”作为 名字,只要内容一样,那么的对应的名字肯定是一样的,为什么这里面会不一样呢? Git确实根据内容来生成名字的,而且同名(SHA1哈希串值)肯定会有 相同内容,但是提交对象(commit)和其它对象有点不一样,它里面会多一个时间戳(timestamp),所以在不同的时间生成的提交对象,即使内容 完全一样其名字也不会相同。
下面命令主是查看主分支最新提交的内容:
$cat refs/heads/master | xargs git cat-file -p tree 0bd1dc15d804534cf25c5cb53260fd03c84fd4b9 author liuhui998 1300697913 +0800 committer liuhui998 1300697913 +0800 project init
“1300697913 +0800”这就是时间戳(timestamp)。
现在查看此分支里面所包含的数据(blob)
$cat refs/heads/master | xargs git cat-file -p | head -n 1 | cut -b6-15 | xargs git cat-file -p 100644 blob 4b5fa63702dd96796042e92787f464e28f09f17d readme.txt
查看当前的readme.txt
$git cat-file -p 4b5fa63 hello, world $cd ..
好的,前面是在主分支(master)里面玩,下面我们想要创建一个自己的测试分支来玩一下。git branch命令可以创建一个新的分支,也可以查看当前仓库里有的分支。下面先创建一个叫“test”的分支: $git branch test
再来看一下当前项目仓库中有几个分支:
$git branch * master test
我们现在签出“test”分支到工作目录里:
$git checkout test
现在再来看一下我们处在哪个分支上:
$git branch master * test
好的,我们现在在“test”分支里面了,那么我们就修改一下“readme.txt”这个文件,再把它提交到本地的仓库里面支:
$echo "In test branch" >> readme.txt $git add readme.txt $git commit -m "test branch modified" [test 7f3c997] test branch modified 1 files changed, 1 insertions(+), 0 deletions(-)
当看当前版本所包含的blob:
$git cat-file -p HEAD | head -n 1 | cut -b6-15 | xargs git cat-file -p
我们现在再像前面一样的看看Git如何存储“test”这个分支的,先来看看“.git/HEAD”这个文件是否指向了新的分支:
$cd .git $cat HEAD ref: refs/heads/test
没错,“.git/HEAD”确实指向的“test”分支。再来看看“.git/refs/heads”目录里的内容:
$ls refs/heads master test
我们可以看到目录里面多了一个名叫“test”文件,我们来看一下里面的内容:
$cat refs/heads/test 7f3c9972577a221b0a30b58981a554aafe10a104
查看测试分支(test)最新提交的内容:
$cat refs/heads/test | xargs git cat-file -p tree 7fa3bfbeae072063c32621ff08d51f512a3bac53 parent b765df9edd4db791530f14c2e107aa40907fed1b author liuhui998 1300698655 +0800 committer liuhui998 1300698655 +0800 test branch modified
再来查看此分支里面所包含的数据(blob):
$cat refs/heads/test | xargs git cat-file -p | head -n 1 | cut -b6-15 | xargs git cat-file -p 100644 blob ebe01d6c3c2bbb74e043715310098d8da2baa4bf readme.txt
查看当前”readme.txt”文件里的内容:
$git cat-file -p ebe01d6 hello, world In test branch cd ..
我们再回到主分支里面:
$git checkout master Switched to branch 'master' $git checkout master $cat readme.txt hello, world
如我们想看看主分支(master)和测试分支(test)之间的差异,可以使用git diff命令来查看它们之间的diff:
$git diff test diff --git a/readme.txt b/readme.txt index ebe01d6..4b5fa63 100644 --- a/readme.txt +++ b/readme.txt @@ -1,2 +1 @@ hello, world -In test branch
大家可以以到当前分支与测试分支(test)相比,少了一行内容:“-In test branch”。
如果执行完git diff命令后认为测试分支(test)的修改无误,能合并时,可以用git merge命令把它合并到主分支(master)中:
$git merge test Updating b765df9..7f3c997 Fast-forward readme.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
“Updating b765df9..7f3c997”表示现在正在更新合并“b765df9”和“7f3c997”两个提交(commit)之间的内容;“b765df9”代表着主分支(master),“7f3c997”代表测试分支(test)。
“Fast-forward”在这里可以理解为顺利合并,没有冲突。“readme.txt | 1 +”表示这个文件有一行被修改,“1 files changed, 1 insertions(+), 0 deletions(-)”,表示这一次合并只有一个文件被修改,一行新数据插入,0 行被删除。
我们现在看一下合并后的“readme.txt”的内容:
$cat readme.txt hello, world In test branch
内容没有错,是“master”分支和“test”分支合并后的结果,再用“git status”看一下,当前工作目录的状态也是干净的(clean)。
$git status # On branch master nothing to commit (working directory clean)
好的,现在测试分支(test)结束了它的使命,没有存在的价值的,可以用“git branch -d”命令把这个分支删掉:
$git branch -d test Deleted branch test (was 61ce004).
如果你想要删除的分支还没有被合并到其它分支中去,那么就不能用“git branch -d”来删除它,需要改用“git branch -D”来强制删除。
评论暂时关闭