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, 其父节点为 mainbranch-name 的最新提交记录所表示的结点(C2C3).

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

Rebase

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

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

C2C3的工作可以是并行的.

现在使用 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>

假设 C2C5 分支自共有父节点 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 中的提交进行修改, 就需要进行一些修改和排序.