上次我们讲到git中的object: commit, tree和blob。一个commit指向了一个tree,这个tree就代表了我们所有文件的根目录。tree可以包含任意多个其他的tree以及blob, blob可以存储任意二进制序列,也就是文件内容。这非常像一个文件系统。

分支
Git中的分支是什么呢?我们知道当初始化一个git仓库后默认是在master分支上,查看一下.git/refs/master
$ cat .git/refs/heads/master c428c2cd998c5b91937f1398d2beecf4033a877f
可以看到,分支其实就是记录了一个commit。这里的c428c2c就是我们最新的commit的SHA1.
下面我们创建一个dev分支
$ git branch dev $ git branch dev * master
当前标记*表示我们目前处于 master分支,这个记录在.git/HEAD文件里
$ cat .git/HEAD ref: refs/heads/master
可以发现,HEAD文件的内容是标记了一个reference,说明当前处于master分支。可以这么理解,HEAD指向某个分支,而分支指向某一个commit。

接下来我们在master上修改一下文件yalewoo.com.txt,然后提交
$ git commit -m "change yalewoo.txt in master"
[master 11f11b7] change yalewoo.txt in master
1 file changed, 1 insertion(+)
$ git log
commit 11f11b7127675cc9e0f7f88acc72d8597848065d (HEAD -> master)
Author: yalewoo <chongruyuntian@163.com>
Date: Mon Sep 16 19:53:19 2019 +0800
change yalewoo.txt in master
commit c428c2cd998c5b91937f1398d2beecf4033a877f (dev)
Author: yalewoo <chongruyuntian@163.com>
Date: Sun Sep 15 11:05:37 2019 +0800
change blogs.txt
commit 606b6c3d7e55733783be97b7fc2b929eaa3b790c
Author: yalewoo <chongruyuntian@163.com>
Date: Sun Sep 15 10:37:43 2019 +0800
first commit
提交commit时,git根据HEAD得知当前所在分支,然后修改分支指向最新的commit

接下来我们切换到dev分支
$ git checkout dev Switched to branch 'dev'
切换时,git将HEAD指向dev分支,并根据dev分支指向的commit替换当前工作区。你应该还记得,一个commit指向了一个类似根目录的tree对象,根据这个对象我们可以得到当前commit下的所有文件的内容。其实在git看来我们工作区的文件内容其实是并不重要的,因为每个文件的内容都被git存到了.git目录下的object中,我们可以随时切换到任意commit标记的状态,同时替换当前工作区的文件。

接下来我们在dev分支上修改yalewoo.com.txt文件并提交
$ git commit -m "change yalewoo.txt in dev" [dev 1c4be07] change yalewoo.txt in dev 1 file changed, 1 insertion(+)
现在的状态是这样的

Merge
下面我们回到master分支然后合并dev分支。yalewoo.com.txt出现了conflict

我们手动解决冲突后提交
$ git add details/yalewoo.com.txt
$ git commit -m "resolve conflict"
[master d2b4705] resolve conflict
Yalewoo@DESKTOP-DU53APD MINGW64 /d/code/learngit (master)
$ git log
commit d2b4705c6609219e43c0f44b110b5aaec6763553 (HEAD -> master)
Merge: 11f11b7 1c4be07
Author: yalewoo <chongruyuntian@163.com>
Date: Mon Sep 16 20:13:06 2019 +0800
resolve conflict
commit 1c4be07a121cc786a0426fdf9f2685d0e9a90c1e (dev)
Author: yalewoo <chongruyuntian@163.com>
Date: Mon Sep 16 20:05:36 2019 +0800
change yalewoo.txt in dev
commit 11f11b7127675cc9e0f7f88acc72d8597848065d
Author: yalewoo <chongruyuntian@163.com>
Date: Mon Sep 16 19:53:19 2019 +0800
change yalewoo.txt in master
commit c428c2cd998c5b91937f1398d2beecf4033a877f
Author: yalewoo <chongruyuntian@163.com>
Date: Sun Sep 15 11:05:37 2019 +0800
。可以看到新产生了一个commit,使用git cat-file可以查看该commit的内容:
$ git cat-file d2b4705 -p tree 09b3794aefad8da2a2639632f264f1e9590c6a53 parent 11f11b7127675cc9e0f7f88acc72d8597848065d parent 1c4be07a121cc786a0426fdf9f2685d0e9a90c1e author yalewoo <chongruyuntian@163.com> 1568635986 +0800 committer yalewoo <chongruyuntian@163.com> 1568635986 +0800 resolve conflict
可以看到,merge的结果其实是也一个commit,他有两个parent,表示merge的两个分支。

之后当你切换回dev分支,在dev上合并master分支时,由于在master上已经合并过,因此会进行fast forward模式,不创建新的commit而是直接指向已有的commit d2b4705.
这次就到这里啦,下次小乐会和大家分享git rebase。
支付宝打赏
微信打赏