05-HEAD、master 与 branch
引用commit 的快捷方式首先再看一次loggit log第一行的commit后面括号里的HEAD - master, origin/master, origin/HEAD是几个指向这个commit的引用。在 Git 的使用中经常会需要对指定的commit进行操作。每一个commit都有一个它唯一的指定方式——它的 SHA-1 校验值也就是上图中每个黄色的commit右边的那一长串字符。两个 SHA-1 值的重复概率极低所以你可以使用这个 SHA-1 值来指代commit也可以只使用它的前几位来指代它例如第一个78bb0ab7d541…16b77你使用78bb0ab甚至78bb来指代它通常也可以但毕竟这种没有任何含义的字符串是很难记忆的所以 Git 提供了「引用」的机制使用固定的字符串作为引用指向某个commit作为操作commit时的快捷方式。HEAD当前 commit 的引用上一段里说到图中括号里是指向这个commit的引用。其中这个括号里的HEAD是引用中最特殊的一个它是指向当前commit的引用。所谓当前commit这个概念很简单它指的就是当前工作目录所对应的commit。例如上图中的当前commit就是第一行中的那个最新的commit。每当有新commit时工作目录自动与最新的commit对应而与此同时HEAD也会转而指向最新的commit。事实上当使用checkout、reset等指令手动指定改变当前commit的时候HEAD也会一起跟过去。总之当前commit在哪里HEAD就在哪里这是一个永远自动指向当前commit的引用所以你永远可以用HEAD来操作当前commit。branchHEAD是 Git 中一个独特的引用它是唯一的。而除了HEAD之外Git 还有一种引用叫做branch分支。HEAD除了可以指向commit还可以指向一个branch当它指向某个branch的时候会通过这个branch来间接地指向某个commit另外当HEAD在提交时自动向前移动的时候它会像一个拖钩一样带着它所指向的branch一起移动。例如上面的那张图里HEAD-master中的master就是一个branch的名字而它左边的箭头-表示HEAD正指向它当然也会间接地指向它所指向的commit。如果我在这时创建一个commit那么HEAD会带着master一起移动到最新的commitgit commit通过查看log可以对这个逻辑进行验证git log从图中可以看出最新的commit提交信息Add feature1被创建后HEAD和master这两个引用都指向了它而在上面第一张图中的后两个引用origin/master和origin/HEAD则依然停留在原先的位置。master: 默认 branch上面的这个master其实是一个特殊的branch它是 Git 的默认branch俗称主branch/ 主分支。所谓的「默认branch」主要有两个特点新创建的 repository仓库是没有任何commit的。但在它创建第一个commit时会把master指向它并把HEAD指向master。当有人使用git clone时除了从远程仓库把.git这个仓库目录下载到工作目录中还会checkout签出mastercheckout的意思就是把某个commit作为当前commit把HEAD移动过去并把工作目录的文件内容替换成这个commit所对应的内容。另外需要说一下的是大多数的开发团队会规定开发以master为核心所有的分支都在一定程度上围绕着master来开发。这个在事实上构成了master和其它分支在地位上的一个额外的区别。branch 的通俗化理解尽管在 Git 中branch只是一个指向commit的引用但它有一个更通俗的理解你还可以把一个branch理解为从初始commit到branch所指向的commit之间的所有commits 的一个「串」。例如下面这张图master的本质是一个指向3的引用但你也可以把master理解为是123三个commit的「串」它的起点是1终点是3。这种理解方式比较符合branch这个名字的本意branch的本意是树枝可以延伸为事物的分支也是大多数人对branch的理解。不过如果你选择这样理解branch需要注意下面两点所有的branch之间都是平等的。例如上面这张图branch1是1256的串而不要理解为256或者56。其实起点在哪里并不是最重要的重要的是你要知道所有branch之间是平等的master除了上面我说的那几点之外并不比其他branch高级。这个认知的理解对于branch的正确使用非常重要。换个角度来说上面这张图我可以用别的画法来表达它们的意思是一样的通过这张动图应该能够对「平等」这个概念更好地理解了吧branch包含了从初始commit到它的所有路径而不是一条路径。并且这些路径之间也是彼此平等的。像上图这样master在合并了branch1之后从初始commit到master有了两条路径。这时master的串就包含了12347和12567这两条路径。而且这两条路径是平等的12347这条路径并不会因为它是「原生路径」而拥有任何的特别之处。如果你喜欢用「树枝」的概念来理解 Git 的branch一定要注意上面说的这两点否则在今后使用branch的时候就可能与出现理解偏差或者使用方式不当的问题。事实上我本人并不喜欢用这种方式来理解branch因为觉得它有点舍近求远的味道我为了「直观」地思考给它了一个形象的比喻但由于它的本质含义其实更加简单导致我的这种比喻反而增加了思考它时的复杂度未免有点画蛇添足。不过这是我自己的感受怎么理解branch是个个人偏好的问题这两种理解方式你选一个喜欢的就好。branch 的创建、切换和删除创建 branch如果你想在某处创建branch只需要输入一行git branch 名称。例如你现在在master上你想在这个commit处创建一个叫做 feature1 的branch只要输入git branch feature1你的branch就创建好了切换 branch不过新建的branch并不会自动切换你的HEAD在这时依然是指向master的。你需要用checkout来主动切换到你的新branch去git checkout feature1然后HEAD就会指向新建的branch了除此之外你还可以用git checkout -b 名称来把上面两步操作合并执行。这行代码可以帮你用指定的名称创建branch后再直接切换过去。还以feature1为例的话就是git checkout -b feature1在切换到新的branch后再次commit时HEAD就会带着新的branch移动了git commit而这个时候如果你再切换到master去commit就会真正地出现分叉了git checkout master git commit删除 branch删除branch的方法非常简单git branch -d名称。例如要删除feature1这个branchgit branch -d feature1需要说明HEAD指向的branch不能删除。如果要删除HEAD指向的branch需要先用checkout把HEAD指向其他地方。由于 Git 中的branch只是一个引用所以删除branch的操作也只会删掉这个引用并不会删除任何的commit。不过如果一个commit不在任何一个branch的「路径」上或者换句话说如果没有任何一个branch可以回溯到这条commit也许可以称为野生commit那么在一定时间后它会被 Git 的回收机制删除掉。出于安全考虑没有被合并到master过的branch在删除时会失败因为怕你误删掉「未完成」的branch啊这种情况如果你确认是要删除这个branch例如某个未完成的功能被团队确认永久毙掉了不再做了可以把-d改成-D小写换成大写就能删除了。引用」的本质所谓「引用」reference其实就是一个个的字符串。这个字符串可以是一个commit的 SHA-1 码例c08de9a4d8771144cd23986f9f76c4ed729e69b0也可以是一个branch例ref: refs/heads/feature3。Git 中的HEAD和每一个branch以及其他的引用都是以文本文件的形式存储在本地仓库.git目录中而 Git 在工作的时候就是通过这些文本文件的内容来判断这些所谓的「引用」是指向谁的。小结这一节介绍了 Git 中的一些「引用」HEAD、master、branch。这里总结一下HEAD是指向当前commit的引用它具有唯一性每个仓库中只有一个HEAD。在每次提交时它都会自动向前移动到最新的commit。branch是一类引用。HEAD除了直接指向commit也可以通过指向某个branch来间接指向commit。当HEAD指向一个branch时commit发生时HEAD会带着它所指向的branch一起移动。master是 Git 中的默认branch它和其它branch的区别在于新建的仓库中的第一个commit会被master自动指向在git clone时会自动checkout出master。branch的创建、切换和删除创建branch的方式是git branch名称或git checkout -b 名称创建后自动切换切换的方式是git checkout 名称删除的方式是git branch -d名称。

相关新闻