git rebase
、git revert
和git reset
是 Git 中用于处理提交历史的三个不同的命令,它们各自有着不同的原理和用途。
1.git rebase
:
原理: git rebase
用于将一个分支的提交应用于另一个分支。它会将当前分支的提交逐个地移动到目标分支的最后,使得提交历史更为线性。
使用场景: 主要用于清理、整理提交历史、合并提交,以及将本地分支同步到远程分支时使用。
注意事项: 由于会改变提交历史,因此在对已推送到远程仓库的分支进行 rebase 操作时需要格外小心,以免引发冲突。
考虑有两个分支:source_branch
和 target_branch
。我们想要将 source_branch
上的提交应用到 target_branch
上。
-
初始状态:
A---B---C (target_branch) \ D---E (source_branch)
-
执行
git checkout target_branch
切换到目标分支:A---B---C (target_branch - HEAD) \ D---E (source_branch)
-
执行
git rebase source_branch
:A---B---C---D'---E' (target_branch - HEAD) \ D---E (source_branch)
注意:提交
D
和E
被拷贝到新的提交D'
和E'
上,这是git rebase
的重放过程。- Git 计算
source_branch
和target_branch
之间的差异。 - Git 将差异应用于
target_branch
,创建新的提交序列。
- Git 计算
-
解决冲突(如果有的话):
如果在重放提交的过程中发生冲突,Git 会在每个冲突点停下来,等待用户解决冲突。解决冲突后,继续执行
git rebase --continue
。 -
完成
git rebase
:当所有提交都被成功应用,
git rebase
完成。此时,target_branch
包含了source_branch
上的提交,并且提交历史线性而不是分叉。A---B---C---D'---E' (target_branch - HEAD) \ D---E (source_branch)
这个过程帮助你理解了 git rebase
的基本原理。请注意,git rebase
会改写提交历史,因此在协作开发中需要小心使用,尤其是在共享的分支上。
2.git revert
:
原理: git revert
用于创建新的提交,以撤销之前某次提交的更改。它不会改变原有的提交历史,而是添加一个新的提交,该提交的更改与要撤销的提交相反。
使用场景: 适用于撤销某次提交的更改,并保留原有的提交历史。
注意事项: 适用于公共分支,不会改变已共享的提交历史。
考虑有一个提交历史如下:
A---B---C---D (main - HEAD)
现在,假设我们想要撤销提交 C
的更改。我们可以使用 git revert
来创建一个新的提交,该提交将 C
的更改撤销掉。
-
执行
git revert
:git revert C
这将打开一个编辑器,让你编辑撤销提交的提交信息。你可以保存并关闭编辑器,或者修改提交信息。
-
保存提交信息:
保存并关闭编辑器后,Git 将创建一个新的撤销提交:
A---B---C---D---E (main - HEAD)
这里的
E
是新的撤销提交。它的更改与C
的更改相反,实现了对C
的撤销。
这样,通过 git revert
创建了一个新的提交,用于撤销之前某次提交的更改,而不修改原提交历史。这种方式更安全,特别是在共享分支上。
3.git reset
:
原理: git reset
用于将分支的 HEAD 移动到指定的提交,同时可以选择是否修改工作目录和暂存区。--soft
选项不修改工作目录和暂存区,只是移动 HEAD;--mixed
选项移动 HEAD 同时重置暂存区;--hard
选项会移动 HEAD 并重置暂存区和工作目录。
使用场景: 主要用于撤销一些本地的提交,重新开始一个新的提交历史。
注意事项: 在共享分支上进行 reset 操作时需谨慎,因为它改变了提交历史。
考虑有一个提交历史如下:
A---B---C---D (main - HEAD)
假设我们要使用 git reset
来将当前分支 main
的 HEAD
移动到某个特定的提交,例如 B
。
-
执行
git reset
:git reset B
这将使得
main
分支的HEAD
移动到提交B
,而提交C
和D
不再被直接引用:A---B (main - HEAD) \ C---D
注意:默认情况下,
git reset
使用--mixed
选项,这会将工作目录保留为原样,但是将提交历史和暂存区重置到指定的提交。 -
执行
git reset --hard
(可选):如果想要连工作目录一起回滚,可以使用
--hard
选项:git reset --hard B
这将使得
main
分支的HEAD
、提交历史和工作目录都回滚到提交B
,删除了提交C
和D
:A---B (main - HEAD)
git reset
是一种强大的工具,但在共享分支上使用时需要小心,因为它会改变提交历史。如果提交已经被推送到共享仓库,最好避免使用 git reset
,以免破坏其他协作者的工作。
总体而言,git rebase
用于整理提交历史,git revert
用于撤销某次提交的更改而不改变历史,git reset
用于重新设置当前分支的 HEAD。选择使用哪个命令取决于你的具体需求以及对提交历史的要求。