Git基础篇(二十五)——rebase指令

前言:
   rebase指令是git中功能较为复杂的一个指令,用好了可以简化提交记录。

1 rebase

   rebase 可对一段连续的提交记录进行修改、删除、复制粘贴、合并操作,规范的使用该指令能使得提交记录更加干净整洁。

1.1 指定格式

  指令格式如下。

1
git rebase -i [StartPoint] [EndPoint]
  • -i : 是指令 --interactive 的缩写,即弹出交互式界面让用户选择具体的执行动作;
  • [StartPoint] : 指定一段提交记录的起点,但不包含该提交记录;
  • [EndPoint] : 指定一段提交记录的终点,包含该提交记录。提交时间上不能比StartPoint指定的提交记录早;

1.2 选择提交记录

  假设有以下提交记录,提交记录的选择有多种方式,可以通过git提交时为每个提交记录生成的唯一 commit id 指定,或者用 HEAD 的形式等。在git中区间的指定都是左开右闭, [EndPoint] 可以省略,表示到分支的最新提交记录。选择的提交记录必须是同一分支上连续的提交记录。
  假设有以下提交记录,我们我们要选择 f56ce4e13779c0 两个提交记录。可编辑如下指令。

Git基础篇(二十五)——rebase指令

前言:
   rebase指令是git中功能较为复杂的一个指令,用好了可以简化提交记录。

1 rebase

   rebase 可对一段连续的提交记录进行修改、删除、复制粘贴、合并操作,规范的使用该指令能使得提交记录更加干净整洁。

1.1 指定格式

  指令格式如下。

1
git rebase -i [StartPoint] [EndPoint]
  • -i : 是指令 --interactive 的缩写,即弹出交互式界面让用户选择具体的执行动作;
  • [StartPoint] : 指定一段提交记录的起点,但不包含该提交记录;
  • [EndPoint] : 指定一段提交记录的终点,包含该提交记录。提交时间上不能比StartPoint指定的提交记录早;

1.2 选择提交记录

  假设有以下提交记录,提交记录的选择有多种方式,可以通过git提交时为每个提交记录生成的唯一 commit id 指定,或者用 HEAD 的形式等。在git中区间的指定都是左开右闭, [EndPoint] 可以省略,表示到分支的最新提交记录。选择的提交记录必须是同一分支上连续的提交记录。
  假设有以下提交记录,我们我们要选择 f56ce4e13779c0 两个提交记录。可编辑如下指令。

main.png

1
git rebase -i 1fc8a58 13779c0

  由于区间的选择是左开右闭的,因此这里选择的 [StartPoint] 要比实际需要的提交记录提前一个节点。

1
git rebase -i f56ce4e^ 13779c0

  也可以使用 ^ 符号,表示在该提交记录的基础上回退一个节点。

1
git rebase -i HEAD~3 HEAD~1

  如果 HEAD 指针在所操作分支上,也可使用通过HEAD进行区间选择。

1
git rebase -i StartPoint^ EndPoint

  如果提交记录被打上tag,则可以通过tag指定区间。

1.3 命令种类

  执行 rebase -i 指令后可看到如下界面。

Cmd.png

  常用指令介绍如下。

  • pick : 简写为 p ,保留提交记录;
  • reword : 简写为 r ,保留提交记录但编辑提交信息;
  • edit : 简写为 e ,保留提交记录但要停下来进行 amend 修改;
  • squash : 简写为 s ,与前一个提交记录合并;
  • fixup : 简写为 f ,与前一个提交记录合并,但要停下来修改提交信息;
  • exec : 简写为 x ,执行shell命令;
  • drop : 简写为 d ,舍弃本地提交记录;

2 修改

  在之前的文章中介绍过 amend 指令的用法,它可以对分支的最新提交记录进行修改,不会产生新的提交记录,若想对任意提交记录进行修改则可使用 rebase 指令的 edit 指令。 reword 指令是只对任意提交记录的提交信息进行修改,文件和目录保持不变,用法同 amend ,下面以 amend 指令来讲解。
  以下演示对 StartPointEndPoint 提交记录的修改,执行以下指令。

1
git rebase -i f56ce4e^ 13779c0

  将选择要对节点执行的指令,默认为 pick ,节点是按时间排序的,从上到下对应从旧到新的提交。要对这两次提交记录进行修改,因此将 pick 改为 edit 或简写为 e

1
2
edit f56ce4e main-2
edit 3643500 main-3

  编辑完成后在Vim模式输入指令 :wq 即可开始执行指令。此时可看到终端显示如下信息,会依照从旧到新的顺序停下来让用户逐一对使用 edit 的提交记录进行修改,可修改文件也可修改提交信息。

git_rebase_edit_1.png

  需要配合 git addgit commit --amend 指令对当前提交记录进行修改,完成修改后还需执行以下指令推动rebase下一步骤进行。

1
git rebase --continue

  此时可以看到终端显示如下信息。

git_rebase_edit_2.png

  中间可能出现冲突,比如不同提交记录对同一个文件做了不同修改,有冲突解决冲突即可。
  需要注意的是,git中每个提交记录都是基于上一个提交记录的基础上修改的,如果你对中间某个提交记录进行了修改,那必然会对该分支上该提交记录之后所有的提交记录产生影响,所以这种修改方式非常容易出现冲突。因此建议对中间某个节点修改时,应该对之后所有的节点也都使用 edit 指令进行一一修改。否则,只对中间某些提交记录进行修改,之后的修改记录会从分支中“舍弃”,但该舍弃不是完全删除,使用 git log --allgit reflog 依然可以看到原来的提交记录。

2.1 从中间修改到最新

  使用以下指令修改 main 分支从 f56ce4e13779c0 最新提交记录。

1
git rebase -i f56ce4e

  对提交记录一路修改后通过log可看到如下信息。

git_rebase_edit_log.png

  从log可以看到main分支出现了两个分支,旧的支路默认是不可见的,可在log全显下看到。

2.2 只修改中间

  只修改中间的提交记录,会导致原本分支的修改关系被打破,因此git将会为新的修改创建一个游离分支,游离分支复制原分支然后将修改在这个游离分支上进行,由于提交记录的逻辑的逻辑关系被打破,在游离分支上修改记录之后的记录会被删除,用户可以创建一个新分支并且将游戏分支的提交记录合并到新分支上。

git_rebase_edit_log2.png

  当前分支处于游离分支时,使用指令 git branch <newbranch> 创建新分支,然后使用指令 git merge <newbranch> 将游离分支的记录合并到新分支上。可以将原分支删除然后再次创建同名分支,再将离散分支的记录合并回该分支上。更简单的方法是使用 git reset --hard <commit id> ,填写游离分支的最新节点的 commit id 号,以此来使main分支切换到另外一个子分支上。

3 删除

  使用指令 rebase 可以删除旧的历史提交。 rebase 指令的主要用法上面已经介绍清除,下面主要介绍几种具体应用场景,详细操作流程可参考第2章节。
  用指令 drop 修饰提交记录,可将对应的提交记录删除,与修改提交记录类似的,也有两种修改情况。

3.1 从中间删除到最新

  被 drop 修饰的提交记录都被删除。

3.2 只删除中间

  只删除中间提交记录,会破坏提交记录的逻辑关系,因为每次提交都是在上一个提交记录的基础上进行的,如果之前的提交不存在了,后续的提交也没有存在意义。删除中间的提交记录之后的提交也会被删除,因此git会为这种删除操作创建游离分支并且在游戏分支上进行,游离分支复制原分支然后将 drop 修饰的提交记录及其之后更新的提交记录一并删除。
  通过 drop 指令删除中间两个节点后log信息如下。

git_rebase_drop_log.png

  main分支只剩下删除记录之前的提交记录。当前分支处于游离分支时使用 git merge <newbranch> 将修改合并到新分支上。可以将原分支删除然后再次创建同名分支,再将离散分支的记录合并回该分支上。更简单的方法是使用 git reset --hard <commit id> ,填写游离分支的最新节点的 commit id 号,以此来使main分支切换到另外一个子分支上。

4 复制粘贴

  使用使用以下指令可将某分支的一段提交记录复制到其他分支上。复制到其他分支也分两种情况,复制到其他分支最新提交记录之后,或复制到其他分支中间提交记录之后。
  指令格式如下。

1
git rebase -i --onto [branch/ToPoint] [StartPoint] [EndPoint]

  该指令表示将 [StartPoint] [EndPoint] 区间的提交记录复制到 [branch/ToPoint] 所指的分支最新提交记录或所指某提交记录之后。不需对提交记录修改时 -i 指令可省略,此时是原样复制,若是带修改的复制则可配置 -i 指令,比如复制提交记录到其他分支但要进行修改,复制并合并提交记录到其他分支等。可能用的指令有 squash ,表示将该提交和前一个提交合并,而 fixup 表示该提交和前一个提交合并但不保留其提交信息。

4.1 复制到最新记录

  当 [branch/ToPoint] 写分支名时,表示将所选区间的提交记录复制到该分支的最新提交记录之后。需要 注意 的是,复制动作的源分支和目标分支如果是重合的,若复制后的状态仍然是两分支重合,git会将源分支复制记录之后的记录删除,目标分支的指针不变。此种需求不应进行操作,而是应直接移动目标分支的指针。

4.2 复制到中间记录

  插入式复制会破坏分支上原本的提交记录之间的逻辑关系,因此git会将插入位置之后的提交记录都删除掉。

5 合并

  通过 squashfixup 指令修饰,将对应提交记录合并与前一个提交记录合并,直到所选区间的第一提交记录,第一个提交记录可使用 pickrewordedit 修饰。同样的,合并也有两种情况,合并的区间是最新提交记录或是中间某一段提交记录。

5.1 合并最新提交记录

  按提交顺序,只所选区间的最旧提交记录保留,其他提交记录都选择与上一次提交合并,比如。

1
2
3
pick f56ce4e main-2
squash 3643500 main-3
squash 13779c0 main-4

  合并后最后会弹出提交信息编辑界面,会列出所有提交记录原本的提交信息,可在此基础上编辑。

5.2 合并中间提交记录

  同样的,将中间的提交记录合并会破坏原本提交记录之间的逻辑关系,因此git会将插入位置之后的提交记录都删除掉,并且这些操作都会在游离分支上。

1
git rebase -i 1fc8a58 13779c0

  由于区间的选择是左开右闭的,因此这里选择的 [StartPoint] 要比实际需要的提交记录提前一个节点。

1
git rebase -i f56ce4e^ 13779c0

  也可以使用 ^ 符号,表示在该提交记录的基础上回退一个节点。

1
git rebase -i HEAD~3 HEAD~1

  如果 HEAD 指针在所操作分支上,也可使用通过HEAD进行区间选择。

1
git rebase -i StartPoint^ EndPoint

  如果提交记录被打上tag,则可以通过tag指定区间。

1.3 命令种类

  执行 rebase -i 指令后可看到如下界面。

Git基础篇(二十五)——rebase指令

前言:
   rebase指令是git中功能较为复杂的一个指令,用好了可以简化提交记录。

1 rebase

   rebase 可对一段连续的提交记录进行修改、删除、复制粘贴、合并操作,规范的使用该指令能使得提交记录更加干净整洁。

1.1 指定格式

  指令格式如下。

1
git rebase -i [StartPoint] [EndPoint]
  • -i : 是指令 --interactive 的缩写,即弹出交互式界面让用户选择具体的执行动作;
  • [StartPoint] : 指定一段提交记录的起点,但不包含该提交记录;
  • [EndPoint] : 指定一段提交记录的终点,包含该提交记录。提交时间上不能比StartPoint指定的提交记录早;

1.2 选择提交记录

  假设有以下提交记录,提交记录的选择有多种方式,可以通过git提交时为每个提交记录生成的唯一 commit id 指定,或者用 HEAD 的形式等。在git中区间的指定都是左开右闭, [EndPoint] 可以省略,表示到分支的最新提交记录。选择的提交记录必须是同一分支上连续的提交记录。
  假设有以下提交记录,我们我们要选择 f56ce4e13779c0 两个提交记录。可编辑如下指令。

main.png

1
git rebase -i 1fc8a58 13779c0

  由于区间的选择是左开右闭的,因此这里选择的 [StartPoint] 要比实际需要的提交记录提前一个节点。

1
git rebase -i f56ce4e^ 13779c0

  也可以使用 ^ 符号,表示在该提交记录的基础上回退一个节点。

1
git rebase -i HEAD~3 HEAD~1

  如果 HEAD 指针在所操作分支上,也可使用通过HEAD进行区间选择。

1
git rebase -i StartPoint^ EndPoint

  如果提交记录被打上tag,则可以通过tag指定区间。

1.3 命令种类

  执行 rebase -i 指令后可看到如下界面。

Cmd.png

  常用指令介绍如下。

  • pick : 简写为 p ,保留提交记录;
  • reword : 简写为 r ,保留提交记录但编辑提交信息;
  • edit : 简写为 e ,保留提交记录但要停下来进行 amend 修改;
  • squash : 简写为 s ,与前一个提交记录合并;
  • fixup : 简写为 f ,与前一个提交记录合并,但要停下来修改提交信息;
  • exec : 简写为 x ,执行shell命令;
  • drop : 简写为 d ,舍弃本地提交记录;

2 修改

  在之前的文章中介绍过 amend 指令的用法,它可以对分支的最新提交记录进行修改,不会产生新的提交记录,若想对任意提交记录进行修改则可使用 rebase 指令的 edit 指令。 reword 指令是只对任意提交记录的提交信息进行修改,文件和目录保持不变,用法同 amend ,下面以 amend 指令来讲解。
  以下演示对 StartPointEndPoint 提交记录的修改,执行以下指令。

1
git rebase -i f56ce4e^ 13779c0

  将选择要对节点执行的指令,默认为 pick ,节点是按时间排序的,从上到下对应从旧到新的提交。要对这两次提交记录进行修改,因此将 pick 改为 edit 或简写为 e

1
2
edit f56ce4e main-2
edit 3643500 main-3

  编辑完成后在Vim模式输入指令 :wq 即可开始执行指令。此时可看到终端显示如下信息,会依照从旧到新的顺序停下来让用户逐一对使用 edit 的提交记录进行修改,可修改文件也可修改提交信息。

git_rebase_edit_1.png

  需要配合 git addgit commit --amend 指令对当前提交记录进行修改,完成修改后还需执行以下指令推动rebase下一步骤进行。

1
git rebase --continue

  此时可以看到终端显示如下信息。

git_rebase_edit_2.png

  中间可能出现冲突,比如不同提交记录对同一个文件做了不同修改,有冲突解决冲突即可。
  需要注意的是,git中每个提交记录都是基于上一个提交记录的基础上修改的,如果你对中间某个提交记录进行了修改,那必然会对该分支上该提交记录之后所有的提交记录产生影响,所以这种修改方式非常容易出现冲突。因此建议对中间某个节点修改时,应该对之后所有的节点也都使用 edit 指令进行一一修改。否则,只对中间某些提交记录进行修改,之后的修改记录会从分支中“舍弃”,但该舍弃不是完全删除,使用 git log --allgit reflog 依然可以看到原来的提交记录。

2.1 从中间修改到最新

  使用以下指令修改 main 分支从 f56ce4e13779c0 最新提交记录。

1
git rebase -i f56ce4e

  对提交记录一路修改后通过log可看到如下信息。

git_rebase_edit_log.png

  从log可以看到main分支出现了两个分支,旧的支路默认是不可见的,可在log全显下看到。

2.2 只修改中间

  只修改中间的提交记录,会导致原本分支的修改关系被打破,因此git将会为新的修改创建一个游离分支,游离分支复制原分支然后将修改在这个游离分支上进行,由于提交记录的逻辑的逻辑关系被打破,在游离分支上修改记录之后的记录会被删除,用户可以创建一个新分支并且将游戏分支的提交记录合并到新分支上。

git_rebase_edit_log2.png

  当前分支处于游离分支时,使用指令 git branch <newbranch> 创建新分支,然后使用指令 git merge <newbranch> 将游离分支的记录合并到新分支上。可以将原分支删除然后再次创建同名分支,再将离散分支的记录合并回该分支上。更简单的方法是使用 git reset --hard <commit id> ,填写游离分支的最新节点的 commit id 号,以此来使main分支切换到另外一个子分支上。

3 删除

  使用指令 rebase 可以删除旧的历史提交。 rebase 指令的主要用法上面已经介绍清除,下面主要介绍几种具体应用场景,详细操作流程可参考第2章节。
  用指令 drop 修饰提交记录,可将对应的提交记录删除,与修改提交记录类似的,也有两种修改情况。

3.1 从中间删除到最新

  被 drop 修饰的提交记录都被删除。

3.2 只删除中间

  只删除中间提交记录,会破坏提交记录的逻辑关系,因为每次提交都是在上一个提交记录的基础上进行的,如果之前的提交不存在了,后续的提交也没有存在意义。删除中间的提交记录之后的提交也会被删除,因此git会为这种删除操作创建游离分支并且在游戏分支上进行,游离分支复制原分支然后将 drop 修饰的提交记录及其之后更新的提交记录一并删除。
  通过 drop 指令删除中间两个节点后log信息如下。

git_rebase_drop_log.png

  main分支只剩下删除记录之前的提交记录。当前分支处于游离分支时使用 git merge <newbranch> 将修改合并到新分支上。可以将原分支删除然后再次创建同名分支,再将离散分支的记录合并回该分支上。更简单的方法是使用 git reset --hard <commit id> ,填写游离分支的最新节点的 commit id 号,以此来使main分支切换到另外一个子分支上。

4 复制粘贴

  使用使用以下指令可将某分支的一段提交记录复制到其他分支上。复制到其他分支也分两种情况,复制到其他分支最新提交记录之后,或复制到其他分支中间提交记录之后。
  指令格式如下。

1
git rebase -i --onto [branch/ToPoint] [StartPoint] [EndPoint]

  该指令表示将 [StartPoint] [EndPoint] 区间的提交记录复制到 [branch/ToPoint] 所指的分支最新提交记录或所指某提交记录之后。不需对提交记录修改时 -i 指令可省略,此时是原样复制,若是带修改的复制则可配置 -i 指令,比如复制提交记录到其他分支但要进行修改,复制并合并提交记录到其他分支等。可能用的指令有 squash ,表示将该提交和前一个提交合并,而 fixup 表示该提交和前一个提交合并但不保留其提交信息。

4.1 复制到最新记录

  当 [branch/ToPoint] 写分支名时,表示将所选区间的提交记录复制到该分支的最新提交记录之后。需要 注意 的是,复制动作的源分支和目标分支如果是重合的,若复制后的状态仍然是两分支重合,git会将源分支复制记录之后的记录删除,目标分支的指针不变。此种需求不应进行操作,而是应直接移动目标分支的指针。

4.2 复制到中间记录

  插入式复制会破坏分支上原本的提交记录之间的逻辑关系,因此git会将插入位置之后的提交记录都删除掉。

5 合并

  通过 squashfixup 指令修饰,将对应提交记录合并与前一个提交记录合并,直到所选区间的第一提交记录,第一个提交记录可使用 pickrewordedit 修饰。同样的,合并也有两种情况,合并的区间是最新提交记录或是中间某一段提交记录。

5.1 合并最新提交记录

  按提交顺序,只所选区间的最旧提交记录保留,其他提交记录都选择与上一次提交合并,比如。

1
2
3
pick f56ce4e main-2
squash 3643500 main-3
squash 13779c0 main-4

  合并后最后会弹出提交信息编辑界面,会列出所有提交记录原本的提交信息,可在此基础上编辑。

5.2 合并中间提交记录

  同样的,将中间的提交记录合并会破坏原本提交记录之间的逻辑关系,因此git会将插入位置之后的提交记录都删除掉,并且这些操作都会在游离分支上。

  常用指令介绍如下。

  • pick : 简写为 p ,保留提交记录;
  • reword : 简写为 r ,保留提交记录但编辑提交信息;
  • edit : 简写为 e ,保留提交记录但要停下来进行 amend 修改;
  • squash : 简写为 s ,与前一个提交记录合并;
  • fixup : 简写为 f ,与前一个提交记录合并,但要停下来修改提交信息;
  • exec : 简写为 x ,执行shell命令;
  • drop : 简写为 d ,舍弃本地提交记录;

2 修改

  在之前的文章中介绍过 amend 指令的用法,它可以对分支的最新提交记录进行修改,不会产生新的提交记录,若想对任意提交记录进行修改则可使用 rebase 指令的 edit 指令。 reword 指令是只对任意提交记录的提交信息进行修改,文件和目录保持不变,用法同 amend ,下面以 amend 指令来讲解。
  以下演示对 StartPointEndPoint 提交记录的修改,执行以下指令。

1
git rebase -i f56ce4e^ 13779c0

  将选择要对节点执行的指令,默认为 pick ,节点是按时间排序的,从上到下对应从旧到新的提交。要对这两次提交记录进行修改,因此将 pick 改为 edit 或简写为 e

1
2
edit f56ce4e main-2
edit 3643500 main-3

  编辑完成后在Vim模式输入指令 :wq 即可开始执行指令。此时可看到终端显示如下信息,会依照从旧到新的顺序停下来让用户逐一对使用 edit 的提交记录进行修改,可修改文件也可修改提交信息。

Git基础篇(二十五)——rebase指令

前言:
   rebase指令是git中功能较为复杂的一个指令,用好了可以简化提交记录。

1 rebase

   rebase 可对一段连续的提交记录进行修改、删除、复制粘贴、合并操作,规范的使用该指令能使得提交记录更加干净整洁。

1.1 指定格式

  指令格式如下。

1
git rebase -i [StartPoint] [EndPoint]
  • -i : 是指令 --interactive 的缩写,即弹出交互式界面让用户选择具体的执行动作;
  • [StartPoint] : 指定一段提交记录的起点,但不包含该提交记录;
  • [EndPoint] : 指定一段提交记录的终点,包含该提交记录。提交时间上不能比StartPoint指定的提交记录早;

1.2 选择提交记录

  假设有以下提交记录,提交记录的选择有多种方式,可以通过git提交时为每个提交记录生成的唯一 commit id 指定,或者用 HEAD 的形式等。在git中区间的指定都是左开右闭, [EndPoint] 可以省略,表示到分支的最新提交记录。选择的提交记录必须是同一分支上连续的提交记录。
  假设有以下提交记录,我们我们要选择 f56ce4e13779c0 两个提交记录。可编辑如下指令。

main.png

1
git rebase -i 1fc8a58 13779c0

  由于区间的选择是左开右闭的,因此这里选择的 [StartPoint] 要比实际需要的提交记录提前一个节点。

1
git rebase -i f56ce4e^ 13779c0

  也可以使用 ^ 符号,表示在该提交记录的基础上回退一个节点。

1
git rebase -i HEAD~3 HEAD~1

  如果 HEAD 指针在所操作分支上,也可使用通过HEAD进行区间选择。

1
git rebase -i StartPoint^ EndPoint

  如果提交记录被打上tag,则可以通过tag指定区间。

1.3 命令种类

  执行 rebase -i 指令后可看到如下界面。

Cmd.png

  常用指令介绍如下。

  • pick : 简写为 p ,保留提交记录;
  • reword : 简写为 r ,保留提交记录但编辑提交信息;
  • edit : 简写为 e ,保留提交记录但要停下来进行 amend 修改;
  • squash : 简写为 s ,与前一个提交记录合并;
  • fixup : 简写为 f ,与前一个提交记录合并,但要停下来修改提交信息;
  • exec : 简写为 x ,执行shell命令;
  • drop : 简写为 d ,舍弃本地提交记录;

2 修改

  在之前的文章中介绍过 amend 指令的用法,它可以对分支的最新提交记录进行修改,不会产生新的提交记录,若想对任意提交记录进行修改则可使用 rebase 指令的 edit 指令。 reword 指令是只对任意提交记录的提交信息进行修改,文件和目录保持不变,用法同 amend ,下面以 amend 指令来讲解。
  以下演示对 StartPointEndPoint 提交记录的修改,执行以下指令。

1
git rebase -i f56ce4e^ 13779c0

  将选择要对节点执行的指令,默认为 pick ,节点是按时间排序的,从上到下对应从旧到新的提交。要对这两次提交记录进行修改,因此将 pick 改为 edit 或简写为 e

1
2
edit f56ce4e main-2
edit 3643500 main-3

  编辑完成后在Vim模式输入指令 :wq 即可开始执行指令。此时可看到终端显示如下信息,会依照从旧到新的顺序停下来让用户逐一对使用 edit 的提交记录进行修改,可修改文件也可修改提交信息。

git_rebase_edit_1.png

  需要配合 git addgit commit --amend 指令对当前提交记录进行修改,完成修改后还需执行以下指令推动rebase下一步骤进行。

1
git rebase --continue

  此时可以看到终端显示如下信息。

git_rebase_edit_2.png

  中间可能出现冲突,比如不同提交记录对同一个文件做了不同修改,有冲突解决冲突即可。
  需要注意的是,git中每个提交记录都是基于上一个提交记录的基础上修改的,如果你对中间某个提交记录进行了修改,那必然会对该分支上该提交记录之后所有的提交记录产生影响,所以这种修改方式非常容易出现冲突。因此建议对中间某个节点修改时,应该对之后所有的节点也都使用 edit 指令进行一一修改。否则,只对中间某些提交记录进行修改,之后的修改记录会从分支中“舍弃”,但该舍弃不是完全删除,使用 git log --allgit reflog 依然可以看到原来的提交记录。

2.1 从中间修改到最新

  使用以下指令修改 main 分支从 f56ce4e13779c0 最新提交记录。

1
git rebase -i f56ce4e

  对提交记录一路修改后通过log可看到如下信息。

git_rebase_edit_log.png

  从log可以看到main分支出现了两个分支,旧的支路默认是不可见的,可在log全显下看到。

2.2 只修改中间

  只修改中间的提交记录,会导致原本分支的修改关系被打破,因此git将会为新的修改创建一个游离分支,游离分支复制原分支然后将修改在这个游离分支上进行,由于提交记录的逻辑的逻辑关系被打破,在游离分支上修改记录之后的记录会被删除,用户可以创建一个新分支并且将游戏分支的提交记录合并到新分支上。

git_rebase_edit_log2.png

  当前分支处于游离分支时,使用指令 git branch <newbranch> 创建新分支,然后使用指令 git merge <newbranch> 将游离分支的记录合并到新分支上。可以将原分支删除然后再次创建同名分支,再将离散分支的记录合并回该分支上。更简单的方法是使用 git reset --hard <commit id> ,填写游离分支的最新节点的 commit id 号,以此来使main分支切换到另外一个子分支上。

3 删除

  使用指令 rebase 可以删除旧的历史提交。 rebase 指令的主要用法上面已经介绍清除,下面主要介绍几种具体应用场景,详细操作流程可参考第2章节。
  用指令 drop 修饰提交记录,可将对应的提交记录删除,与修改提交记录类似的,也有两种修改情况。

3.1 从中间删除到最新

  被 drop 修饰的提交记录都被删除。

3.2 只删除中间

  只删除中间提交记录,会破坏提交记录的逻辑关系,因为每次提交都是在上一个提交记录的基础上进行的,如果之前的提交不存在了,后续的提交也没有存在意义。删除中间的提交记录之后的提交也会被删除,因此git会为这种删除操作创建游离分支并且在游戏分支上进行,游离分支复制原分支然后将 drop 修饰的提交记录及其之后更新的提交记录一并删除。
  通过 drop 指令删除中间两个节点后log信息如下。

git_rebase_drop_log.png

  main分支只剩下删除记录之前的提交记录。当前分支处于游离分支时使用 git merge <newbranch> 将修改合并到新分支上。可以将原分支删除然后再次创建同名分支,再将离散分支的记录合并回该分支上。更简单的方法是使用 git reset --hard <commit id> ,填写游离分支的最新节点的 commit id 号,以此来使main分支切换到另外一个子分支上。

4 复制粘贴

  使用使用以下指令可将某分支的一段提交记录复制到其他分支上。复制到其他分支也分两种情况,复制到其他分支最新提交记录之后,或复制到其他分支中间提交记录之后。
  指令格式如下。

1
git rebase -i --onto [branch/ToPoint] [StartPoint] [EndPoint]

  该指令表示将 [StartPoint] [EndPoint] 区间的提交记录复制到 [branch/ToPoint] 所指的分支最新提交记录或所指某提交记录之后。不需对提交记录修改时 -i 指令可省略,此时是原样复制,若是带修改的复制则可配置 -i 指令,比如复制提交记录到其他分支但要进行修改,复制并合并提交记录到其他分支等。可能用的指令有 squash ,表示将该提交和前一个提交合并,而 fixup 表示该提交和前一个提交合并但不保留其提交信息。

4.1 复制到最新记录

  当 [branch/ToPoint] 写分支名时,表示将所选区间的提交记录复制到该分支的最新提交记录之后。需要 注意 的是,复制动作的源分支和目标分支如果是重合的,若复制后的状态仍然是两分支重合,git会将源分支复制记录之后的记录删除,目标分支的指针不变。此种需求不应进行操作,而是应直接移动目标分支的指针。

4.2 复制到中间记录

  插入式复制会破坏分支上原本的提交记录之间的逻辑关系,因此git会将插入位置之后的提交记录都删除掉。

5 合并

  通过 squashfixup 指令修饰,将对应提交记录合并与前一个提交记录合并,直到所选区间的第一提交记录,第一个提交记录可使用 pickrewordedit 修饰。同样的,合并也有两种情况,合并的区间是最新提交记录或是中间某一段提交记录。

5.1 合并最新提交记录

  按提交顺序,只所选区间的最旧提交记录保留,其他提交记录都选择与上一次提交合并,比如。

1
2
3
pick f56ce4e main-2
squash 3643500 main-3
squash 13779c0 main-4

  合并后最后会弹出提交信息编辑界面,会列出所有提交记录原本的提交信息,可在此基础上编辑。

5.2 合并中间提交记录

  同样的,将中间的提交记录合并会破坏原本提交记录之间的逻辑关系,因此git会将插入位置之后的提交记录都删除掉,并且这些操作都会在游离分支上。

  需要配合 git addgit commit --amend 指令对当前提交记录进行修改,完成修改后还需执行以下指令推动rebase下一步骤进行。

1
git rebase --continue

  此时可以看到终端显示如下信息。

Git基础篇(二十五)——rebase指令

前言:
   rebase指令是git中功能较为复杂的一个指令,用好了可以简化提交记录。

1 rebase

   rebase 可对一段连续的提交记录进行修改、删除、复制粘贴、合并操作,规范的使用该指令能使得提交记录更加干净整洁。

1.1 指定格式

  指令格式如下。

1
git rebase -i [StartPoint] [EndPoint]
  • -i : 是指令 --interactive 的缩写,即弹出交互式界面让用户选择具体的执行动作;
  • [StartPoint] : 指定一段提交记录的起点,但不包含该提交记录;
  • [EndPoint] : 指定一段提交记录的终点,包含该提交记录。提交时间上不能比StartPoint指定的提交记录早;

1.2 选择提交记录

  假设有以下提交记录,提交记录的选择有多种方式,可以通过git提交时为每个提交记录生成的唯一 commit id 指定,或者用 HEAD 的形式等。在git中区间的指定都是左开右闭, [EndPoint] 可以省略,表示到分支的最新提交记录。选择的提交记录必须是同一分支上连续的提交记录。
  假设有以下提交记录,我们我们要选择 f56ce4e13779c0 两个提交记录。可编辑如下指令。

main.png

1
git rebase -i 1fc8a58 13779c0

  由于区间的选择是左开右闭的,因此这里选择的 [StartPoint] 要比实际需要的提交记录提前一个节点。

1
git rebase -i f56ce4e^ 13779c0

  也可以使用 ^ 符号,表示在该提交记录的基础上回退一个节点。

1
git rebase -i HEAD~3 HEAD~1

  如果 HEAD 指针在所操作分支上,也可使用通过HEAD进行区间选择。

1
git rebase -i StartPoint^ EndPoint

  如果提交记录被打上tag,则可以通过tag指定区间。

1.3 命令种类

  执行 rebase -i 指令后可看到如下界面。

Cmd.png

  常用指令介绍如下。

  • pick : 简写为 p ,保留提交记录;
  • reword : 简写为 r ,保留提交记录但编辑提交信息;
  • edit : 简写为 e ,保留提交记录但要停下来进行 amend 修改;
  • squash : 简写为 s ,与前一个提交记录合并;
  • fixup : 简写为 f ,与前一个提交记录合并,但要停下来修改提交信息;
  • exec : 简写为 x ,执行shell命令;
  • drop : 简写为 d ,舍弃本地提交记录;

2 修改

  在之前的文章中介绍过 amend 指令的用法,它可以对分支的最新提交记录进行修改,不会产生新的提交记录,若想对任意提交记录进行修改则可使用 rebase 指令的 edit 指令。 reword 指令是只对任意提交记录的提交信息进行修改,文件和目录保持不变,用法同 amend ,下面以 amend 指令来讲解。
  以下演示对 StartPointEndPoint 提交记录的修改,执行以下指令。

1
git rebase -i f56ce4e^ 13779c0

  将选择要对节点执行的指令,默认为 pick ,节点是按时间排序的,从上到下对应从旧到新的提交。要对这两次提交记录进行修改,因此将 pick 改为 edit 或简写为 e

1
2
edit f56ce4e main-2
edit 3643500 main-3

  编辑完成后在Vim模式输入指令 :wq 即可开始执行指令。此时可看到终端显示如下信息,会依照从旧到新的顺序停下来让用户逐一对使用 edit 的提交记录进行修改,可修改文件也可修改提交信息。

git_rebase_edit_1.png

  需要配合 git addgit commit --amend 指令对当前提交记录进行修改,完成修改后还需执行以下指令推动rebase下一步骤进行。

1
git rebase --continue

  此时可以看到终端显示如下信息。

git_rebase_edit_2.png

  中间可能出现冲突,比如不同提交记录对同一个文件做了不同修改,有冲突解决冲突即可。
  需要注意的是,git中每个提交记录都是基于上一个提交记录的基础上修改的,如果你对中间某个提交记录进行了修改,那必然会对该分支上该提交记录之后所有的提交记录产生影响,所以这种修改方式非常容易出现冲突。因此建议对中间某个节点修改时,应该对之后所有的节点也都使用 edit 指令进行一一修改。否则,只对中间某些提交记录进行修改,之后的修改记录会从分支中“舍弃”,但该舍弃不是完全删除,使用 git log --allgit reflog 依然可以看到原来的提交记录。

2.1 从中间修改到最新

  使用以下指令修改 main 分支从 f56ce4e13779c0 最新提交记录。

1
git rebase -i f56ce4e

  对提交记录一路修改后通过log可看到如下信息。

git_rebase_edit_log.png

  从log可以看到main分支出现了两个分支,旧的支路默认是不可见的,可在log全显下看到。

2.2 只修改中间

  只修改中间的提交记录,会导致原本分支的修改关系被打破,因此git将会为新的修改创建一个游离分支,游离分支复制原分支然后将修改在这个游离分支上进行,由于提交记录的逻辑的逻辑关系被打破,在游离分支上修改记录之后的记录会被删除,用户可以创建一个新分支并且将游戏分支的提交记录合并到新分支上。

git_rebase_edit_log2.png

  当前分支处于游离分支时,使用指令 git branch <newbranch> 创建新分支,然后使用指令 git merge <newbranch> 将游离分支的记录合并到新分支上。可以将原分支删除然后再次创建同名分支,再将离散分支的记录合并回该分支上。更简单的方法是使用 git reset --hard <commit id> ,填写游离分支的最新节点的 commit id 号,以此来使main分支切换到另外一个子分支上。

3 删除

  使用指令 rebase 可以删除旧的历史提交。 rebase 指令的主要用法上面已经介绍清除,下面主要介绍几种具体应用场景,详细操作流程可参考第2章节。
  用指令 drop 修饰提交记录,可将对应的提交记录删除,与修改提交记录类似的,也有两种修改情况。

3.1 从中间删除到最新

  被 drop 修饰的提交记录都被删除。

3.2 只删除中间

  只删除中间提交记录,会破坏提交记录的逻辑关系,因为每次提交都是在上一个提交记录的基础上进行的,如果之前的提交不存在了,后续的提交也没有存在意义。删除中间的提交记录之后的提交也会被删除,因此git会为这种删除操作创建游离分支并且在游戏分支上进行,游离分支复制原分支然后将 drop 修饰的提交记录及其之后更新的提交记录一并删除。
  通过 drop 指令删除中间两个节点后log信息如下。

git_rebase_drop_log.png

  main分支只剩下删除记录之前的提交记录。当前分支处于游离分支时使用 git merge <newbranch> 将修改合并到新分支上。可以将原分支删除然后再次创建同名分支,再将离散分支的记录合并回该分支上。更简单的方法是使用 git reset --hard <commit id> ,填写游离分支的最新节点的 commit id 号,以此来使main分支切换到另外一个子分支上。

4 复制粘贴

  使用使用以下指令可将某分支的一段提交记录复制到其他分支上。复制到其他分支也分两种情况,复制到其他分支最新提交记录之后,或复制到其他分支中间提交记录之后。
  指令格式如下。

1
git rebase -i --onto [branch/ToPoint] [StartPoint] [EndPoint]

  该指令表示将 [StartPoint] [EndPoint] 区间的提交记录复制到 [branch/ToPoint] 所指的分支最新提交记录或所指某提交记录之后。不需对提交记录修改时 -i 指令可省略,此时是原样复制,若是带修改的复制则可配置 -i 指令,比如复制提交记录到其他分支但要进行修改,复制并合并提交记录到其他分支等。可能用的指令有 squash ,表示将该提交和前一个提交合并,而 fixup 表示该提交和前一个提交合并但不保留其提交信息。

4.1 复制到最新记录

  当 [branch/ToPoint] 写分支名时,表示将所选区间的提交记录复制到该分支的最新提交记录之后。需要 注意 的是,复制动作的源分支和目标分支如果是重合的,若复制后的状态仍然是两分支重合,git会将源分支复制记录之后的记录删除,目标分支的指针不变。此种需求不应进行操作,而是应直接移动目标分支的指针。

4.2 复制到中间记录

  插入式复制会破坏分支上原本的提交记录之间的逻辑关系,因此git会将插入位置之后的提交记录都删除掉。

5 合并

  通过 squashfixup 指令修饰,将对应提交记录合并与前一个提交记录合并,直到所选区间的第一提交记录,第一个提交记录可使用 pickrewordedit 修饰。同样的,合并也有两种情况,合并的区间是最新提交记录或是中间某一段提交记录。

5.1 合并最新提交记录

  按提交顺序,只所选区间的最旧提交记录保留,其他提交记录都选择与上一次提交合并,比如。

1
2
3
pick f56ce4e main-2
squash 3643500 main-3
squash 13779c0 main-4

  合并后最后会弹出提交信息编辑界面,会列出所有提交记录原本的提交信息,可在此基础上编辑。

5.2 合并中间提交记录

  同样的,将中间的提交记录合并会破坏原本提交记录之间的逻辑关系,因此git会将插入位置之后的提交记录都删除掉,并且这些操作都会在游离分支上。

  中间可能出现冲突,比如不同提交记录对同一个文件做了不同修改,有冲突解决冲突即可。
  需要注意的是,git中每个提交记录都是基于上一个提交记录的基础上修改的,如果你对中间某个提交记录进行了修改,那必然会对该分支上该提交记录之后所有的提交记录产生影响,所以这种修改方式非常容易出现冲突。因此建议对中间某个节点修改时,应该对之后所有的节点也都使用 edit 指令进行一一修改。否则,只对中间某些提交记录进行修改,之后的修改记录会从分支中“舍弃”,但该舍弃不是完全删除,使用 git log --allgit reflog 依然可以看到原来的提交记录。

2.1 从中间修改到最新

  使用以下指令修改 main 分支从 f56ce4e13779c0 最新提交记录。

1
git rebase -i f56ce4e

  对提交记录一路修改后通过log可看到如下信息。

Git基础篇(二十五)——rebase指令

前言:
   rebase指令是git中功能较为复杂的一个指令,用好了可以简化提交记录。

1 rebase

   rebase 可对一段连续的提交记录进行修改、删除、复制粘贴、合并操作,规范的使用该指令能使得提交记录更加干净整洁。

1.1 指定格式

  指令格式如下。

1
git rebase -i [StartPoint] [EndPoint]
  • -i : 是指令 --interactive 的缩写,即弹出交互式界面让用户选择具体的执行动作;
  • [StartPoint] : 指定一段提交记录的起点,但不包含该提交记录;
  • [EndPoint] : 指定一段提交记录的终点,包含该提交记录。提交时间上不能比StartPoint指定的提交记录早;

1.2 选择提交记录

  假设有以下提交记录,提交记录的选择有多种方式,可以通过git提交时为每个提交记录生成的唯一 commit id 指定,或者用 HEAD 的形式等。在git中区间的指定都是左开右闭, [EndPoint] 可以省略,表示到分支的最新提交记录。选择的提交记录必须是同一分支上连续的提交记录。
  假设有以下提交记录,我们我们要选择 f56ce4e13779c0 两个提交记录。可编辑如下指令。

main.png

1
git rebase -i 1fc8a58 13779c0

  由于区间的选择是左开右闭的,因此这里选择的 [StartPoint] 要比实际需要的提交记录提前一个节点。

1
git rebase -i f56ce4e^ 13779c0

  也可以使用 ^ 符号,表示在该提交记录的基础上回退一个节点。

1
git rebase -i HEAD~3 HEAD~1

  如果 HEAD 指针在所操作分支上,也可使用通过HEAD进行区间选择。

1
git rebase -i StartPoint^ EndPoint

  如果提交记录被打上tag,则可以通过tag指定区间。

1.3 命令种类

  执行 rebase -i 指令后可看到如下界面。

Cmd.png

  常用指令介绍如下。

  • pick : 简写为 p ,保留提交记录;
  • reword : 简写为 r ,保留提交记录但编辑提交信息;
  • edit : 简写为 e ,保留提交记录但要停下来进行 amend 修改;
  • squash : 简写为 s ,与前一个提交记录合并;
  • fixup : 简写为 f ,与前一个提交记录合并,但要停下来修改提交信息;
  • exec : 简写为 x ,执行shell命令;
  • drop : 简写为 d ,舍弃本地提交记录;

2 修改

  在之前的文章中介绍过 amend 指令的用法,它可以对分支的最新提交记录进行修改,不会产生新的提交记录,若想对任意提交记录进行修改则可使用 rebase 指令的 edit 指令。 reword 指令是只对任意提交记录的提交信息进行修改,文件和目录保持不变,用法同 amend ,下面以 amend 指令来讲解。
  以下演示对 StartPointEndPoint 提交记录的修改,执行以下指令。

1
git rebase -i f56ce4e^ 13779c0

  将选择要对节点执行的指令,默认为 pick ,节点是按时间排序的,从上到下对应从旧到新的提交。要对这两次提交记录进行修改,因此将 pick 改为 edit 或简写为 e

1
2
edit f56ce4e main-2
edit 3643500 main-3

  编辑完成后在Vim模式输入指令 :wq 即可开始执行指令。此时可看到终端显示如下信息,会依照从旧到新的顺序停下来让用户逐一对使用 edit 的提交记录进行修改,可修改文件也可修改提交信息。

git_rebase_edit_1.png

  需要配合 git addgit commit --amend 指令对当前提交记录进行修改,完成修改后还需执行以下指令推动rebase下一步骤进行。

1
git rebase --continue

  此时可以看到终端显示如下信息。

git_rebase_edit_2.png

  中间可能出现冲突,比如不同提交记录对同一个文件做了不同修改,有冲突解决冲突即可。
  需要注意的是,git中每个提交记录都是基于上一个提交记录的基础上修改的,如果你对中间某个提交记录进行了修改,那必然会对该分支上该提交记录之后所有的提交记录产生影响,所以这种修改方式非常容易出现冲突。因此建议对中间某个节点修改时,应该对之后所有的节点也都使用 edit 指令进行一一修改。否则,只对中间某些提交记录进行修改,之后的修改记录会从分支中“舍弃”,但该舍弃不是完全删除,使用 git log --allgit reflog 依然可以看到原来的提交记录。

2.1 从中间修改到最新

  使用以下指令修改 main 分支从 f56ce4e13779c0 最新提交记录。

1
git rebase -i f56ce4e

  对提交记录一路修改后通过log可看到如下信息。

git_rebase_edit_log.png

  从log可以看到main分支出现了两个分支,旧的支路默认是不可见的,可在log全显下看到。

2.2 只修改中间

  只修改中间的提交记录,会导致原本分支的修改关系被打破,因此git将会为新的修改创建一个游离分支,游离分支复制原分支然后将修改在这个游离分支上进行,由于提交记录的逻辑的逻辑关系被打破,在游离分支上修改记录之后的记录会被删除,用户可以创建一个新分支并且将游戏分支的提交记录合并到新分支上。

git_rebase_edit_log2.png

  当前分支处于游离分支时,使用指令 git branch <newbranch> 创建新分支,然后使用指令 git merge <newbranch> 将游离分支的记录合并到新分支上。可以将原分支删除然后再次创建同名分支,再将离散分支的记录合并回该分支上。更简单的方法是使用 git reset --hard <commit id> ,填写游离分支的最新节点的 commit id 号,以此来使main分支切换到另外一个子分支上。

3 删除

  使用指令 rebase 可以删除旧的历史提交。 rebase 指令的主要用法上面已经介绍清除,下面主要介绍几种具体应用场景,详细操作流程可参考第2章节。
  用指令 drop 修饰提交记录,可将对应的提交记录删除,与修改提交记录类似的,也有两种修改情况。

3.1 从中间删除到最新

  被 drop 修饰的提交记录都被删除。

3.2 只删除中间

  只删除中间提交记录,会破坏提交记录的逻辑关系,因为每次提交都是在上一个提交记录的基础上进行的,如果之前的提交不存在了,后续的提交也没有存在意义。删除中间的提交记录之后的提交也会被删除,因此git会为这种删除操作创建游离分支并且在游戏分支上进行,游离分支复制原分支然后将 drop 修饰的提交记录及其之后更新的提交记录一并删除。
  通过 drop 指令删除中间两个节点后log信息如下。

git_rebase_drop_log.png

  main分支只剩下删除记录之前的提交记录。当前分支处于游离分支时使用 git merge <newbranch> 将修改合并到新分支上。可以将原分支删除然后再次创建同名分支,再将离散分支的记录合并回该分支上。更简单的方法是使用 git reset --hard <commit id> ,填写游离分支的最新节点的 commit id 号,以此来使main分支切换到另外一个子分支上。

4 复制粘贴

  使用使用以下指令可将某分支的一段提交记录复制到其他分支上。复制到其他分支也分两种情况,复制到其他分支最新提交记录之后,或复制到其他分支中间提交记录之后。
  指令格式如下。

1
git rebase -i --onto [branch/ToPoint] [StartPoint] [EndPoint]

  该指令表示将 [StartPoint] [EndPoint] 区间的提交记录复制到 [branch/ToPoint] 所指的分支最新提交记录或所指某提交记录之后。不需对提交记录修改时 -i 指令可省略,此时是原样复制,若是带修改的复制则可配置 -i 指令,比如复制提交记录到其他分支但要进行修改,复制并合并提交记录到其他分支等。可能用的指令有 squash ,表示将该提交和前一个提交合并,而 fixup 表示该提交和前一个提交合并但不保留其提交信息。

4.1 复制到最新记录

  当 [branch/ToPoint] 写分支名时,表示将所选区间的提交记录复制到该分支的最新提交记录之后。需要 注意 的是,复制动作的源分支和目标分支如果是重合的,若复制后的状态仍然是两分支重合,git会将源分支复制记录之后的记录删除,目标分支的指针不变。此种需求不应进行操作,而是应直接移动目标分支的指针。

4.2 复制到中间记录

  插入式复制会破坏分支上原本的提交记录之间的逻辑关系,因此git会将插入位置之后的提交记录都删除掉。

5 合并

  通过 squashfixup 指令修饰,将对应提交记录合并与前一个提交记录合并,直到所选区间的第一提交记录,第一个提交记录可使用 pickrewordedit 修饰。同样的,合并也有两种情况,合并的区间是最新提交记录或是中间某一段提交记录。

5.1 合并最新提交记录

  按提交顺序,只所选区间的最旧提交记录保留,其他提交记录都选择与上一次提交合并,比如。

1
2
3
pick f56ce4e main-2
squash 3643500 main-3
squash 13779c0 main-4

  合并后最后会弹出提交信息编辑界面,会列出所有提交记录原本的提交信息,可在此基础上编辑。

5.2 合并中间提交记录

  同样的,将中间的提交记录合并会破坏原本提交记录之间的逻辑关系,因此git会将插入位置之后的提交记录都删除掉,并且这些操作都会在游离分支上。

  从log可以看到main分支出现了两个分支,旧的支路默认是不可见的,可在log全显下看到。

2.2 只修改中间

  只修改中间的提交记录,会导致原本分支的修改关系被打破,因此git将会为新的修改创建一个游离分支,游离分支复制原分支然后将修改在这个游离分支上进行,由于提交记录的逻辑的逻辑关系被打破,在游离分支上修改记录之后的记录会被删除,用户可以创建一个新分支并且将游戏分支的提交记录合并到新分支上。

Git基础篇(二十五)——rebase指令

前言:
   rebase指令是git中功能较为复杂的一个指令,用好了可以简化提交记录。

1 rebase

   rebase 可对一段连续的提交记录进行修改、删除、复制粘贴、合并操作,规范的使用该指令能使得提交记录更加干净整洁。

1.1 指定格式

  指令格式如下。

1
git rebase -i [StartPoint] [EndPoint]
  • -i : 是指令 --interactive 的缩写,即弹出交互式界面让用户选择具体的执行动作;
  • [StartPoint] : 指定一段提交记录的起点,但不包含该提交记录;
  • [EndPoint] : 指定一段提交记录的终点,包含该提交记录。提交时间上不能比StartPoint指定的提交记录早;

1.2 选择提交记录

  假设有以下提交记录,提交记录的选择有多种方式,可以通过git提交时为每个提交记录生成的唯一 commit id 指定,或者用 HEAD 的形式等。在git中区间的指定都是左开右闭, [EndPoint] 可以省略,表示到分支的最新提交记录。选择的提交记录必须是同一分支上连续的提交记录。
  假设有以下提交记录,我们我们要选择 f56ce4e13779c0 两个提交记录。可编辑如下指令。

main.png

1
git rebase -i 1fc8a58 13779c0

  由于区间的选择是左开右闭的,因此这里选择的 [StartPoint] 要比实际需要的提交记录提前一个节点。

1
git rebase -i f56ce4e^ 13779c0

  也可以使用 ^ 符号,表示在该提交记录的基础上回退一个节点。

1
git rebase -i HEAD~3 HEAD~1

  如果 HEAD 指针在所操作分支上,也可使用通过HEAD进行区间选择。

1
git rebase -i StartPoint^ EndPoint

  如果提交记录被打上tag,则可以通过tag指定区间。

1.3 命令种类

  执行 rebase -i 指令后可看到如下界面。

Cmd.png

  常用指令介绍如下。

  • pick : 简写为 p ,保留提交记录;
  • reword : 简写为 r ,保留提交记录但编辑提交信息;
  • edit : 简写为 e ,保留提交记录但要停下来进行 amend 修改;
  • squash : 简写为 s ,与前一个提交记录合并;
  • fixup : 简写为 f ,与前一个提交记录合并,但要停下来修改提交信息;
  • exec : 简写为 x ,执行shell命令;
  • drop : 简写为 d ,舍弃本地提交记录;

2 修改

  在之前的文章中介绍过 amend 指令的用法,它可以对分支的最新提交记录进行修改,不会产生新的提交记录,若想对任意提交记录进行修改则可使用 rebase 指令的 edit 指令。 reword 指令是只对任意提交记录的提交信息进行修改,文件和目录保持不变,用法同 amend ,下面以 amend 指令来讲解。
  以下演示对 StartPointEndPoint 提交记录的修改,执行以下指令。

1
git rebase -i f56ce4e^ 13779c0

  将选择要对节点执行的指令,默认为 pick ,节点是按时间排序的,从上到下对应从旧到新的提交。要对这两次提交记录进行修改,因此将 pick 改为 edit 或简写为 e

1
2
edit f56ce4e main-2
edit 3643500 main-3

  编辑完成后在Vim模式输入指令 :wq 即可开始执行指令。此时可看到终端显示如下信息,会依照从旧到新的顺序停下来让用户逐一对使用 edit 的提交记录进行修改,可修改文件也可修改提交信息。

git_rebase_edit_1.png

  需要配合 git addgit commit --amend 指令对当前提交记录进行修改,完成修改后还需执行以下指令推动rebase下一步骤进行。

1
git rebase --continue

  此时可以看到终端显示如下信息。

git_rebase_edit_2.png

  中间可能出现冲突,比如不同提交记录对同一个文件做了不同修改,有冲突解决冲突即可。
  需要注意的是,git中每个提交记录都是基于上一个提交记录的基础上修改的,如果你对中间某个提交记录进行了修改,那必然会对该分支上该提交记录之后所有的提交记录产生影响,所以这种修改方式非常容易出现冲突。因此建议对中间某个节点修改时,应该对之后所有的节点也都使用 edit 指令进行一一修改。否则,只对中间某些提交记录进行修改,之后的修改记录会从分支中“舍弃”,但该舍弃不是完全删除,使用 git log --allgit reflog 依然可以看到原来的提交记录。

2.1 从中间修改到最新

  使用以下指令修改 main 分支从 f56ce4e13779c0 最新提交记录。

1
git rebase -i f56ce4e

  对提交记录一路修改后通过log可看到如下信息。

git_rebase_edit_log.png

  从log可以看到main分支出现了两个分支,旧的支路默认是不可见的,可在log全显下看到。

2.2 只修改中间

  只修改中间的提交记录,会导致原本分支的修改关系被打破,因此git将会为新的修改创建一个游离分支,游离分支复制原分支然后将修改在这个游离分支上进行,由于提交记录的逻辑的逻辑关系被打破,在游离分支上修改记录之后的记录会被删除,用户可以创建一个新分支并且将游戏分支的提交记录合并到新分支上。

git_rebase_edit_log2.png

  当前分支处于游离分支时,使用指令 git branch <newbranch> 创建新分支,然后使用指令 git merge <newbranch> 将游离分支的记录合并到新分支上。可以将原分支删除然后再次创建同名分支,再将离散分支的记录合并回该分支上。更简单的方法是使用 git reset --hard <commit id> ,填写游离分支的最新节点的 commit id 号,以此来使main分支切换到另外一个子分支上。

3 删除

  使用指令 rebase 可以删除旧的历史提交。 rebase 指令的主要用法上面已经介绍清除,下面主要介绍几种具体应用场景,详细操作流程可参考第2章节。
  用指令 drop 修饰提交记录,可将对应的提交记录删除,与修改提交记录类似的,也有两种修改情况。

3.1 从中间删除到最新

  被 drop 修饰的提交记录都被删除。

3.2 只删除中间

  只删除中间提交记录,会破坏提交记录的逻辑关系,因为每次提交都是在上一个提交记录的基础上进行的,如果之前的提交不存在了,后续的提交也没有存在意义。删除中间的提交记录之后的提交也会被删除,因此git会为这种删除操作创建游离分支并且在游戏分支上进行,游离分支复制原分支然后将 drop 修饰的提交记录及其之后更新的提交记录一并删除。
  通过 drop 指令删除中间两个节点后log信息如下。

git_rebase_drop_log.png

  main分支只剩下删除记录之前的提交记录。当前分支处于游离分支时使用 git merge <newbranch> 将修改合并到新分支上。可以将原分支删除然后再次创建同名分支,再将离散分支的记录合并回该分支上。更简单的方法是使用 git reset --hard <commit id> ,填写游离分支的最新节点的 commit id 号,以此来使main分支切换到另外一个子分支上。

4 复制粘贴

  使用使用以下指令可将某分支的一段提交记录复制到其他分支上。复制到其他分支也分两种情况,复制到其他分支最新提交记录之后,或复制到其他分支中间提交记录之后。
  指令格式如下。

1
git rebase -i --onto [branch/ToPoint] [StartPoint] [EndPoint]

  该指令表示将 [StartPoint] [EndPoint] 区间的提交记录复制到 [branch/ToPoint] 所指的分支最新提交记录或所指某提交记录之后。不需对提交记录修改时 -i 指令可省略,此时是原样复制,若是带修改的复制则可配置 -i 指令,比如复制提交记录到其他分支但要进行修改,复制并合并提交记录到其他分支等。可能用的指令有 squash ,表示将该提交和前一个提交合并,而 fixup 表示该提交和前一个提交合并但不保留其提交信息。

4.1 复制到最新记录

  当 [branch/ToPoint] 写分支名时,表示将所选区间的提交记录复制到该分支的最新提交记录之后。需要 注意 的是,复制动作的源分支和目标分支如果是重合的,若复制后的状态仍然是两分支重合,git会将源分支复制记录之后的记录删除,目标分支的指针不变。此种需求不应进行操作,而是应直接移动目标分支的指针。

4.2 复制到中间记录

  插入式复制会破坏分支上原本的提交记录之间的逻辑关系,因此git会将插入位置之后的提交记录都删除掉。

5 合并

  通过 squashfixup 指令修饰,将对应提交记录合并与前一个提交记录合并,直到所选区间的第一提交记录,第一个提交记录可使用 pickrewordedit 修饰。同样的,合并也有两种情况,合并的区间是最新提交记录或是中间某一段提交记录。

5.1 合并最新提交记录

  按提交顺序,只所选区间的最旧提交记录保留,其他提交记录都选择与上一次提交合并,比如。

1
2
3
pick f56ce4e main-2
squash 3643500 main-3
squash 13779c0 main-4

  合并后最后会弹出提交信息编辑界面,会列出所有提交记录原本的提交信息,可在此基础上编辑。

5.2 合并中间提交记录

  同样的,将中间的提交记录合并会破坏原本提交记录之间的逻辑关系,因此git会将插入位置之后的提交记录都删除掉,并且这些操作都会在游离分支上。

  当前分支处于游离分支时,使用指令 git branch <newbranch> 创建新分支,然后使用指令 git merge <newbranch> 将游离分支的记录合并到新分支上。可以将原分支删除然后再次创建同名分支,再将离散分支的记录合并回该分支上。更简单的方法是使用 git reset --hard <commit id> ,填写游离分支的最新节点的 commit id 号,以此来使main分支切换到另外一个子分支上。

3 删除

  使用指令 rebase 可以删除旧的历史提交。 rebase 指令的主要用法上面已经介绍清除,下面主要介绍几种具体应用场景,详细操作流程可参考第2章节。
  用指令 drop 修饰提交记录,可将对应的提交记录删除,与修改提交记录类似的,也有两种修改情况。

3.1 从中间删除到最新

  被 drop 修饰的提交记录都被删除。

3.2 只删除中间

  只删除中间提交记录,会破坏提交记录的逻辑关系,因为每次提交都是在上一个提交记录的基础上进行的,如果之前的提交不存在了,后续的提交也没有存在意义。删除中间的提交记录之后的提交也会被删除,因此git会为这种删除操作创建游离分支并且在游戏分支上进行,游离分支复制原分支然后将 drop 修饰的提交记录及其之后更新的提交记录一并删除。
  通过 drop 指令删除中间两个节点后log信息如下。

Git基础篇(二十五)——rebase指令

前言:
   rebase指令是git中功能较为复杂的一个指令,用好了可以简化提交记录。

1 rebase

   rebase 可对一段连续的提交记录进行修改、删除、复制粘贴、合并操作,规范的使用该指令能使得提交记录更加干净整洁。

1.1 指定格式

  指令格式如下。

1
git rebase -i [StartPoint] [EndPoint]
  • -i : 是指令 --interactive 的缩写,即弹出交互式界面让用户选择具体的执行动作;
  • [StartPoint] : 指定一段提交记录的起点,但不包含该提交记录;
  • [EndPoint] : 指定一段提交记录的终点,包含该提交记录。提交时间上不能比StartPoint指定的提交记录早;

1.2 选择提交记录

  假设有以下提交记录,提交记录的选择有多种方式,可以通过git提交时为每个提交记录生成的唯一 commit id 指定,或者用 HEAD 的形式等。在git中区间的指定都是左开右闭, [EndPoint] 可以省略,表示到分支的最新提交记录。选择的提交记录必须是同一分支上连续的提交记录。
  假设有以下提交记录,我们我们要选择 f56ce4e13779c0 两个提交记录。可编辑如下指令。

main.png

1
git rebase -i 1fc8a58 13779c0

  由于区间的选择是左开右闭的,因此这里选择的 [StartPoint] 要比实际需要的提交记录提前一个节点。

1
git rebase -i f56ce4e^ 13779c0

  也可以使用 ^ 符号,表示在该提交记录的基础上回退一个节点。

1
git rebase -i HEAD~3 HEAD~1

  如果 HEAD 指针在所操作分支上,也可使用通过HEAD进行区间选择。

1
git rebase -i StartPoint^ EndPoint

  如果提交记录被打上tag,则可以通过tag指定区间。

1.3 命令种类

  执行 rebase -i 指令后可看到如下界面。

Cmd.png

  常用指令介绍如下。

  • pick : 简写为 p ,保留提交记录;
  • reword : 简写为 r ,保留提交记录但编辑提交信息;
  • edit : 简写为 e ,保留提交记录但要停下来进行 amend 修改;
  • squash : 简写为 s ,与前一个提交记录合并;
  • fixup : 简写为 f ,与前一个提交记录合并,但要停下来修改提交信息;
  • exec : 简写为 x ,执行shell命令;
  • drop : 简写为 d ,舍弃本地提交记录;

2 修改

  在之前的文章中介绍过 amend 指令的用法,它可以对分支的最新提交记录进行修改,不会产生新的提交记录,若想对任意提交记录进行修改则可使用 rebase 指令的 edit 指令。 reword 指令是只对任意提交记录的提交信息进行修改,文件和目录保持不变,用法同 amend ,下面以 amend 指令来讲解。
  以下演示对 StartPointEndPoint 提交记录的修改,执行以下指令。

1
git rebase -i f56ce4e^ 13779c0

  将选择要对节点执行的指令,默认为 pick ,节点是按时间排序的,从上到下对应从旧到新的提交。要对这两次提交记录进行修改,因此将 pick 改为 edit 或简写为 e

1
2
edit f56ce4e main-2
edit 3643500 main-3

  编辑完成后在Vim模式输入指令 :wq 即可开始执行指令。此时可看到终端显示如下信息,会依照从旧到新的顺序停下来让用户逐一对使用 edit 的提交记录进行修改,可修改文件也可修改提交信息。

git_rebase_edit_1.png

  需要配合 git addgit commit --amend 指令对当前提交记录进行修改,完成修改后还需执行以下指令推动rebase下一步骤进行。

1
git rebase --continue

  此时可以看到终端显示如下信息。

git_rebase_edit_2.png

  中间可能出现冲突,比如不同提交记录对同一个文件做了不同修改,有冲突解决冲突即可。
  需要注意的是,git中每个提交记录都是基于上一个提交记录的基础上修改的,如果你对中间某个提交记录进行了修改,那必然会对该分支上该提交记录之后所有的提交记录产生影响,所以这种修改方式非常容易出现冲突。因此建议对中间某个节点修改时,应该对之后所有的节点也都使用 edit 指令进行一一修改。否则,只对中间某些提交记录进行修改,之后的修改记录会从分支中“舍弃”,但该舍弃不是完全删除,使用 git log --allgit reflog 依然可以看到原来的提交记录。

2.1 从中间修改到最新

  使用以下指令修改 main 分支从 f56ce4e13779c0 最新提交记录。

1
git rebase -i f56ce4e

  对提交记录一路修改后通过log可看到如下信息。

git_rebase_edit_log.png

  从log可以看到main分支出现了两个分支,旧的支路默认是不可见的,可在log全显下看到。

2.2 只修改中间

  只修改中间的提交记录,会导致原本分支的修改关系被打破,因此git将会为新的修改创建一个游离分支,游离分支复制原分支然后将修改在这个游离分支上进行,由于提交记录的逻辑的逻辑关系被打破,在游离分支上修改记录之后的记录会被删除,用户可以创建一个新分支并且将游戏分支的提交记录合并到新分支上。

git_rebase_edit_log2.png

  当前分支处于游离分支时,使用指令 git branch <newbranch> 创建新分支,然后使用指令 git merge <newbranch> 将游离分支的记录合并到新分支上。可以将原分支删除然后再次创建同名分支,再将离散分支的记录合并回该分支上。更简单的方法是使用 git reset --hard <commit id> ,填写游离分支的最新节点的 commit id 号,以此来使main分支切换到另外一个子分支上。

3 删除

  使用指令 rebase 可以删除旧的历史提交。 rebase 指令的主要用法上面已经介绍清除,下面主要介绍几种具体应用场景,详细操作流程可参考第2章节。
  用指令 drop 修饰提交记录,可将对应的提交记录删除,与修改提交记录类似的,也有两种修改情况。

3.1 从中间删除到最新

  被 drop 修饰的提交记录都被删除。

3.2 只删除中间

  只删除中间提交记录,会破坏提交记录的逻辑关系,因为每次提交都是在上一个提交记录的基础上进行的,如果之前的提交不存在了,后续的提交也没有存在意义。删除中间的提交记录之后的提交也会被删除,因此git会为这种删除操作创建游离分支并且在游戏分支上进行,游离分支复制原分支然后将 drop 修饰的提交记录及其之后更新的提交记录一并删除。
  通过 drop 指令删除中间两个节点后log信息如下。

git_rebase_drop_log.png

  main分支只剩下删除记录之前的提交记录。当前分支处于游离分支时使用 git merge <newbranch> 将修改合并到新分支上。可以将原分支删除然后再次创建同名分支,再将离散分支的记录合并回该分支上。更简单的方法是使用 git reset --hard <commit id> ,填写游离分支的最新节点的 commit id 号,以此来使main分支切换到另外一个子分支上。

4 复制粘贴

  使用使用以下指令可将某分支的一段提交记录复制到其他分支上。复制到其他分支也分两种情况,复制到其他分支最新提交记录之后,或复制到其他分支中间提交记录之后。
  指令格式如下。

1
git rebase -i --onto [branch/ToPoint] [StartPoint] [EndPoint]

  该指令表示将 [StartPoint] [EndPoint] 区间的提交记录复制到 [branch/ToPoint] 所指的分支最新提交记录或所指某提交记录之后。不需对提交记录修改时 -i 指令可省略,此时是原样复制,若是带修改的复制则可配置 -i 指令,比如复制提交记录到其他分支但要进行修改,复制并合并提交记录到其他分支等。可能用的指令有 squash ,表示将该提交和前一个提交合并,而 fixup 表示该提交和前一个提交合并但不保留其提交信息。

4.1 复制到最新记录

  当 [branch/ToPoint] 写分支名时,表示将所选区间的提交记录复制到该分支的最新提交记录之后。需要 注意 的是,复制动作的源分支和目标分支如果是重合的,若复制后的状态仍然是两分支重合,git会将源分支复制记录之后的记录删除,目标分支的指针不变。此种需求不应进行操作,而是应直接移动目标分支的指针。

4.2 复制到中间记录

  插入式复制会破坏分支上原本的提交记录之间的逻辑关系,因此git会将插入位置之后的提交记录都删除掉。

5 合并

  通过 squashfixup 指令修饰,将对应提交记录合并与前一个提交记录合并,直到所选区间的第一提交记录,第一个提交记录可使用 pickrewordedit 修饰。同样的,合并也有两种情况,合并的区间是最新提交记录或是中间某一段提交记录。

5.1 合并最新提交记录

  按提交顺序,只所选区间的最旧提交记录保留,其他提交记录都选择与上一次提交合并,比如。

1
2
3
pick f56ce4e main-2
squash 3643500 main-3
squash 13779c0 main-4

  合并后最后会弹出提交信息编辑界面,会列出所有提交记录原本的提交信息,可在此基础上编辑。

5.2 合并中间提交记录

  同样的,将中间的提交记录合并会破坏原本提交记录之间的逻辑关系,因此git会将插入位置之后的提交记录都删除掉,并且这些操作都会在游离分支上。

  main分支只剩下删除记录之前的提交记录。当前分支处于游离分支时使用 git merge <newbranch> 将修改合并到新分支上。可以将原分支删除然后再次创建同名分支,再将离散分支的记录合并回该分支上。更简单的方法是使用 git reset --hard <commit id> ,填写游离分支的最新节点的 commit id 号,以此来使main分支切换到另外一个子分支上。

4 复制粘贴

  使用使用以下指令可将某分支的一段提交记录复制到其他分支上。复制到其他分支也分两种情况,复制到其他分支最新提交记录之后,或复制到其他分支中间提交记录之后。
  指令格式如下。

1
git rebase -i --onto [branch/ToPoint] [StartPoint] [EndPoint]

  该指令表示将 [StartPoint] [EndPoint] 区间的提交记录复制到 [branch/ToPoint] 所指的分支最新提交记录或所指某提交记录之后。不需对提交记录修改时 -i 指令可省略,此时是原样复制,若是带修改的复制则可配置 -i 指令,比如复制提交记录到其他分支但要进行修改,复制并合并提交记录到其他分支等。可能用的指令有 squash ,表示将该提交和前一个提交合并,而 fixup 表示该提交和前一个提交合并但不保留其提交信息。

4.1 复制到最新记录

  当 [branch/ToPoint] 写分支名时,表示将所选区间的提交记录复制到该分支的最新提交记录之后。需要 注意 的是,复制动作的源分支和目标分支如果是重合的,若复制后的状态仍然是两分支重合,git会将源分支复制记录之后的记录删除,目标分支的指针不变。此种需求不应进行操作,而是应直接移动目标分支的指针。

4.2 复制到中间记录

  插入式复制会破坏分支上原本的提交记录之间的逻辑关系,因此git会将插入位置之后的提交记录都删除掉。

5 合并

  通过 squashfixup 指令修饰,将对应提交记录合并与前一个提交记录合并,直到所选区间的第一提交记录,第一个提交记录可使用 pickrewordedit 修饰。同样的,合并也有两种情况,合并的区间是最新提交记录或是中间某一段提交记录。

5.1 合并最新提交记录

  按提交顺序,只所选区间的最旧提交记录保留,其他提交记录都选择与上一次提交合并,比如。

1
2
3
pick f56ce4e main-2
squash 3643500 main-3
squash 13779c0 main-4

  合并后最后会弹出提交信息编辑界面,会列出所有提交记录原本的提交信息,可在此基础上编辑。

5.2 合并中间提交记录

  同样的,将中间的提交记录合并会破坏原本提交记录之间的逻辑关系,因此git会将插入位置之后的提交记录都删除掉,并且这些操作都会在游离分支上。