git回退历史版本无法上传_警惕:错误的Git版本回退姿势

今天公司群里又看到同事做了 force push,手不抖也不潮,他是修改了repo设置,解锁那个branch之后,再用git push -f 强推入库。篡改repo历史,是十分容易遭到谴责的,99%以上的情况,篡改都是错误的操作姿势引起的,并非出自本意。

强推害人不浅,最典型的副作用是让人困惑它让所有pull过被强推版本的小伙伴困惑,下一次没法正常pull和push了

它让集成版本控制系统的系统困惑,例如CI和发布系统,它不知道该怎么做

了解了一下同事的真实需求,他原本只是想把代码回退到某个历史版本中的样子,并没有修改历史的意思,但是不熟悉 git 的概念,用 reset --hard 做了回退,发现 push 不了,不得已才用了强推。

其实 git 的回退是很简单的,假设现在 repo 中master分支的历史是这样子的

A --- B --- C

(HEAD)

其中最后一个 commit C,我们可以称之为HEAD,它是一个可以移动的指针,当你在C的基础上修改 commit 了 D,并且push进去了,repo就会变成这样

本地: A --- B --- C --- D

(HEAD)

repo: A --- B --- C

(HEAD)

结果: A --- B --- C --- D

(HEAD)

这种情况下的 push,是畅通无阻的,因为 repo 的 HEAD C 在你要 push 的 branch中,它只要接纳你的D,并且把 HEAD 指针移动到 D 上就完成了,这个过程也就是 fast forward,git唯一允许的合法提交就是 fast forward,这个 HEAD 指针只能单向的向前移动,不能倒退。

假如你做了 reset --hard

git reset --hard B

本地: A --- B

(HEAD)

repo: A --- B --- C

(HEAD)

此时 repo 中的 C 该何去何从?丢掉吗?这就是篡改历史的过程了。如果别人正好pull过带C的版本,你强推之后,C不见了,他下次pull的时候,他本地git如何面对篡改了的版本历史?

那么需要回退的时候该用什么姿势呢?总结一下最典型的几种情况。

把少量文件回退到B版本

可能这是最简单也最常见的情况了,

git checkout B -- 要回退的文件1 要回退的文件2

然后commit这两个文件得到新的版本D

本地: A --- B --- C --- D

(HEAD)

repo: A --- B --- C

(HEAD)

此时 push,repo可以快速移动指针 HEAD,从C移动到D,push 成功。如果B版本中这个文件不存在,只是想删除呢?更简单,你直接rm删了再commit好了。

回退前1次,或者几次commit的所有变更

这种情况也非常简单,使用 revert undo 掉之前的 commit 就行了

git revert C 产生跟 B 内容一样的新commit B',repo 快速移动到B'就行了

A --- B --- C --- B'

(HEAD)

revert 是逆向回放,如果revert 的是B,由于C的一些变更,可能undo会有冲突,无法自动完成,所以它不是万能的,只适用于某些情况。

回退到某个指定版本

这是最容易引起force push的场景了,那么how to?假设repo如下,想回退到B

A --- B --- C --- D

(HEAD)

git reset --hard B

git reset --soft D

第一个操作把 working, index, HEAD 都强行置为 B,状态如下

A --- B

(HEAD)

第二个操作,把 HEAD 设置回 D,看起来状态如下,B'是跟B内容一样的状态

A --- B --- C --- D --- B'

(HEAD)

此时若 commit,得到如下状态,满足 fast forward

A --- B --- C --- D --- B'

(HEAD)

更好的姿势,不用 git reset --hard B,直接起个新分支

A --- B --- C --- D

(HEAD)

git checkout -b ttt B

git reset --soft D

然后 commit 得到

ttt: A --- B --- C --- D --- B'

(HEAD)

把这个branch推到repo的master

git push origin HEAD:master 或者

git push origin ttt:master 都行

完事之后删掉这个临时的ttt branch即可

开临时新分支的最大的好处,是不会影响master分支,你可以更方便的查看或者切回master。不像hard reset后那样,丢掉了master的历史,只能借助reflog查看和恢复历史。

到底什么时候可以用强推?

纠正错误的历史的时候,比如把密码或者隐私文件入库了

把病毒或者恶意的东西入库了

把苍老师.avi入库了

发生这种状况时,只能rewrite整个库了,然后写邮件道歉并通知所有所有被困惑了的人。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值