前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >git撤销修改各种情况

git撤销修改各种情况

作者头像
fanfan
发布2018-01-24 18:10:53
1.4K0
发布2018-01-24 18:10:53
举报
文章被收录于专栏:编程思想之路编程思想之路

如何在Git里撤销(几乎)任何操作

一、撤销一个已经公开的改变

场景:已经执行了gitpush,将修改发送到了github,需要撤销某一个commit。

方法:git revert<commit版本号>,则改commit的所有改变都会被反转。这是git最安全、最基本的撤销场景。

二、修正最后一个commit消息

场景:在最后一条commit消息里有一个笔误,已经执行git commit –m’xxx’,但在push之前发现说明信息有误

方法:git commit–-amend 或者git commit –amend –m’正确的信息’

原理:git commit–amend会用一个新的commit更新并替换最近的commit,这个心的commit会把任何修改内容和上一个commit的内容结合起来。如果当前没有提出任何修改,这个操作会把上次的commit消息重写一遍。

三、撤销本地修改

场景:git add后恢复,撤销git add。

方法:git checkout– filename

此种撤销会使任何修改完全消失,所以使用前最好用git diff确认下。

四、重置本地的修改

场景:在本地提交了一些东西(还没有push),希望撤销前面的三次提交。

方法:git reset <lastgood SHA>或git reset –hard <last good SHA>

原理:git reset会把代码库历史返回到指定的SHA状态。这样就像这些提交从来没有发生过。缺省情况下,git reset会保留工作目录。这样提交是没有了,但是修改内容还在磁盘上。这是一种安全选择,但通常希望一步就撤销提交及修改内容,这就是—hard选项的功能了。

五、在撤销了本地修改之后再恢复

场景:提交了几个commit后,用git reset –-hard撤销了这些修改,希望还原这些修改。

方法:git reflog和git reset或git checkout

原理:git reflog对于恢复项目历史是一个超棒的资源。可以恢复几乎任何东西——任何你commit过得东西。

一些注意事项:

l  它涉及的只是HEAD的改变。在切换分支、用git commit进行提交、以及用git reset撤销commit时,HEAD都会改变,但是当用git checkout -- <bad filrname>时,HEAD并不会改变,因此reflog也无法恢复。

l  git reflog不会永远保持。Git会定期清理那些用不到的对象,不要指望几个月前的提交还在那里。

l  不能用reflog来恢复另一个开发者没有push过得commit。

l  如果下网准确恢复项目的历史到某个时间点,用gitreset—hard<SHA>

l  如果希望重建工作目录里的一个或多个文件,让它们恢复到某个时间点的状态,用git checkout <SHA> -- <filename>

l  如果希望把这些commit里的某一个重新提交到代码库,用git cherry-pick <SHA>

六、利用分支的另一种做法

场景:进行了一些提交,然后意识到开始check out的是master分支。希望提交到另一个分支(feature)。

方法:git branchfeature,git reset –-hard origin/master,and git checkoutfeature

原理:gitcheckout –b <name>创建新的分支,这是创建新分支并马上check out的流行捷径,但是如果不希望马上切换分支。这里。git branch feature创建一个叫做feature的新分支并指向最近的commit,但还是checkout在master分支上。下一步,在提及任何新的commit之前,用git reset –-hard把master分支倒回到origin/master。不过那些commit还在feature中。最后,用git checkout切换到新的feature分支,并且让你最近所有的工作都完好无损。

七、在master繁殖的基础上创建了feature分支,但master分支已经滞后origin/master很多。现在master分支已经和origin/master同步,你希望在feature上的提交从现在开始,而不是从滞后很多的地方开始。

方法:git checkoutfeature和git rebase master

原理:要达到这个效果,你本来可以通过git reset (不加,--hard,这样可以在磁盘上保留修改)和git checkout –b <new branch name>然后再重新提交修改,不过这样做的话就会失去提交历史。

git rebase master会做如下事情:

Ø  首先他会找到你当前check out的分支和master分支的共同祖先。

Ø  然后它reset当前check out的分支到那个共同祖先,在一个临时保存区存放所有之前的提交。

Ø  然后它把当前check out的分支提交到master的末尾部分,并从临时保存区重新把存放的commit提交到master分支的最后一个commit之后。

八、大量的撤销/恢复

场景:进行了很多次提交,但是发现只需要其中一部分,其他提交需要舍弃。

方法:git rebase–i <earlier SHA>

原理:-i 参数让rebase进入“交互模式”。它开始类似于前面讨论的rebase,但在重新进行提交之前,它会暂停下来并允许详细修改每个提交。

rebase –I 会打开你的缺省文本编译器,里面列出候选的提交。前面两列是键:第一个是选定命令,对应第二列里的SHA确定的commit。缺省情况下,rebase–i假定每个commit都要通过pick命令。

要丢弃一个commit,只要在编辑器里删除那一行就可以了。如果你需要commit的内容,而是对commit消息进行编辑,可以使用reword命令。把第一列里的pick替换为reword(或者直接用r)。有人会觉得这里直接重写commit消息就行了,但是这样不管用rebase –i会忽略SHA列前面的任何东西,它后面的文本只是来帮助我们记住这个commit是来干嘛的。当你完成rebase –i的操作之后,你会被提示输入需要编写的任何commit消息。

如果比需要把两个commit合并到一起,可以使用squash或者fixup命令。Squash和fixup会向上合并,带有这两个命令的commit会被合并它的前一个commit里。如果选择squash,git会提示给新合并的commit一个新的commit消息;fixup则会把合并清单里第一个commit的消息直接给新合并的commit。当你保存并退出编辑器时,git会按从顶部到底部的顺序运用你的commit。可以通过在保存前修改commit顺序来改变运用的顺序。

九、停止追踪一个文件

场景:偶然把application.log加到代码库里了,现在每次运行应用,git都会报告在application.log里有未提交的修改。你把*.login放到了.gitignore文件里,可文件还是在代码库里,怎么才能告诉git撤销对这个文件的追踪呢?

方法:git rm –cachedapplication.log

原理:虽然.gitignore会阻止git追踪文件的修改,甚至不关心文件是否存在,但这只是针对于那些以前从来没有追踪过得文件。一旦有个文件被加入提交,git就会持续关注该文件的改变。如果你希望从git的追踪对象中删除那个本应忽略的文件,git rm –-cached会从追踪对象中删除它,但让文件在磁盘上保持原封不动。因为现在它已经被忽略了,你再git status里就不会再看见这个文件,也不会再偶然提交该文件的修改了。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-08-29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档