多人合作程序开发的过程中,我们有时会出现错误提交的情况,此时我们希望能撤销提交操作,让程序回到提交前的样子,操作有:
回退(reset):reset是彻底回退到指定的commit版本,该commit后的所有commit都将被清除;reset执行后不会产生记录
反转(revert):revert仅是撤销指定commit的修改,并不影响后续的commit。revert执行后会产生记录。
reset,revert都有撤销、回退的意思,但却各有千秋,区别还是很大的,所以该使用哪种命令一定要结合实际情况来决定。要搞清这些,还是得多学习下git基础知识。
一个基本的 Git 工作流程如下:
使用git的每次提交,Git都会自动把它们串成一条时间线,这条时间线就是一个分支。
如果没有新建分支,那么只有一条时间线,即只有一个分支,在Git里,这个分支叫主分支,即master分支。
有一个HEAD指针指向当前分支(只有一个分支的情况下会指向master,而master是指向最新提交)。
每个版本都会有自己的版本信息,如特有的版本号、版本名等。如下图,假设只有一个分支:
还需了解的术语
三个 blob 对象(保存着文件快照)、一个树对象(记录着目录结构和 blob 对象索引)以及一个提交对象(包含着指向前述树对象的指针和所有提交信息)。
Git 保存的不是文件的变化或者差异,而是一系列不同时刻的文件快照。
这个命令主要配合reset的--hard,--mixed和--solf三个参数对对本次的修改进行处理
通过命令行删除远程和本地提交记录
当文件在工作区修改,还没有提交到暂存区和本地仓库时,可以用 git checkout -- 文件名 来回滚这部分修改。
执行以下命令回滚工作区的修改:
git checkout -- build.sh
不过需要特别留意的是这些改动没有提交到 Git 仓库,Git 无法追踪其历史,一旦回滚就直接丢弃了。
示例: 用 git status 查看,还没提交到暂存区的修改出现在 “Changes not staged for commit:” 部分。
即执行过 git add 添加到暂存区,但还没 commit,这时可以用 git reset HEAD 文件名 回滚。
执行以下命令回滚暂存区的修改:
git reset HEAD build.sh
回滚后工作区会保留该文件的改动,可重新编辑再提交,或者 git checkout -- 文件名 彻底丢弃修改。
即已经提交到本地代码库了,不过还没有 push 到远端。这时候可用 git reset 命令,命令格式为:
git reset <要回滚到的 commit> 或者 git reset --hard <要回滚到的 commit>
需注意的是,提供的是 要回滚到的 commit,该 commit 之后的提交记录会被丢弃。
注意!此时不能用 "git reset",需要用 "git revert"!
重要事情说三遍!之所以这样强调,是因为 "git reset" 会抹掉历史,用在已经 push 的记录上会带来各种问题;而 "git revert" 用于回滚某次提交的内容,并生成新的提交,不会抹掉历史。
命令 | 是否抹掉历史 | 适用场景 |
---|---|---|
git reset | 是,回滚的历史将消失 | 本地未push的记录 |
git revert | 否,历史记录保留,回滚后重新生成提交记录 | 回滚已push的内容 |
确保还没其他人提交之前,进行强制回滚——重置HEAD(当前分支的版本顶端)到另外一个commit
git reset --hard HEAD~2
git push -f ////强制覆盖
记住git reset不会产生commits,它仅仅更新一个branch(branch本身就是一个指向一个commit的指针)指向另外一个commit(Head和branch Tip同时移动保持一致).其他的仅剩对于index和work tree(working directory)有什么影响。git checkout xxxCommit则只影响HEAD,如果xxxCommit和一个branch tip是一致的话,则HEAD和branch相匹配,如果xxxCommit并不和任何branch tip相一致,则git进入detached HEAD 状态
如果别已经提交了代码,怎么删除远程的历史提交记录
git reset --hard 2b93fa8bdc8a1ca8e0c7498bd56460e6d1c408d1 //跟版本号
git push origin HEAD --force
但是,你根据上面命令,确无法操作成功,比如报如下提示:
! [remote rejected] master -> master (pre-receive hook declined)
这个分支权限被限制了
settings/repository/Protected Branches ->un protected
git revert 之前的提交仍会保留在git log中,而此次撤销会做为一次新的提交。
revert和reset 操作上都差不多,不同的是:
git rebase --onto
然后开始删除提交记录2,3[执行 rebase 时会可能遇到冲突,解决冲突不在本文描述范围
git rebase --onto master~3 master~1 master
删除某条commit记录
git rebase -i d65f0fba23f2113ece6fbb3d104a33a1a8a80406
会进入vim模式,pick改为drop即可,具体操作,查看:https://www.jianshu.com/p/520f8661659c
顺便推荐下:《git中merge还是rebase?git之圣战merge vs rebase 》
参考文章:
Git 代码回滚与找回的艺术https://segmentfault.com/a/1190000039320926
git reset soft,hard,mixed之区别深解 https://www.cnblogs.com/kidsitcn/p/4513297.html
git 理解 HEAD^与HEAD~ https://blog.csdn.net/claroja/article/details/78858411
git reset revert rebase 区别 https://blog.csdn.net/lainegates/article/details/72897693
git reset 、rebase和 revert的区别 https://blog.csdn.net/rebeccachong/article/details/39379703
git reset与git revert的区别 https://segmentfault.com/a/1190000019153248
代码回滚:git reset、git checkout和git revert区别和联系 https://www.cnblogs.com/houpeiyong/p/5890748.html
git中reset和revert的区别是什么 https://www.php.cn/tool/git/485052.html
Git恢复之前版本的两种方法reset、revert(图文详解) https://blog.csdn.net/yxlshk/article/details/79944535
转载本站文章《head/reset/revert/rebase代码回滚全解:git提交记录的背后原理》, 请注明出处:https://www.zhoulujun.cn/html/tools/VCS/git/4828.html
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。