get commit 

在当前分支创建一个提交记录

分支

创建新分支

git branch <branch-name>

创建分支后直接使用

git commit

并不会在新分支产生提交记录, 这是因为没有切换到新分支.

git 工具会使用*来提示你目前所在的分支.

git checkout <branch-name>

切换到名为 branch-name 的分支, 这个时候提交就可以在该分支下产生新提交记录了.

把这两个功能整合起来的命令:

git checkout -b <branch-name>

合并

对于同一父节点有着不同的分支, 这两个分支表示各有一个独立提交.

把branch-name 合并到 main 里:

git merge <branch-name>

这会产生一个新节点 C4, 其父节点为 main 和 branch-name 的最新提交记录所表示的结点(C2和C3).

在此基础上再将 main 合并到 branch-name, 因为此时 main 继承自 branch-name, 所以只会把 branch-name 代表的指针移动到最后产生的结点(C4)

Rebase

这是另一种合并分支的方法, 就是去除一系列的提交记录, 将其在另一个地方逐一执行. 这可以让代码库的提交历史变得更清晰.

假设 main 和 bugFix 的分支自结点C1, 各自的最新提交记录结点为 C2 和 C3, 目前所在分支是 bugFix.

C2 和 C3的工作可以是并行的.

现在使用 rebase 命令实现合并, 这会使得两个分支的功能像是顺序实现的.

git rebase main

这会产生一个新结点C3', 其父节点为 C2, main 停留在 C2, bugFix 停留在 C3', 目前所在分支仍然为 bugFix.

现在我们需要使 main 得到更新:

git checkout main;git merge bugFix;

因为 bugFix 继承自 main, 所以git 要做到以上指令, 只需要将 main 指针移动到 C3' 即可.

目前所在分支为 main.

分离

如何在提交树上移动?

Head 是一个对当前分支的符号引用, 它用来指代当前分支的最新提交记录. 这也意味着 Head 会随着你的提交而更新.

现在我们要让 HEAD 指向 具体的提交记录而并非分支名.

假设这样一个状态:main*指针指向最新提交记录C1, HEAD 指向 main.

即

HEAD -> main -> C1

我们执行命令:

git checkout C1

这样就变成了

HEAD -> C1

当然在具体的操作实践中, 结点的记录不会像 C1 这样简单, 而是一个更复杂的哈希值(可以长达40位!).

相对引用

Git 对于哈希值的处理有一定的智能, 它允许你可以只使用哈希值的前几个字符来指代对应的提交记录, 而无需将哈希值完整写出.

你可以通过

git log

来查看提交记录的哈希值.

如果是通过相对引用, 就可以不用使用哈希值.

两种常见的移动方法:

  • 使用^向上移动一个提交记录

    具体用法是将^加在引用名称的后面, 比如

    git checkout main^
    

    将 HEAD 切换到 main 的父节点.

    HEAD 本身也可以作为引用名称的对象.

  • 使用~<num>向上移动 num 个提交记录

    git checkout HEAD~4
    

    这将使得 HEAD 指针移到 HEAD 的第四个父节点.

使用 -f 来让分支指向另一个提交.(-f 代表强制)

git branch -f main HEAD~3

这会将 main 分支强制指向 HEAD 的第3级父提交.

撤销变更

有两种实现方法:

  • git reset

    这会使得提交记录回溯, 原来指向的提交记录会被代码库忽略.

    但是原提交记录所作出变更还在, 只是没有加入暂存区.

    这个只适用于本地代码库, 对于远程分支是无效的.

  • git revert C2

    为了将撤销更改分享给别人, 需要用到这个指令.

    这会产生一个新的提交记录结点C2', 这个更改是用来撤销C2的. 即 C2' 状态也就是 C1.

注意辨别两个指令在使用的时候所使用的坐标是谁.

整理提交记录

现在我们需要处理更复杂的工作流了.

git cherry-pick <commit>

假设 C2 和 C5 分支自共有父节点 C1, 而C2后的提交记录分别是C3, C4.

现在main指针指向 C5, side 指针指向 C4. 且当前所在分支为main.(git 工具会提示你main*)

我们执行

git cherry-pick C2 C4

这会使得 C5 后依次出现新提交记录 C2' 和 C4', 并且 main* 指向C4'.

交互式 rebase

在我们并不清楚提交记录的哈希值的时候, git 提供了一个方法.

--interactive 或者 -i, 这会使 Git 打开一个 UI 界面并列出提交记录的哈希值和提交说明.

在实际操作中, 这个 UI 窗口可能仅仅只是一个文本编辑器中的界面. VS Code 中的代码管理会比这个更人性化一些.

具体来说里面有若干个提交记录, 通过鼠标点击拖动来调整或者忽略这些结点顺序.

只取一个提交记录

为了调试而在代码中添加了一些调试命令, 这部分代码在正式的 使用中显然是不会用到的.

实际上我们只需要'刚好能解决问题并且没有任何调试代码'的那一个提交记录就可以了.

我们可以借助之前所学的命令来达成这一目的.

  • git rebase -i

  • git cherry-pick

git checkout main;
git cherry-pick bugFix;

或者

git rebase -i main bugFix;
git branch -f main HEAD

提交的技巧

假设在 newImage 分支进行了一次提交, 又在这个提交基础上创建了 caption 分支, 然后又在 caption 分支上进行了一次提交.

现在如果要对 newImage 中的提交进行修改, 就需要进行一些修改和排序.