Git深入学习

129 阅读5分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 9 天

Git学习|青训营笔记

首先了解几个概念 HEAD,main以及branch 在查看git log 后 QQ截图20230128210801.jpg

commit后面括号里的(HEAD -> main, origin/main, origin/HEAD),均是指向commit的引用,黄色字符串为每个commit的唯一SHA-1校验和,可以用校验和来指代某个commit,但这样表达过于繁琐,因此Git 提供了「引用」的机制:使用固定的字符串作为引用,指向某个 commit,作为操作 commit 时的快捷方式。

HEAD:当前commit的引用

HEAD 是引用中最特殊的一个:它是指向当前 commit 的引用。即当前工作目录所对应的 commit

每次当有新的 commit 的时候,工作目录自动与最新的 commit 对应;而与此同时,HEAD 也会转而指向最新的 commit

总之,当前 commit 在哪里,HEAD 就在哪里,这是一个永远自动指向当前 commit 的引用,所以永远可以用 HEAD 来操作当前 commit

branch

branch是Git中另一类引用。

HEAD 除了可以指向 commit,还可以指向一个 branch,当它指向某个 branch 的时候,会通过这个 branch 来间接地指向某个 commit;另外,当 HEAD 在提交时自动向前移动的时候,它会像一个拖钩一样带着它所指向的 branch 一起移动。

例如上面的那张图里,HEAD -> master 中的 master 就是一个 branch 的名字,而它左边的箭头 -> 表示 HEAD 正指向它(当然,也会间接地指向它所指向的 commit)。

下图为再次git commit 后的git log QQ截图20230128212040.jpg 可以看到最新的commit被创建后,HEAD指向main,main指向当前commit,而origin/main, origin/HEAD仍在原处

main:默认branch

main是特殊branch,是Git的默认branch,有以下特点:

  1. 新创建的 repository(仓库)是没有任何 commit 的。但在它创建第一个 commit 时,会把 master 指向它,并把 HEAD 指向 master
  2. 当有人使用 git clone 时,除了从远程仓库把 .git 这个仓库目录下载到工作目录中,还会 checkout (签出) mastercheckout 的意思就是把某个 commit 作为当前 commit,把 HEAD 移动过去,并把工作目录的文件内容替换成这个 commit 所对应的内容)。

大多数的开发团队会规定开发以 master 为核心,所有的分支都在一定程度上围绕着 master 来开发。这个在事实上构成了 master 和其它分支在地位上的一个额外的区别。

branch的创建,切换和删除

创建branch

想在某处创建branch,输入git branch 名称,例如在main上创建分支feature1

git branch feature1

切换branch

新建的 branch 并不会自动切换, HEAD 在这时依然是指向 master 的。需要用 checkout 来主动切换到新 branch 去:

git checkout feature1

然后 HEAD 就会指向新建的 branch 了:

除此之外,可以用 git checkout -b 名称 来把上面两步操作合并执行。

这行代码可以用指定的名称创建 branch 后,再直接切换过去。以 feature1 为例的话,就是:

git checkout -b feature1

在切换到新的 branch 后,再次 commit 时 HEAD 就会带着新的 branch 移动了

而这个时候,如果再切换到 master 去 commit,就会真正地出现分叉了:

git checkout master 
... git 
commit

删除branch

删除 branch 的方法非常简单:git branch -d 名称。例如要删除 feature1 这个 branch:

git branch -d feature1

删除时需要注意:

  1. HEAD 指向的 branch 不能删除。如果要删除 HEAD 指向的 branch,需要先用 checkout 把 HEAD 指向其他地方。
  2. 由于 Git 中的 branch 只是一个引用,所以删除 branch 的操作也只会删掉这个引用,并不会删除任何的 commit。(不过如果一个 commit 不在任何一个 branch 的「路径」上,或者换句话说,如果没有任何一个 branch 可以回溯到这条 commit,那么在一定时间后,它会被 Git 的回收机制删除掉。)
  3. 出于安全考虑,没有被合并到 master 过的 branch 在删除时会失败(因为怕误删掉「未完成」的 branch )
    这种情况如果确认是要删除这个 branch (例如某个未完成的功能被团队确认永久毙掉了,不再做了),可以把 -d 改成 -D,小写换成大写,就能删除了。

「引用」的本质

所谓「引用」(reference),其实就是一个个的字符串。这个字符串可以是一个 commit 的 SHA-1 码(例:c08de9a4d8771144cd23986f9f76c4ed729e69b0),也可以是一个 branch(例:ref: refs/heads/feature3)。

Git 中的 HEAD 和每一个 branch 以及其他的引用,都是以文本文件的形式存储在本地仓库 .git 目录中,而 Git 在工作的时候,就是通过这些文本文件的内容来判断这些所谓的「引用」是指向谁的。

总结

  1. HEAD 是指向当前 commit 的引用,它具有唯一性,每个仓库中只有一个 HEAD。在每次提交时它都会自动向前移动到最新的 commit 。

  2. branch 是一类引用。HEAD 除了直接指向 commit,也可以通过指向某个 branch 来间接指向 commit。当 HEAD 指向一个 branch 时,commit 发生时,HEAD 会带着它所指向的 branch 一起移动。

  3. master 是 Git 中的默认 branch,它和其它 branch 的区别在于:

    1. 新建的仓库中的第一个 commit 会被 master 自动指向;
    2. 在 git clone 时,会自动 checkout 出 master
  4. branch 的创建、切换和删除:

    1. 创建 branch 的方式是 git branch 名称 或 git checkout -b 名称(创建后自动切换);
    2. 切换的方式是 git checkout 名称
    3. 删除的方式是 git branch -d 名称