git 分支管理进阶

1. merge

命令:git merge A 

作用:把 A 分支 合并到当前分支 (此时当前分支新增了一次提交,指着指向该提交)

初始状态:

git 分支管理进阶_第1张图片

git merge bugFix 后:

git 分支管理进阶_第2张图片

此外,如果再把 main 分支合并到 bugFix 即(git checkout bugFix, git merge main)

git 分支管理进阶_第3张图片

此时,因为 main 继承自 bugFix,Git 什么都不用做,只是简单地把 bugFix 移动到 main 所指向的那个提交记录。现在所有提交记录的颜色都一样了,这表明每一个分支都包含了代码库的所有修改!

2. rebase

        作为第二种合并分支的方法,实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。Rebase 的优势就是可以创造更线性的提交历史(看起来像是按顺序开发,但实际上它们是并行开发的。),这听上去有些难以理解。如果只允许使用 Rebase 的话,代码库的提交历史将会变得异常清晰。

命令:git rebase A

作用:把当前分支  合并到 A分支 (此时A分支新增了一次提交,指针指向该提交)

初始状态:

git 分支管理进阶_第4张图片

git merge main 后:

git 分支管理进阶_第5张图片

 bugFix 分支上的工作在 main 的最顶端,同时我们也得到了一个更线性的提交序列。

注意,提交记录 C3 依然存在(树上那个半透明的节点),而 C3' 是我们 Rebase 到 main 分支上的 C3 的副本。

此外,有个问题就是 main 还没有更新,则可以: git checkout main , git rebase bugFix ,即

git 分支管理进阶_第6张图片

由于 bugFix 继承自 main,所以 Git 只是简单的把 main 分支的引用向前移动了一下而已。

3. 指针——分支切换

哈希值方式

        git 指针即上图中的 * ,一般用HEAD表示,指向某个分支的最后一次提交。

分离的 HEAD 就是让其指向了某个具体的提交记录而不是分支名。在命令执行之前的状态如下所示:HEAD 指向 main, main 指向 C1(HEAD -> main -> C1)

git 分支管理进阶_第7张图片

而 git checkout c1(c1 为某次提交记录的哈希值前几位,提交记录的哈希值一般很长,通过

git log 查看提交记录哈希值)则会变成如下图:

git 分支管理进阶_第8张图片

相对引用 

  1. 使用 ^ 向上移动 1 个提交记录(main^^ 是 main 的第二个 parent 节点)
  2. 使用 ~ 向上移动多个提交记录,如 ~3

例1:*原本在main处,切换到 main 的 parent 节点 (git checkout main^)git 分支管理进阶_第9张图片

也可以将 HEAD 作为相对引用的参照。*原本在main处,下面咱们就用 HEAD 在提交树中向上移动几次:git checkout C3,git checkout HEAD^,git checkout HEAD^,git checkout HEAD^ 

git 分支管理进阶_第10张图片

例2.1:使用~

初始状态 :

git 分支管理进阶_第11张图片

git checkout HEAD~4后:

git 分支管理进阶_第12张图片

例2.2

初始状态:

git 分支管理进阶_第13张图片

git branch -f main HEAD~3 将 main 分支强制指向 HEAD 的(前)第 3 级 parent 提交:

git 分支管理进阶_第14张图片

4.撤销

4.1 本地分支 撤销

git reset 通过把分支记录回退几个提交记录来实现撤销改动。你可以将这想象成“改写历史”。git reset 向上移动分支,原来指向的提交记录就跟从来没有提交过一样。

例1 初始状态:

git 分支管理进阶_第15张图片

git reset HEAD~1后:

git 分支管理进阶_第16张图片

Git 把 main 分支移回到 C1;现在我们的本地代码库根本就不知道有 C2 这个提交了。

(注意:在reset后, C2 所做的变更还在,但是处于未加入暂存区状态。)

4.2 远程分支 撤销

例2:初始状态

git 分支管理进阶_第17张图片

git revert HEAD (撤销当前分支main的一次提交)后:

git 分支管理进阶_第18张图片

此时,多了一个新提交记录 C2' 引入了更改 —— 这些更改刚好是用来撤销 C2 这个提交的。也就是说 C2' 的状态与 C1 是相同的。revert 之后就可以把你的更改推送到远程仓库撤销之前的提交。

5.Cherry-pick

       命令:git cherry-pick <提交号>...

        作用:将一些提交复制到当前所在的位置(HEAD)的下面

例子:将 side 分支上的一些提交,复制到 main 分支

初始状态:

git 分支管理进阶_第19张图片

git cherry-pick C2 C4后:

git 分支管理进阶_第20张图片

如果不记得提交记录的哈希值,可以利用交互式的 rebase

例子:假如之前在 newImage 分支上进行了一次提交,然后又基于它创建了 caption 分支,然后又提交了一次。此时你想对某个以前的提交记录进行一些小小的调整。比如设计师想修改一下 newImage 中图片的分辨率,尽管那个提交记录并不是最新的了。

方案:

  1. 先用 git rebase -i 将提交重新排序,然后把我们想要修改的提交记录挪到最前
  2. 然后用 git commit --amend 来进行一些修改(对之前的commit 提交进行修改,push后取代原来的commit)
  3. 接着再用 git rebase -i 来将他们调回原来的顺序
  4. 最后我们把 main 移到修改的最前端

初始状态

git 分支管理进阶_第21张图片

 git rebase -i HEAD~2 可以打开交互框,对前2次提交进行编辑(排序,取舍):

git 分支管理进阶_第22张图片

对提交记录进行调整后会出现一个新的分支

git 分支管理进阶_第23张图片

将后三步走完之后,效果如下:

git 分支管理进阶_第24张图片

6. 标签(锚点)

        分支很容易被人为移动,并且当有新的提交时,它也会移动。tag 可以永久地将某个特定的提交命名为里程碑(大版本),它们并不会随着新的提交而移动。你也不能切换到某个标签上面进行修改提交,它就像是提交树上的一个锚点,标识了某个特定的位置。如果你不指定提交记录,Git 会用 HEAD 所指向的位置。

命令:git tag v1 c1 给c1提交打上v1标签,如下:

git 分支管理进阶_第25张图片

Git Describe 能帮你在提交历史中移动了多次以后找到方向,用来描述离你最近的 tag

命令:git describe

 ref 可以是任何能被 Git 识别成提交记录的引用,如果你没有指定的话,Git 会使用你目前所在的位置(HEAD

输出:__g

tag 表示的是离 ref 最近的标签, numCommits 是表示这个 ref 与 tag 相差有多少个提交记录, hash 表示的是你所给定的 ref 所表示的提交记录哈希值的前几位

当 ref 提交记录上有某个标签时,则只 输出 标签名称。

例:初始状态:

git 分支管理进阶_第26张图片

git describe main 会输出: v1_2_gC2

git describe side  会输出:v2_1_gC4

你可能感兴趣的:(git)