git 撤销提交操作
Git 撤销操作指南 在使用 Git 进行版本控制时,撤销操作是必不可少的技能。本文将介绍 Git 中常用的撤销操作,涵盖硬盘、暂存区、本地仓库和远端仓库四个区域。
Git 区域概述
- 硬盘 (disk): 存储着本地文件的实际内容。
- 暂存区 (staging): 用于暂存即将提交的文件修改。
- 本地仓库 (local): 存储着所有提交的历史记录和分支信息。
- 远端仓库 (remote): 通常指 GitHub 等远程托管平台上的仓库。
常用撤销操作
1. 撤销对文件的修改
- 场景: 你对文件进行了修改,但想要撤销这些修改,恢复到之前的状态。
- 操作:
git checkout <文件名>
或git restore <文件名>
这两个命令会将文件恢复到暂存区或本地仓库中的最新状态,从而撤销所有修改。
2. 取消暂存区的修改
- 场景: 你已经将文件修改添加到暂存区,但想要撤销这个操作,保留硬盘上的修改。
- 操作:
git reset <文件名>
或git restore --staged <文件名>
这两个命令会将文件从暂存区移除,但不会影响硬盘上的修改。
3. 撤销所有修改
- 场景: 你想要撤销所有对文件的修改,包括暂存区和硬盘上的修改。
- 操作:
git checkout HEAD <文件名>
注意: 这个命令会丢失硬盘上的所有修改,请谨慎使用。
3.5 撤销单个提交
- 场景: 你想要撤销最近一次提交,但保留暂存区和硬盘上的修改。
- 操作:
git reset --soft HEAD~1
这个命令会将本地仓库回退到前一个提交,但保留暂存区和硬盘上的修改。
4. 撤销提交并保留修改
- 场景: 你想要撤销最近一次提交,并保留暂存区中的修改。
- 操作:
git reset HEAD~1
或git reset --mixed HEAD~1
这两个命令会将本地仓库和暂存区回退到前一个提交,但保留硬盘上的修改。
5. 撤销提交并删除修改
- 场景: 你想要撤销最近一次提交,并删除暂存区和硬盘上的修改,完全恢复到前一个提交的状态。
- 操作:
git reset --hard HEAD~1
注意: 这个命令会丢失所有修改,请谨慎使用。
6. 撤销任意提交
- 场景: 你想要撤销任意一次提交,并保留后续提交。
- 操作:
git revert <commit-hash>
这个命令会创建一个新的提交,其内容与指定提交完全相反,从而撤销该提交的影响。
公有分支与个人分支
- 公有分支: 指多人共同使用的分支,如项目的主分支。
- 个人分支: 指仅个人使用的分支,如功能分支。
注意: 对于公有分支,只能使用
git revert
命令撤销提交,因为git reset
命令会破坏分支的完整性。对于个人分支,可以使用git reset
命令撤销提交,并使用git push -f
强制推送修改到远端仓库。
总结
掌握 Git 的撤销操作,可以帮助你更好地管理代码版本,避免错误修改带来的麻烦。请根据实际情况选择合适的撤销命令,并谨慎使用 git reset --hard
等可能造成数据丢失的命令。
原始版
我们在使用 git 的时候经常会需要撤销我们做的修改,然而 git 作为一个相对复杂的版本控制软件,它的撤销并不像文本编辑器一样按一个 CTRL+Z 那么简单 总结一下在 git 里面最常用最实用的撤销操作在使用 git 的时候我们一般会涉及到4个区域,分别是我们的:
- 硬盘(disk)
- 暂存区(staging)
- 本地的git 我们管它叫 (local)
- 远端的git比如说github 我们管它叫(remote)
我们现在假设在初始状态下这4个区域是保持同步的也就都只有一个 init commit
操作1
我们假设我对代码文件进行了一些修改这个时候如果你用 git diff 你是可以看到你的修改的也就是修改后的文件跟git里面目前保存的文件有什么不一样,如果你使用 git status 会发现这个文件在 changes not state for commit 这个底下一般来说呢这个文件会显示成红色的那我们第一个可能涉及到的修改就是
我发现我现在对文件的修改是错误的我想撤销掉所有对文件的修改
在这种情况下我们可以使用
git checkout 这个文件名
来恢复这个文件之前的状态也就是把我们硬盘上对这个文件的修改撤销。在比较新的git版本中你还可以使用
get restore 这个文件名
这是因为在比较古老的git版本中 checkout 这个命令它肩负了两个使命,而比较新的版本中想把这两个使命给分开。这两个命令在当前这种情况下使用的时候效果是一样的 喜欢用哪个都行
操作2
如果我们在完成了对文件的修改之后使用了git add 这个文件那这个修改就会被同步到暂存区(staging)这个时候使用 git status 就会发现你修改的这个文件被放到了 changes to be committed 底下,一般来说显示出来是绿色的。在这种情况下如果我们想把这个修改从暂存区(staging)移除但还保留硬盘(disk)上的修改。
也就是我们想撤销这个git add的操作
可以使用
git reset 这个文件名
或者在比较新的版本里面
git restore--staged 这个文件名
这个操作比较安全只会把文件从暂存区(staging)移出让你 commit 的时候不再 commit 这个文件它不会对你硬盘上的源代码本身进行修改。
操作3
如果你就是想撤销掉你所有的修改包括暂存区(staging)和硬盘(disk)上的修改你可以使用
git checkout HEAD 加上你的文件名
这个HEAD在git里面表示最近的一次commit,在目前例子中也就代表了init 。 这里注意,这个操作会让你丢失硬盘上的修改使用的时候要小心
操作3.5
如果你再把文件加入暂存区(staging)之后,使用了git commit
那你的修改就正式成为了一个commit,并且被放到了local git 里
在这种情况下,如果我们只是想单纯的撤销这个 commit 我们可以用
git reset --soft HEAD~1
我们刚才说过 HEAD 表示最近的一次 commit 。在目前的情况下就是 change 这个 commit~1 代表之前一个 HEAD~1 指向的是 init 。这个命令的意思是把 local git 的状态变成 init 这个 commit 。在运行完这个命令之后你硬盘里的文件不会变这个变化也会被保留在暂存区只是local git里面这个commit被你干掉了。
操作4
那当然有 soft 就有不 soft。如果你直接使用git reset HEAD~1
的话,它等价于你使用git reset --mixed HEAD~1
同时撤销你的 git commit 和 git add 也就是把你这个 commit 拿掉也会把这个文件从暂存区(staging)拿掉,只保留你硬盘(disk)上的修改当然我们还可以再进一步使用
git reset --hard HEAD~1
这里会把你这个修改从local git 暂存区(staging)和硬盘(disk)里面同时删掉也就是完整的恢复到初始状态那大家使用这个命令的时候呢要稍微小心一点
尽管这个命令本身是可撤销的他并不会立刻删除你所有的数据但是想找回来啊稍微有点麻烦。起码你直观上看啊你的修改就都没有了所以用的时候呢一定要过一下脑子
当然这里我们举例的时候都是用的 HEAD~1 那如果你想往回退两个 commit呢 就 HEAD~2 退3个就 HEAD~3
git reset命令可以让你退回到之前任意一个 commit 的状态
操作5
那在我们完成了 git commit 之后我们还有另外一种形式的撤销就是 git revert 。
和 git reset 不一样 get revert 本质上是在给你增加一个 commit 而这个 commit 的效果,恰好是你之前那个 commit 反过来。比如你之前那个 commit 在这加了一行我就在这给你减一行,所以在这里呢我们把这个反作用的 commit 我们叫 -change。
get revert 命令的参数是一个或者多个 commit 在这里我们给的参数是 HEAD。而HEAD也就是 change 这个 commit 所以他会把 change 这个 commit 里面加的东西变成减,减的东西变成加。
弄出来一个新的 commit 然后再放到 git 上那最终效果 init 增加了一个 change 又增加了一个 -change 他还会回到init状态,这里大家可能要花点时间思考一下。
因为这个 revert 不是那么直观他和我们的直觉有点相悖,他相当于和面的时候不是我水倒多了我把水给舀出去。是水多了我倒点面,面多了我再倒点水,他是一个往上添加反作用的过程。
那么和 reset 这个相对直观的命令相比 revert 有什么好处呢?
首先我们之前提到过 reset 只能回到之前某一个 commit 的状态,但是 revert 可以撤销中间任意一个 commit。 比如说我们从init的开始,然后commit了一个 change1 又 commit 了一个 change2 .假设这个 change1 的hash是 70a0…这个时候我们可以用
git revert 70a0
在这个链上面增加一个 -change 这样我们最终得到的结果就相当于是在 init 的上面直接做了一个 change2 这个效果是我们用 get reset 没有办法轻松的达到的。
还有一个更重要的好处
当我们把 local git 这些修改用 git push到了远端比如说 github 上面之后,这个修改就离开本地到了公域了,这时候我们就要判断我们使用的这个分支是公有分支还是个人分支,什么叫公有分支?只要不止你一个人在使用这个分支这个分支就是公有分支。比如说,几乎所有项目的主分支都是公有分支,那你自己的 feature branch 可能是个人分支。
对于公有分支来说你是只可以往前走不可以往后退的,或者说你是只能增加不能减少的,因为你一旦做了一个删除操作别人的分支就乱套了,当其他人在尝试拉取这个公有分支的修改的时候,他会发现
这个分支跟我保存的这个比怎么少了点东西呢 ?
所以当我们的修改目标是一个公有分支的时候我们只能使用 git revert 命令在这个公有分支上先加一个 commit 然后从结果上撤销我们之前的修改。我们使用的是 git revert 由于本质上我们只是增加了一个 commit,所以我们可以直接使用 git push 命令。
如果我们修改的分支是个人分支除了你之外没有任何其他人用你就可以用这个 git reset 把这个commit直接砍掉。 这个时候如果你想同步到远端的话你必须使用 get push -f 这个 f 代表 force . 因为当你正常push的时候,远端的git会发现
哎你这个分支怎么少了 commit
它会不高兴的,所以你要用 -f 来强迫它接受你的修改。 对于公有分支绝对不应该使用-f. 但是如果这个分支是个人分支的话,你是可以使用-f让你的commit看起来更加的简洁的。