reset
git reset [--soft | --mixed | --hard] [HEAD|哈希] [ |文件]
多人协作时不要使用 git reset --hard,会将其他人的代码删除掉;
原理
git reset 命令用于回退版本,可以指定退回某一次提交的版本,即修改 HEAD 的位置,即将 HEAD 指向的位置改变为之前存在的某个版本;
git reset 切换到指定位置之后,根据使用模式的不同,会做出不同的反应;
三种模式
模式 | 描述 |
---|---|
mixed(默认) | 将撤回的代码,存放到工作区,同时会保留本地未提交的内容 |
soft | 回退到某个版本,将撤回的代码,存放到暂存区,同时会保留本地未提交的内容 |
hard | 彻底回退到某个版本,丢弃将撤回的代码,本地没有 commit 的修改会被全部擦掉 |
HEAD 说明
# 表示当前版本
HEAD
# 上一个版本
HEAD^
# 上上一个版本
HEAD^^
# 上上上一个版本
HEAD^^^
......
# 表示当前版本
HEAD~0
# 上一个版本
HEAD~1
# 上上一个版本
HEAD^2
# 上上上一个版本
HEAD^3
......
revert
原理
git revert 创建一个新的提交,撤销之前的提交,不会更改 Git 的提交历史;
git revert 创建的新的提交将包含之前提交的相反的变更 (git revert 是反做撤销其中的 commit-id,然后重新生成一个commit-id,本身不会对其他任何的提交 commit-id 产生影响);
git revert 其实算是一个进度往前走的逆向提交,也就是说 HEAD 版本及提交记录将会继续前进,只是新的 commit 的内容和要 revert 的内容正好相反,能够抵消要被 revert 的内容;
回退 revert
如果想要对已经 revert 一次的代码进行恢复,需要对 revert 的 commit-id 再次 revert 即可 “负负得正” 恢复最开始的状态;
回退 merge
对于 revert 撤回 Merge 提交,必须重新把 Revert 的再 Revert 回去,不然 Git 会认为你不需要这些内容;也就是说,下一次 Merge 的时候,会丢失代码!
# revert 并不知道 merge 之后哪个分支是主线、支线,所以 -m 1 来指定主线/支线的 commit-id
# 选择主线就还原非主线,选择非主线就还原主线
git revert -m 1 3b5ad0c
rebase
多人协作时不要使用 git rebase,会篡改提交历史,不好追踪溯源;
什么是变基
当执行 rebase 操作时,git 会从两个分支的共同祖先开始提取待变基分支上的修改,然后将待变基分支指向基分支的最新提交,最后将刚才提取的修改应用到基分支的最新提交的后面;
rebase 工作流程
-
构造两个分支 master 和 feature,其中 feature 是在提交点 B 处从 master 上拉出的分支,master 上有一个新提交 M,feature 上有两个新提交 C 和 D;
-
此时切换到 feature 分支上,执行 rebase 命令,相当于是想要把 master 分支合并到 feature 分支 (这一步的场景就可以类比为我们在自己的分支 feature 上开发了一段时间了,准备从主干 master 上拉一下最新改动,模拟了 git pull --rebase 的情形)
# 这两条命令等价于 git rebase master feature git checkout feature git rebase master
-
rebase 变基,可以直接理解为改变基底:
- feature 分支是基于 master 分支的 B 拉出来的分支,feature 的基底是 B,而 master 在 B 之后有新的提交,就相当于此时要用 master 上新的提交 M 来作为 feature 分支的新基底;
- 实际操作为把 B 之后 feature 的提交 C、D 先暂存下来,然后删掉原来这些提交,再找到 master 的最新提交位置 M,把存下来的提交再接上去 (接上去是逐个和新基底处理冲突的过程,此时的 C’、D’ 已经不是原来的 C、D 了),如此 feature 分支的基底就相当于变成了 M 而不是原来的 B 了;
- 注意:如果 master 上在 B 以后没有新提交,那么就还是用原来的 B 作为基,rebase 操作相当于无效,此时和 git merge 就基本没区别了,差异只在于 git merge 会多一条记录 Merge 操作的提交记录;
ES6+ 箭头函数
上一篇