上次我们讲到git中的object: commit, tree和blob。一个commit指向了一个tree,这个tree就代表了我们所有文件的根目录。tree可以包含任意多个其他的tree以及blob, blob可以存储任意二进制序列,也就是文件内容。这非常像一个文件系统。
分支
Git中的分支是什么呢?我们知道当初始化一个git仓库后默认是在master分支上,查看一下.git/refs/master
1 2 |
$ cat .git/refs/heads/master c428c2cd998c5b91937f1398d2beecf4033a877f |
可以看到,分支其实就是记录了一个commit。这里的c428c2c就是我们最新的commit的SHA1.
下面我们创建一个dev分支
1 2 3 4 5 |
$ git branch dev $ git branch dev * master |
当前标记*表示我们目前处于 master分支,这个记录在.git/HEAD文件里
1 2 |
$ cat .git/HEAD ref: refs/heads/master |
可以发现,HEAD文件的内容是标记了一个reference,说明当前处于master分支。可以这么理解,HEAD指向某个分支,而分支指向某一个commit。
接下来我们在master上修改一下文件yalewoo.com.txt,然后提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
$ 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分支
1 2 |
$ git checkout dev Switched to branch 'dev' |
切换时,git将HEAD指向dev分支,并根据dev分支指向的commit替换当前工作区。你应该还记得,一个commit指向了一个类似根目录的tree对象,根据这个对象我们可以得到当前commit下的所有文件的内容。其实在git看来我们工作区的文件内容其实是并不重要的,因为每个文件的内容都被git存到了.git目录下的object中,我们可以随时切换到任意commit标记的状态,同时替换当前工作区的文件。
接下来我们在dev分支上修改yalewoo.com.txt文件并提交
1 2 3 |
$ 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
我们手动解决冲突后提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
$ 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的内容:
1 2 3 4 5 6 7 8 |
$ 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。