目录
Git用法基础篇在上一篇文章中 Learn Git Branching 学习笔记(基础篇)_流年--by gone的博客-CSDN博客
这篇文章主要来介绍Git更为高级的用法,Git超棒的一些特性
一、高级篇
1.在提交树上移动
在接触git更高级功能之前,我们有必要先学习在项目的提交树上前后移动的几种方法。一旦熟悉了如何在GIt提交树上移动,驾驭其他命令的能力也将水涨船高。
我们首先看一下“HEAD”。HEAD是一个对当前检出记录的符号引用——也就是指向正在其基础上工作的提交记录。
HEAD总是指向当前分支上最近一次提交记录。大多数修改提交书的Git命令都是从改变HEAD指向开始的。
HEAD通常情况下是指向分支名的(如bugFix)。在提交时,改变了bugFix的状态,这一变化通过HEAD变得可见。
下面通过实际操作看一下,会观察提交前后HEAD的位置。
git checkout C1
git checkout main //切到main上
git commit //生成C2节点
git checkout C2 //HEAD指向C2
HEAD指向了main,随着提交向前移动。其实这些命令并不是真的在查看HEAD指向,如果想看HEAD指向,可以通过cat,git/HEAD查看,如果HEAD指向的是一个引用,还可以用git symbolic-ref HEAD查看它的指向。但该程序不支持两个命令。
分离的HEAD就是让其指向了某个具体的提交记录而不是分支名。在命令执行之前的状态如下所示:
HEAD -> main -> C1(HEAD指向main,main指向C1)
git checkout C1
现在变成了HEAD ->C1
题目:
想完成此关,从 bugFix 分支中分离出 HEAD 并让其指向一个提交记录。
通过哈希值指定提交记录,每个提交记录的哈希值显示在代表提交记录的圆圈中。
答案:
git checkout C4
2.相对引用^
通过指定提交记录哈希值的方式在Git中移动不太方便。在实际应用中,并没有像本程序这么漂亮的可视化提交树供你参考,所以你就不得不用git log来查看提交记录的哈希值。并且哈希值在真实的Git世界中也会更长(基于SHA-1,共40位)。比较令人欣慰的是,Git对哈希的处理很智能,秩序提供唯一标识提交记录的前几个字符即可,因此可以仅输入fed2而不是上面的一长串字符。
由于通过哈希值指定提交记录很不方便,所以Git引入了相对引用。这个就很厉害了。使用相对引用的话,可以从一个易于记忆的地方(比如bugFix分支或者HEAD)开始计算。
两种简单的用法:
1.使用^向上移动1个提交记录
2.使用~<num>向上移动多个提交记录,如~3
首先看看操作符(^)。把这个符号加在引用名称的后面,表示让Git寻找指定提交记录的夫提交。所以main^相当于main的父节点,main^^是main的第二个父节点。
git checkout main ^(切换到main的父节点)
可以将HEAD作为相对引用的参照,下面就用HEAD再提交树上向上移动几次。
git checkout C3 //HEAD指向C3
git checkout HEAD^ //HEAD指向之前HEAD的上一级
git checkout HEAD^
git checkout HEAD^
可以用HEAD^向上移动。
实际中,提交的节点哈希值不会是C0/C1/C2这么简单的数值,而是40位的...所以还是用相对引用简单。
git checkout master^ //寻找指定提交记录的父提交
git checkout master^^ //寻找指定提交记录的父父提交
题目:
要完成此关,切换到 bugFix 的父节点。这会进入"分离 HEAD 状态"。请尽量使用相对引用。
我的答案:
git checkout C4 //HEAD指向C4
git checkout HEAD^ //HEAD指向之前HEAD的上一级
答案:
git checkout C3 //HEAD指向C3
3.相对引用~
如果想在提交树中向上移动很多步的话,敲很多^貌似也挺烦人的,git也考虑到了这一点,于是又引入了操作符~。该操作符后面可以跟一个数字(可选,不跟数字时与^相同,向上移动一次),指定向上移动多少次。
git checkout HEAD~4 //HEAD节点指向之前HEAD指向的第四级父提交
强行修改分支位置:使用相对引用最多的就是移动分支,可以直接使用-f选项让分支指向另一个提交。例如:git branch -f main HEAD~3,这条命令会将main分支强制指向HEAD的第3级父提交。
git branch -f main HEAD~3 //将main分支强制指向HEAD的第3级父提交
相对引用为我们提供了一种简洁的引用提交记录C1的方式,而-f则容许我们将分支强制移动到那个位置。
题目:
要完成此关,移动HEAD,main和bugFix到目标所示的位置。
答案:
git checkout C1 //HEAD指向C1
git branch -f bugFix HEAD^ //分支bugFix指向HEAD的上一级
git branch -f master C6 //分支master直接指向C6
4.版本回退(reset&revert)
在git里撤销变更的方法很多,和提交一样,撤销变更由底层部分(暂存区的独立文件或者片段)和上层部门(变更到底是通过哪种方式被撤销的)组成。我们这个应用主要关注的是后者。
主要有两种方法用来撤销变更——一是git reset,还有就是git revert,接下来咱们逐个进行讲解。
Git Reset
git reset通过把分支记录回退几个提交记录来实现撤销改动。你可以将这想象成“改写历史”。git reset向上移动分支,原来指向的提交记录就跟从来没有提交过一样。
git reset HEAD~1 //向上移动
Git把main分支移回到C1;现在我们的本地代码库根本就不知道有C2这个提交了。(在reset后,C2所做的变更还在,但是处于未加入暂存区状态。)
Git Revert
虽然在你的本地分支中使用 git reset 很方便,但是这种“改写历史”的方法对大家一起使用的远程分支是无效的!
为了撤销更改并分享给别人,我们需要使用 git revert。
git revert HEAD
在我们要撤销的提交记录后面多出一个新提交!这是因为新提交记录 C2' 引入了更改 —— 这些更改刚好是用来撤销 C2 这个提交的。也就是说 C2' 的状态与 C1 是相同的。revert 之后就可以把你的更改推送到远程仓库与别人分享啦。
如果C2后边还有C3,C4等等提交,C3,C4的修改不会动,仅仅是撤销C2的这次提交修改的内容!并在C4后边生成新的提交(撤销C2的修改)。
题目:
要完成此关,分别撤销 local 分支和 pushed 分支上的最近一次提交。共需要撤销两个提交(每个分支一个)。
记住 pushed 是远程分支,local 是本地分支 —— 这么说你应该知道用分别哪种方法了吧?
答案:
git reset HEAD^ //撤销本地分支用reset
git checkout pushed
git revert HEAD //撤销远程分支用revert
高级篇完结撒花~