在Git中撤销多个操作的最佳方式
序
我相信每个人都知道,任何版本控制系统最有用的功能之一是能够“撤销”您的错误操作。在Git中,“撤销”包含许多稍微不同的功能。当您提交一个新的提交时,Git会在那个特定的时间点保存您的代码库的快照;之后,您可以使用Git返回到项目的早期版本。
撤消“公共”更改
场景:您已经执行了git push并将您的更改发送到GitHub。现在您意识到其中一个提交是错误的,您需要取消该提交。
方法: git恢复SHA
原则: git revert将生成一个新的提交,这与指定SHA对应的提交相反。如果原始提交是“物质的”,新提交是“反物质的”——从原始提交中删除的任何内容都将被重新添加到新提交中,而在原始提交中添加的任何内容都将在新提交中被删除。
这是Git最安全也是最基本的撤销场景,因为它不会改变历史记录——所以你现在可以使用Git来推送一个新的“反向”提交,以抵消你错误提交的提交。
修复最后一条提交消息
场景:您在最后一条提交消息中犯了笔误,并且已经执行了git commit-m ' fxis bug # 42 ',但是在git push之前,您意识到该消息应该是“Fixes bug #42”。
方法: gitcommit-amend或gitcommit-amend-m '修复bug # 42 '
principle : git commit-modify将用新的提交更新和替换最新的提交,并且这个新的提交将把任何修改与之前的提交结合起来。如果目前没有提出任何更改,此操作将只重写最后一条提交消息。
撤消“本地”修改
场景:一只猫走过键盘,不小心保存了修改,然后破坏了编辑器。但是,您还没有提交这些更改。您希望恢复修改后的文件中的所有内容,就像上次提交一样。
方法: git checkout-badfilename
原则: git签出会将工作目录中的文件修改到git之前记录的某个状态。您可以提供您想要返回的分支名称或特定SHA,或者默认情况下,Git会认为您想要签出的是HEAD,即当前签出分支的最后一次提交。
记住:你用这种方式“撤销”的任何改变都将彻底消失。由于从未提交过,Git以后无法帮助我们恢复它们。确保你知道你在这次行动中扔掉了什么!(也许你可以先用git diff确认一下)
重置“本地”修改
场景:你在本地提交了一些东西(还没有推送),但是所有这些东西都是不好的,你想取消之前的三次提交——好像从来没有发生过一样。
方法: git重置最后一个好SHA或git重置-硬最后一个好SHA
原则: git重置会将您的代码库历史返回到指定的SHA状态。就像这些提交从未发生过。默认情况下,git reset保留工作目录。这样,提交就没有了,但是修改仍然在磁盘上。这是一个安全的选择,但通常我们希望“撤销”提交,并在一个步骤中修改内容,也就是硬选项的功能。
撤消本地修改后恢复
场景:您提交了几个提交,然后使用git reset - hard撤销这些更改(参见上一段),然后您意识到您想要恢复这些更改!
方法: git reflog和git重置或git签出
Principle : git reflog是恢复项目历史的一个很好的资源。你几乎可以恢复任何东西——任何你承诺过的东西——只需要通过reflog。
您可能已经熟悉git log命令,它显示了提交列表。Git reflog类似,但它显示了HEAD更改的时间列表。
一些注意事项:
只涉及到HEAD的变化。当您切换分支、使用git commit提交和使用git reset取消提交时,HEAD会发生变化,但是当您使用git check-bad filename取消提交时(正如我们前面提到的),HEAD不会发生变化——正如前面提到的,这些变化从未提交过,因此reflog无法帮助我们恢复它们。
Git reflog不会被永久维护。Git定期清理“未使用”的对象。不要指望几个月前的投稿会一直躺在那里。
你的日志是你的,只是你的。您不能使用git reflog来恢复另一个开发人员尚未推送的承诺。参考日志
那么……如何使用reflog来“恢复”之前的“撤销”提交呢?
这取决于你想做什么:
如果您想准确地将项目历史还原到某个时间点,请使用git reset-hardsha
如果您想在工作目录中重建一个或多个文件,并将其恢复到某个时间点的状态,请使用git checkout SHA - filename
如果您想重新提交其中一个提交到您的代码库,使用git cherry-pick SHA
使用分支的另一种方法
场景:您提交了一些文档,然后意识到您开始签出的是主分支。您希望这些提交进入另一个功能分支。
方法: git分支功能、git重置-硬原点/主点和git结账功能
原则:您可能已经习惯了用git check out -b名称创建新分支-这是一种流行的创建新分支并立即签出的快捷方式-但是您不想立即切换分支。在这里,git分支功能创建了一个名为feature的新分支,并指向您最近的提交,但仍然允许您签出主分支。
接下来,在提交任何新的提交之前,使用git reset - hard将主分支倒回原点/主分支。但是不要担心,那些提交仍然在特性分支中。
最后,使用git checkout切换到新的特性分支,并保持您最近的所有工作完好无损。
及时分支,省去繁琐
场景:您基于主分支创建了特征分支,但是主分支远远落后于原点/主分支。现在主分支已经和origin/master同步了,希望功能上的提交从现在开始,而不是从落后很多的地方开始。
方法: git结账功能和git rebase master
Principle :要达到这种效果,可以使用git reset(不带- hard,这样就可以将更改保留在磁盘上)和git checkout -b新建分支名称然后重新提交更改,但是如果这样做,就会丢失提交历史记录。我们有更好的办法。
Git rebase master将执行以下操作:
首先,它会找到您当前检出分支和主分支的共同祖先。
然后,它将当前签出的分支重置为该公共祖先,并将所有以前的提交存储在临时存储区域中。
然后,它将当前检出分支引用到主分支的最后一部分,并在主分支的最后一次提交之后,从临时存储区域重新提交存储的提交。
大规模撤销/恢复
场景:你开始在某个方向实现一个功能,但是进行到一半的时候,你意识到另一个方案更好。你已经提交了十多次了,但是现在你只需要其中的一些。你希望所有其他不必要的提交消失。
方法: git rebase -i早期的SHA
原则: -i参数使rebase进入“交互模式”。它开始类似于前面讨论的rebase,但是它暂停并允许您在提交任何新的提交之前详细修改每个提交。
我将打开你的默认文本编辑器,它列出了候选提交。如下图所示:
前两列是键:第一列是选定的命令,对应于第二列中SHA确定的提交。默认情况下,rebase -i假设每个提交都将通过pick命令使用。
要放弃提交,只需在编辑器中删除该行。如果您不再需要项目中那些错误的提交,您可以删除上面示例中的第1、3和4行。
如果需要保留提交内容并编辑提交消息,可以使用return命令。将第一列中的pick替换为reword(或简单地使用r)。有些人认为直接在这里重写提交消息是可以的,但是它不起作用——rebase——我将忽略SHA列之前的任何内容。后面的文字只是用来帮助我们记住0835fe2是做什么的。当您完成rebase -i操作时,将提示您输入任何需要写入的提交消息。
如果需要合并两个提交,可以使用挤压或修复命令,如下所示:
挤压和修复将合并“向上”——带有这两个命令的提交将合并到它的前一个提交中。在本例中,0835fe2和6943e85将合并为一个提交,38f5e4e和af67f82将合并为另一个提交。
如果选择挤压,Git会提示我们给新合并的提交一个新的提交消息;Fixup会将合并列表中的第一条提交消息直接发送给新合并的提交。在这里,你知道af67f82是一个“完了……”commit,所以您将保留38f5e4e的commit消息为,但是您将为新的commit编写一个新的消息,该消息结合了0835fe2和6943e85。
当您保存并退出编辑器时,Git将从上到下应用您的提交。您可以通过在保存之前修改提交顺序来更改应用程序的顺序。如果您愿意,也可以通过以下方式将af67f82和0835fe2合并在一起:
修复早期提交
场景:您忘记在之前的提交中添加文件。如果早期提交能够包含这个被遗忘的文件,那就太好了。你还没有推送,但是这个提交不是最近的,所以你不能使用commit-modify。
方法: git提交-挤压早期提交的sha和git rebase-自动挤压-我甚至更早的sha
原则: git commit-puck将创建一个带有提交消息的新提交,类似于puck!较早提交.(您也可以手动创建带有提交消息的提交,但是commit-puck可以节省您的键入时间。)
如果您不想被提示为新合并的提交输入新的提交消息,您也可以使用git commit - fixup。在这种情况下,您可能会使用commit - fixup,因为您只想在重定基准时使用早期提交的提交消息。
我将激活一个交互式的Rebase编辑器,但是当编辑器打开时,提交列表中的任何挤压!还有修理!的提交已经与目标提交配对,如下所示:
当使用-挤压和-修复时,您可能不记得要修复的提交的SHA只记得它是之前的第一个或第五个提交。你会发现Git的and ~运算符特别有用。head是HEAD的前一次提交。HEAD~4是从HEAD向前的第四次,或者一起,第五次最后一次提交。
停止跟踪文件
场景:您不小心将application.log添加到了代码库中。现在,每次运行应用程序时,Git都会在应用程序日志中报告未提交的更改。登录。Gitignore文件,但是文件还在代码库中——怎么告诉git“撤销”对这个文件的跟踪?
方法: gistrm-cachedaapplication . log
原则:虽然。Gitignore将阻止git跟踪文件的修改,甚至不注意文件的存在,它只针对以前从未被跟踪过的文件。一旦文件被添加和提交,Git将关注文件的变化。同样,如果您使用Git add -f来强制或覆盖。gitignore,git将跟踪变化。那么您不必使用-f来添加这个文件。
如果您想从Git的跟踪对象中删除应该被忽略的文件,git rm - cached会将其从跟踪对象中删除,但将文件原封不动地保留在磁盘上。因为现在已经忽略了,所以在git状态下不会再看到这个文件,也不会再意外提交这个文件的修改。
摘要
以上就是如何在Git中撤销任何操作。希望本文的内容能给你的学习或工作带来一些帮助。有问题可以留言交流。
版权声明:在Git中撤销多个操作的最佳方式是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。