6、Git基础操做之撤销操做

版本控制的关键是可撤销性,便可以使项目回退到某些操做以前状态。Git做为一款很是优秀的版本控制软件具有了丰富的撤销的命令来应对不一样的场景,下面咱们来学习一下。html

1.修改最后一次提交

命令:`git commit --amend`
做用:本次提交覆盖上次提交,以此达到修改上次提交的目的。
复制代码

1.1 未修改直接提交

未修改直接再次提交
值得注意的是,两次提交的项目内容和提交人没有变化,可是因为提交的时间不一样,致使commit对象的内容不一样,所以产生内容的ID也不相同。

1.2 修改后再提交

修改后再提交

2. reset、revert和checkout

Git使用reset、revert和checkout三个命令来回退项目到某一个历史快照。
回退有两个影响级别:
1) commit级别:根据指定的commit来恢复项目总体到历史的某一快照。
2) 文件级别:根据指定commit和文件路径来恢复指定文件到某一历史版本。
复制代码

2.1 commit级别回退

1)回退Git仓库

  • 命令:git reset --soft [commit]
  • 做用:把HEAD引用的当前分支的commit引用移动到指定commit,以此达到回退的目的。

恢复git仓库到上一次提交
从新根据reset命令撤销刚才的撤销操做(是否是有点绕口)
撤销刚才的撤销操做
恢复到撤销前的状态

2)回退Git仓库和暂存区

  • 命令:git reset [commit]/git reset --mixed [commit]
  • 做用:本命令会恢复Git仓库到指定commit,并根据指定commit清空覆盖暂存区(不会提示冲突,由于是强行覆盖)。
  • 结果:1)不在指定commit的文件树中的工做区的目录和文件会变成未跟踪状态;2)与指定commit的文件树中的内容不一样的文件会变成已修改状态,待加入暂存区。

回退Git仓库和暂存区

3)回退Git仓库、暂存区和工做区

git reset
  • 命令:git reset --hard [commit]
  • 做用:根据指定commit的文件树,覆盖git仓库和暂存区,清空工做区全部已跟踪文件而后以指定commit的内容代替。
  • 结果:1)只有工做区内处于未跟踪状态的目录和文件会维持原来状态;2)其余文件都会与指定commit内容具备相同内容。

git reset --hard
未跟踪文件不被清除

git revert
  • 命令1:git revert [commit] 做用:打补丁的形式撤销某次历史版本;
  • 命令2:git revert -n [commit]..[commit] 做用:撤销一个commit区间
  • 原理:根据diff操做计算出指定commit与其以前commit的内容差别,针对该差别计算出反补丁,应用反补丁到当前git仓库、暂存区和工做区,并产生一次提交。
  • 条件:1)保持暂存区clean状态;2)工做区不能有和revert补丁冲突的处于已修改状态的文件,例如不能修改同一行等。

git revert
revert的冲突状况

4)reset和revert的区别

初始状态

  • git reset不会产生新的提交,只经过移动HEAD引用的分支指向的commit来恢复项目快照。
    初始状态执行git rest HEAD~后结果
  • git revert不会影响已有历史,它会产生新的提交来撤销某次或必定范围的修改。
    初始状态执行git revert HEAD后结果
  • 区别列表
命令 git reset git revert
原理 改变分支的commit的引用 对已有commit引用打反补丁
反作用 改变commit历史 不会改变commit历史
适用性 本地分支 公共分支
冲突 无冲突 会有冲突
优势 无冲突的恢复到某次历史快照 可针对中间的某次提交进行撤销操做
本质 覆盖操做 修补操做

2.2 文件级别回退

1)回退暂存区文件

  • 命令:git reset [commit] [file],如果commit是HEAD可替换为--
  • 做用:根据指定commit,撤销暂存区指定文件的操做;
  • 结果:若新增,则删除;若删除和修改,则恢复。

2)回退工做区文件

  • 命令1:git checkout file
  • 做用:把暂存区文件检出到工做区;
  • 命令2:git chekcout [commit] [file],如果commit是HEAD可替换为--
  • 做用:根据指定commit,从git仓库检出指定文件到暂存区工做区

3.提交树

Git中每次提交都会存储在Git仓库,只是有些提交通过reset、删除分支、删除储藏等操做后不被分支和标签引用,变成悬挂状态(dangling)。咱们能够经过如下命令查看这些提交(Git的提交树和vim的undo树殊途同归)。node

1)完整提交树

  • 命令:git log -ggit reflog来查看
  • 做用:显示全部操做,包括撤销的。

2)有效提交树

  • 命令:git log查看
  • 做用:显示当前有效的操做

3)撤销的悬挂提交(dangling commit)

  • 命令:git fsck --lost-found
  • 做用:经过校验Git仓库的完整性(经过引用链),找出悬挂对象。

4)一图以蔽之

提交树

4.储藏和恢复

因为revert、分支合并等场景下的操做会与工做区和暂存区的内容产生冲突,若不想提交当前工做区和暂存区的修改内容,能够经过储藏命令将其储藏起来,而后在合适的时候恢复工做区和暂存区。git

git stash       # 储藏当前工做区和暂存区
git stash list  # 查看当前的储藏列表
git stash apply # 恢复上一次的储藏内容
git stach pop   # 恢复上一次的储藏内容,并将其从储藏区删除
复制代码

5.清除未跟踪文件

  • 命令1:git clean -f 做用:删除未跟踪文件
  • 命令2:git clean -df 做用:删除未跟踪文件和目录
  • 通常与git reset --hard命令搭配使用。
git reset --hard commit  # 恢复git仓库、暂存区和工做区(不包含未跟踪内容)到指定commit
git clean -df # 删除当前处于未跟踪状态的文件和目录
git status # 当前处于commit,且暂存区和工做区都处于clean状态
复制代码

参考

  1. 代码回滚:git reset、git checkout和git revert区别和联系
  2. 在 git 中找回丢失的 commit
  3. Git 工具 - 储藏(Stashing)
  4. Git的"~"和"^"的区别
相关文章
相关标签/搜索