• home > tools > versionControl > git >

    head/reset/revert/rebase代码回滚全解:git提交记录的背后原理

    Author:[email protected] Date:

    git无操作,提交了某条历史记录,想在远程删除,怎么办?有时候把错误的代码提交到远程,但是又不想让其他同事看到怎么办呢?怎么让代码恢复到之前的某个版本?git恢复到以前版本

    多人合作程序开发的过程中,我们有时会出现错误提交的情况,此时我们希望能撤销提交操作,让程序回到提交前的样子,操作有:回退(reset)、反转(revert)。

    git的版本管理,及HEAD的理解

    使用git的每次提交,Git都会自动把它们串成一条时间线,这条时间线就是一个分支。如果没有新建分支,那么只有一条时间线,即只有一个分支,在Git里,这个分支叫主分支,即master分支。有一个HEAD指针指向当前分支(只有一个分支的情况下会指向master,而master是指向最新提交)。每个版本都会有自己的版本信息,如特有的版本号、版本名等。如下图,假设只有一个分支:

    这里写图片描述

    还需了解的术语

    • HEAD:这是当前分支版本顶端的别名,也就是在当前分支你最近的一个提交

    • Index:index也被称为staging area,是指一整套即将被下一个提交的文件集合。他也是将成为HEAD的父亲的那个commit

    • Working Copy:working copy代表你正在工作的那个文件集

    • Flow:git项目管理的流程和规划。比如分支规划:Master/Devlop 分支、Feature 分支、Release 分支、Hotfix 分支

    理解 Git 处理分支的方式

    commit 操作会为每目录每一个文件计算hash校验,然后在 Git 仓库中将这些校验和保存为树对象。

    随后,Git 会创建一个提交对象(commit object)。该提交对象会包含一个指向暂存内容快照的指针。还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针。如此一来,Git 就可以在需要的时候重现此次保存的快照。

    然后会把当前版本的文件快照保存到 Git 仓库中(Git 使用 blob 对象来保存它们),最终将校验和加入到暂存区域等待提交。

    首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象,而由多个分支合并产生的提交对象有多个父对象,

    Git 仓库中有五个对象:三个 blob 对象(保存着文件快照)、一个树对象(记录着目录结构和 blob 对象索引)以及一个提交对象(包含着指向前述树对象的指针和所有提交信息)。

    Git 保存的不是文件的变化或者差异,而是一系列不同时刻的文件快照

    HEAD是指当前的快照,这个命令主要配合reset的--hard,--mixed和--solf三个参数对对本次的修改进行处理

    • HEAD~1指回退一个快照,可以简写为HEAD~

    • HEAD~2指回退两个快照,

    • HEAD^主要是控制merge之后回退的方向

    • HEAD~才是回退的步数

    通过命令行删除远程和本地提交记录

    git reset回滚某次提交

    确保还没其他人提交之前,进行强制回滚——重置HEAD(当前分支的版本顶端)到另外一个commit

    git reset --hard HEAD~2

    •  git reset 代码撤回

    • --hard 和 --soft 及默认mixed

      • --hard就是删除提交记录并不保存所删除记录所做的更改——将重置HEAD返回到另外一个commit

        重置index以便反映HEAD的变化,并且重置working copy也使得其完全匹配起来。这是一个比较危险的动作,具有破坏性,数据因此可能会丢失!

      • --soft 虽然删除了最近两个提交记录,但是还保存了提交所做的更改——告诉Git重置HEAD到另外一个commit,但也到此为止

        index,working copy都不会做任何变化,所有的在original HEAD和你重置到的那个commit之间的所有变更集都放在stage(index)区域中。

      • --mixed是reset的默认参数。它将重置HEAD到另外一个commit,并且重置index以便和HEAD相匹配,但是也到此为止。

        working copy不会被更改。所有该branch上从original HEAD(commit)到你重置到的那个commit之间的所有变更将作为local modifications保存在working area中,(被标示为local modification or untracked via git status),但是并未staged的状态,你可以重新检视然后再做修改和commit

    • 数字代表回退几个版本

    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

    关闭分支的protected权限

    但是,你根据上面命令,确无法操作成功,比如报如下提示:

     ! [remote rejected] master -> master (pre-receive hook declined)

    这个分支权限被限制了

    settings/repository/Protected Branches  ->un protected

    git revert放弃某次提交

    git revert 之前的提交仍会保留在git log中,而此次撤销会做为一次新的提交。

    revert和reset 操作上都差不多,不同的是:

    • git revert 是撤销某次操作,此次操作之前的commit都会被保留

    • git reset 是撤销某次提交,但是此次之后的修改都会被退回到暂存区

    • git reset操作会将版本回退至指定的commit,指定commit后的操作都将被撤销

    • 而git revert则撤销指定commit的修改,同时生成一个新的commit


    git rebase 重建提交顺序

    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 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://blog.csdn.net/yxlshk/article/details/79944535




    转载本站文章《head/reset/revert/rebase代码回滚全解:git提交记录的背后原理》,
    请注明出处:https://www.zhoulujun.cn/html/tools/VCS/git/4828.html