网上有关“Git新手教程-撤销更改(七)”话题很是火热,小编也是针对Git新手教程-撤销更改(七)寻找了一些与之相关的一些信息进行分析,如果能碰巧解决你现在面临的问题,希望能够帮助到您。
在前面的文章中,我们学习了标签、分支、和合并。现在我们将学习Git中另外的三个命令 git commit --amend , git revert , git reset 。下面简单的介绍中几个命令的功能:
在平时的项目开发中,有时候我们可能提交完相应文件后,才发现漏掉了几个文件没有添加,或者我们 commit 消息并没有书写完整或有错别字。那这个时候我们该整么办呢?或许我们会执行一个新的提交来添加我们遗漏的内容,但是这样一点都不优雅!!在Git中为我们提供了带有 --amend 选项的提交来修改我们 最近 的提交:
这里大家可能还是不是很明白,我们看下面这个简单的例子:
在上述例仓库中我们创建了一个 commit ,该 commit 消息并没有书写完整。这个时候我们想修改它,那么我们就可以使用命令 git commit --amend ,当输入该命令后,我们能得到如下弹窗:
这个时候,我们就可以完善该 commit 信息,然后保存并离开。这里我改成了 删除了多余的语句 ,这时我们再使用 git log 命令,我们会发现我们的 commit 消息已经被更改了。如下所示:
当然在上述例子中,我们只是简单的修改了 commit 信息,并没有修改或添加一些新的文件,如果你修改或添加了新的文件,并想将这些修改的文件添加到最近的 commit 中去的话,那么你可能要经历以下步骤:
在实际的项目中,如果你想修改最近的 commit ,那么你需要使用 git commit --amend 来更新最近的 commit ,而不是创建新的 commit 。
在上述例子中,我们知道了如何修改最近的 commit ,但是如果我们想还原这个 commit 。那这个时候,我们又该怎么办呢?我们可以使用 git revert 命令来告诉 Git 还原之前创建的commit,该命令使用的方式如下:
还是以上述例子来进行讲解,比如我们想还原下图中红色框中的 commit :
我们可以使用 git revert b71b40 ,需要注意的是使用该命令,默认会创建一个新的提交。如下图所示:
一般情况下,我们可以使用Git系统默认的 revert 信息。当我们保存并退出后,再使用 git log 命令查看我们的日志提交记录,我们能得到下图:
在上述例子中,我们学会了如何还原一个提交,但是如果我们本是这个提交就是错误的,我们并不想要这个提交,也不想仓库记录中包含 revert 的提交记录。这个时候我们又该怎么办呢?我们可以使用 git reset 命令来告诉 Git 重置 commit 。
重置(reset) 似乎和 还原(revert) 相似,但它们实际上差别很大。还原会创建一个新的 commit,并还原或撤消之前的 commit。但是重置会清除 commit!
git reset 命令相比其他 Git 命令功能要多一点,可以用来:
git reset 并不直接使用 commit 的 SHA ,而是使用特殊的 "祖先引用" 来告诉 Git 将 HEAD 指针移动到哪个commit。我们来看看这些特殊的符号。
我们可以通过以下方式引用之前的 commit:
^ 和 ~ 的区别主要体现在通过合并而创建的 commit 中。合并 commit 具有两个父级。对于合并 commit, ^ 引用用来表示第一个父 commit,而 ^2 表示第二个父 commit。第一个父 commit 是当你运行 git merge 时所处的分支,而第二个父 commit 是被合并的分支。
我们看下面的例子,来一起来理解:
因为 HEAD 指向 b71b405 commmit。
了解了祖先引用,现在我们来了解 git reset 命令的使用:
一般情况下,使用该命令,我们会添加如下选项:
直接理解这些选项比较困难,下面我们将结合与实际例子来进行讲解。
在下图中,假如我们的仓库中已经有了如下提交 D、E、F、G、H ,其中 master 指向最近的提交 H , HEAD 指向 master 。
这个时候我们如果使用 git reset --mixed HEAD~1 那么会将 master 与 HEAD 将会指向前一个提交 G 。同时 G 提交会移动到工作目录中。如下图所示:
当 H 提交修改的文件被移动到到工作目录后,文件的状态都为 modifed ,也就是我们需要重新添加到暂存区,然后进行 commit 。我们继续看下面的例子:
在上述仓库中有3个提交,其中 HEAD 指向 bb780f9 上的 master , 这个时候如果我们运行 git reset HEAD~ 命令,会将 commit bb780f9 中的文件移动到工作目录中,如下所示:
调用 git status 来查看我们的仓库状态,我们会发现使用 --mixed 选项,是不会暂存我们的更改的,也就是不会将相应提交的文件放入暂存区中。
当使用 --soft 选项时,不仅会移动 master 与 HEAD 指针,还会将相应修改添加到暂存区中,如下所示:
我们继续查看下面的例子:
最后我们再来看看 --hard 选项:
使用 --hard 将清除对应 commit 所作的更改,继续查看下面的?的例子:
当使用了 --hard 选项后,发现仓库中对应的提交消失了。
当我们直接使用 git reset 或 git reset HEAD 时,表示清除暂存区中的 commit 。下面我们来看这个例子:
那么如果我们只想将 B.java 文件从暂存区中移除,那我们又该怎么办呢?我们可以使用如下命令:
当然在Git中支持多个文件的取消暂存,具体命令如下:
在上述命令中 <file>... 代表一个或多个文件。
最后还是回到我们熟悉的图形化界面的使用流程中。我们来看看IDEA为我们提供了哪些便利吧。
在创建相应 commmit 时,我们可以勾选下图中的
Amend commit 选项。如下所示:
上述操作与使用 git commit --amend 命令的效果一样。
通过依次点击编译器底部的 Version Control -> Log ,然后选择想要 revert 的 commit ,点击鼠标 右键 ,选择 Revert Commit 就可以啦~
通过依次点击编译器底部的 Version Control -> Log ,然后选择想要 reset 的 commit ,点击鼠标 右键 ,选择 Reset Current Branch to Here.. 就完成第一步啦~
当然在第二步中,我们需要选择 git reset 中的选项,在 IDEA 中提供了四种选项 Soft、Mixed、Hard、Keep ,如下所示:
在上图中,我们不熟悉的只有 --keep 选项,因为该选项在平时中的项目并不常用,所以这里就不做更多介绍了,有兴趣的小伙伴,可以查看官方文档中 git reset 中对其的介绍。
站在巨人的肩膀上,才能看的更远~
你刚刚将你本地的分支推送到了远程仓库中,但是却突然发现到其中的一个Commit错了,或者有一些很严重的拼写错误。当然,这没什么大不了的,你能解决。但是你必须手脚快一点,在别人同步这些Commit前解决它,否则被坑了的同事会画小圈圈诅咒你的:)
首先,有两个备选方案可以让你的历史记录完好无损:
备选方案一:在一个新的Commit中改正错误
最简单的方法就是将错误的文件修复好后作为一个新的Commit提交,并同步到远程仓库中。这是一种很直观、也很安全的修复方式,在99%的情况下你都应该使用这种方法,除非这个错的Commit中包含敏感信息。
备选方案二:完全恢复(Revert)这个Commit
有时候你会希望撤销一个Commit的全部更改,幸运的是你可以告诉Git去恢复这个Commit而不用手动地去做这件事。恢复的时候甚至可以不必是最后一个Commit。恢复一个Commit意味着你会撤销这个错误的Commit中的所有更改。就像刚刚的例子中,这个错误的Commit的记录仍然存在,只不过它不再影响当前工作的分支和任何后续的Commit了。
$ git revert dd61ab32
关于历史重写
一般来说我们会避免重写提交的Commit历史,一个很重要的原因就是它会使其他Clone过或Fork过你代码的人和你岔出不同的分支,导致他们不再能pull你重写了的历史记录和后续Commit。如果他们在本地做了一些更改想同步到远程仓库上,需要一些高级的Git知识来理解怎样让Git正常进行工作。
然而有时候你确实就像重写历史记录,无论是因为泄露了敏感信息还是想清除一些本不应该在代码中的非常庞大的文件,亦或者你仅仅就是想要一个干净的历史记录(当然我确实这么做过)。
我平常迁移Subversion或Mercurial项目到Git中时也做过大量的重写历史记录的工作,无论是为了统一LF行结束符,修改提交者的名字、邮箱地址,还是为了从版本库中彻底删除那些大文件。最近我也因为一个大的版本库中一个很早的Commit引起了越来越来多错误而重写了版本库历史。
是的,如果可能的话你应该重写那些已经扩散到了其他fork代码中的历史记录,即使你这样做了也不会世界末日。比如,你仍然可以用Cherry-pick在历史记录中来移动Commit来处理那些在旧历史记录中的Pull请求。
请记住,在开源项目中重写历史记录前先联系版本库的管理者。有的管理者一般情况下不允许任何重写历史,并且会拉黑那些这么做的人,而另外一些管理者倾向于他们自己来做重写。
情形1:删除最后一次Commit
删除最后一次Commit是最简单的一种情况。例如,我们现在有一个拥有master分支的远程仓库mathnet,它现在处于最新的Commitdd61ab32下。我们希望移除这个最新的Commit,或者用Git语言说,我们想force远程仓库mathnet的master分支到dd61ab32的父Commit上。
$ git push mathnet +dd61ab32^:master
在Git命令中,x^代表x的父节点,+代表一个强制的非快速推送(forced
non-fastforward push)。如果你在本地已经处于master分支下了,你也可以通过两个简单的步骤来实现同样的效果:先回退到父Commit,然后强制推送给远程仓库。
$ git reset HEAD^ --hard
$ git push mathnet -f
情形2:删除倒数第二个Commit
现在我们假设需要删除的Commit没有在历史记录的顶部,而是一个稍旧一点的Commit,比如倒数第二个。我们希望删除它同时保留其后的所有Commit,换句话说我们希望重写历史记录然后将重写强制应用到mathnet的master分支上。重写历史的最简单的方法是对错误的Commit做一个互相的变基:
$ git rebase -i dd61ab32^
这个命令会打开一个vi编辑窗口,显示了从我们想删除的Commit以来的所有Commit。
pick dd61ab32
pick dsadhj278
简单地删除我们想删除的Commit信息,在这里我们删除第一行即可(在vi中删除当前行的命令为dd)。保存退出编辑器(在vi中输入:wq然后按回车键),然后解决一下有可能的冲突,然后强制推送到远程仓库就大功告成了:
$ git push mathnet -f
情形3:修复一个Commit中的拼写错误
这种情形下的操作与情形2十分相似,但不是删除Commit信息,而是将pick和edit换一下位置然后保存退出即可。然后变基时,操作将会停在那个Commit上,这时你可以对这个索引做任何你想做的操作。完成后Commit改动然后继续变基(如果你想的话Git会告诉你如何保持Commit的附加信息),然后继续按情形2进行推送。用同样的方法可以将一个Commit分成很多小的Commit,或者将很多Commit合并到一起。
关于“Git新手教程-撤销更改(七)”这个话题的介绍,今天小编就给大家分享完了,如果对你有所帮助请保持对本站的关注!
本文来自作者[青容]投稿,不代表博羽号立场,如若转载,请注明出处:https://sz-boyu.cn/sz/5253.html
评论列表(4条)
我是博羽号的签约作者“青容”!
希望本篇文章《Git新手教程-撤销更改(七)》能对你有所帮助!
本站[博羽号]内容主要涵盖:生活百科,小常识,生活小窍门,知识分享
本文概览:网上有关“Git新手教程-撤销更改(七)”话题很是火热,小编也是针对Git新手教程-撤销更改(七)寻找了一些与之相关的一些信息进行分析,如果能碰巧解决你现在面临的问题,希望能够...