总结一下 Git 不同情况下如何回滚

2019-03-02 00:14:09 +08:00
 billyangg

撤销

在未进行git push前的所有操作,都是在“本地仓库”中执行的。我们暂且将“本地仓库”的代码还原操作叫做“撤销”

情况一:文件被修改了,但未执行git add操作(working tree 内撤销) (modify file) <==> git checkout <filename>/.

git checkout fileName
git checkout .

情况二:同时对多个文件执行了git add操作,但本次只想提交其中一部分文件 git add <==> git reset HEAD <filename>

$ git add *
$ git status
# 取消暂存
$ git reset HEAD <filename>

情况三:文件执行了git add操作,但想撤销对其的修改( index 内回滚) (modify file and add) <==> git reset HEAD <filename> && git checkout <filename>

# 取消暂存
git reset HEAD fileName
# 撤销修改
git checkout fileName

情况四:修改的文件已被git commit,但想再次修改不再产生新的 Commit git commit <==> git commit --amend -m 'msg'

# 修改最后一次提交 
$ git add sample.txt
$ git commit --amend -m"说明"

情况五:已在本地进行了多次git commit操作,现在想撤销到其中某次 Commit (git multiple commit) <==> git git reset [--hard|soft|mixed|merge|keep] [commit|HEAD]

一般使用 --soft

git reset [--hard|soft|mixed|merge|keep] [commit|HEAD]

回滚

上述场景二,已进行git push,即已推送到“远程仓库”中。我们将已被提交到“远程仓库”的代码还原操作叫做“回滚”!注意:对远程仓库做回滚操作是有风险的,需提前做好备份和通知其他团队成员!

情况一:切换到 tag 或 branch

如果你每次更新线上,都会打 tag,那恭喜你,你可以很快的处理上述场景二的情况 git tag <==> git checkout <tag>

git checkout <tag>

如果你回到当前 HEAD 指向 (git current HEAD) <==> git checkout <branch_name>

git checkout <branch_name>

情况二:撤销指定文件到指定版本 (git file in history) <==> git checkout <commitID> <filename>

# 查看指定文件的历史版本
git log <filename>
# 回滚到指定 commitID
git checkout <commitID> <filename>

情况三:删除最后一次远程提交 git revert HEAD || git reset --hard HEAD^

方式一:使用 revert 会有新的 commit 记录

git revert HEAD
git push origin master

方式二:使用 reset 不会产生新的 commit 记录

git reset --hard HEAD^
git push origin master -f

二者区别:

情况四:回滚某次提交 (git commit in history) <==> git revert <commitID>

# 找到要回滚的 commitID
git log
git revert commitID

同样的,revert 会出现一次新的 commit 提交记录,这里也可以使用 reset

删除

删除某次提交 (git commit in history) <==> git rebase -i <commitID>

git log --oneline -n5

git rebase -i <commit id>^

**注意:**需要注意最后的_^_号,意思是 commit id 的前一次提交

git rebase -i "5b3ba7a"^

在编辑框中删除相关 commit,如pick 5b3ba7a test2,然后保存退出(如果遇到_冲突_需要先解决_冲突_)!

git push origin master -f

通过上述操作,如果你想对历史多个 commit 进行处理或者,可以选择git rebase -i,只需删除对应的记录就好。rebase 还可对 commit 消息进行编辑,以及合并多个 commit。

转自: https://blog.csdn.net/ligang2585116/article/details/71094887

我的订阅号:JS 菌;希望能给个关注支持我谢谢~

5236 次点击
所在节点    git
27 条回复
rockyou12
2019-03-03 11:00:55 +08:00
@msg7086 做不到就是项目管理问题啊,有啥好说的。而且你开 feature 分支,肯定是从 master 或者 dev 上来的,这两个分支不允许直接提交。然后你 feature 上开发一堆 commit,然后 rebase 成一个 commit,merge 到 master 或 dev 上需要做什么 force push ?你 feature 分支开发完本来删了就是了,你还 rebase 了 push 上去干嘛。
msg7086
2019-03-03 11:15:20 +08:00
@rockyou12 我们就是这么管理项目的。Rebase 了 Push 上去是为了做 Merge Request Peer Review。不做 Peer Review 直接 Squash 成一个 Commit 然后就往主干上塞?我可谢谢您了。
而且我们要求组员都要频繁提交频繁 Push,完成一处修改就 Commit+Push,以避免本地副本意外丢失。
不知道这些被很多人推荐的项目管理实践怎么到你眼中都变成没必要的东西了。

对我们来说,绑着程序员不让他们自由地利用工具来完成项目才是个项目管理问题,有啥好说的。
rockyou12
2019-03-03 12:16:45 +08:00
@msg7086 我确实不理解我说的和你流程上哪点冲突了,你是主动 merge 也好还是 pull request 也好和你代码 review 没啥冲突。

而且说什么自由利用工具,你们项目都知道做 review 就不是为了让你们不乱写代码,别乱用功能吗? git 功能强,但是功能设计是很有问题的,就像 reset、revert,merge、rebase,单看命名鬼知道区别在哪。

再摸着自己良心想想才工作时候的自己把,你能把 git 吃这么透?不深入掌握就没 git 使用权了?你团队个个都是神能 100%不出错? java 这么流行不就是写着感觉吃屎,但很难想 c++一样能恶心到别人。

所以不准用-f 这个屎,只要领导懂技术,还真就肯定要让开发人员吃,不爽也没法。
msg7086
2019-03-03 12:57:01 +08:00
@rockyou12 Git 这么好用的工具,出错了又怎么样? push -f 又不会丢数据,覆盖了有用提交直接从 reflog 里挖出来 push -f 推回去就行了,为什么要个个是神 100%不出错?出错了才能吸取经验才能进步,就是因为怕犯错才天天这也不敢用那也不敢用,Git 用了 10 年也就和刚上手一两年的人一个水平。

而且相反的,不允许-f 来纠正错误,让程序员提心吊胆生怕不小心推错东西一失足成千古恨,才是所谓的「你团队个个都是神能 100%不出错」。

至于你说的 reset revert merge rebase 瞎瘠薄命名的问题,我只能说,找个好点的客户端吧。不要让工具去限制人的发挥。

命令行 Git 功能参数太乱 -> 复杂 Merge/Rebase 容易丢代码 -> 不允许 push -f -> 程序员怕推错提交而自裁提交数量 -> 不再频繁提交与推送

不知道别人怎么样,反正要是哪天不让我用 push -f 了,怕是我连维护手头的那堆开源软件都不知道怎么操作了。
msg7086
2019-03-03 13:03:16 +08:00
Git 包含两部分,一个是底层的文件结构,也就是 .git 目录和里面的数据。
另一个是上面跑的命令行程序。
Git 强大就强大在他的灵活性上,也就是前者强大;而后者功能虽然强,但是结构非常乱,适合被脚本、软件调用,而不是直接面对用户。

他的对手 Hg 则正好相反,Hg 命令行功能很清晰,但是底层 .hg 功能太弱,基本概念照搬 SVN,分支不方便,Rebase 不方便,适合那种一锤定音一次提交就再不用改的人。Git 则是允许用户犯错,错你随便犯,反正都能修回来;代码尽管随手提交,反正后期都能 Interactive Rebase 回来。

我怕的就是把 Git 当高级版 SVN 用的。
rockyou12
2019-03-03 20:28:57 +08:00
@msg7086 最后回一次后面不回了。你说的这些全部都是从个人来考虑,完全不考虑团队。-f 错了,损失的不是 push 错的人的时间,而是整个团队、甚至运维等其他人的时间。

我 tm 当然知道 git 数据肯定不会丢,你服务器炸了每个人手上都还有个副本呢。但你光看到技术上的东西,管理上的完全给无视了。
haoz1w0w
2019-03-03 21:50:42 +08:00
马克

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/540207

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX