Git里多种撤销操作的最佳方法

更新时间:2023-05-16 20:08:53 阅读: 评论:0

Git⾥多种撤销操作的最佳⽅法
前⾔
相信⼤家都知道任何版本控制系统的⼀个最有的⽤特性就是“撤销 (undo)”你的错误操作的能⼒。在 Git ⾥,“撤销” 蕴含了不少略有差别的功能。当你进⾏⼀次新的提交的时候,Git 会保存你代码库在那个特定时间点的快照;之后,你可以利⽤ Git 返回到你的项⽬的⼀个早期版本。
撤销⼀个“已公开”的改变
场景: 你已经执⾏了git push, 把你的修改发送到了 GitHub,现在你意识到这些 commit 的其中⼀个是有问题的,你需要撤销那⼀个 commit.
⽅法: git revert <SHA>
原理: git revert 会产⽣⼀个新的 commit,它和指定 SHA 对应的 commit 是相反的(或者说是反转的)。如果原先的 commit
intelligence是“物质”,新的 commit 就是“反物质” — 任何从原先的 commit ⾥删除的内容会在新的 commit ⾥被加回去,任何在原先的commit ⾥加⼊的内容会在新的 commit  ⾥被删除。
这是 Git 最安全、最基本的撤销场景,因为它并不会改变历史 — 所以你现在可以  git push 新的“反转” commit 来抵消你错误提交的 commit。
修正最后⼀个 commit 消息
场景: 你在最后⼀条 commit 消息⾥有个笔误,已经执⾏了 git commit -m "Fxies bug #42",但在 git push 之前你意识到消息应该是 “Fixes bug #42″。
⽅法: git commit --amend 或 git commit --amend -m "Fixes bug #42"
原理: git commit --amend会⽤⼀个新的 commit 更新并替换最近的 commit ,这个新的 commit 会把任何修改内容和上⼀个commit 的内容结合起来。如果当前没有提出任何修改,这个操作就只会把上次的 commit 消息重写⼀遍。
撤销“本地的”修改
场景: ⼀只猫从键盘上⾛过,⽆意中保存了修改,然后破坏了编辑器。不过,你还没有 commit 这些修改。你想要恢复被修改⽂件⾥的所有内容 — 就像上次 commit 的时候⼀模⼀样。
⽅法: git checkout -- <bad filename>
原理: git checkout 会把⼯作⽬录⾥的⽂件修改到 Git 之前记录的某个状态。你可以提供⼀个你想返回的分⽀名或特定 SHA ,或者在缺省情况下,Git 会认为你希望 checkout 的是 HEAD,当前 checkout 分⽀的最后⼀次 commit。2013英语二真题
记住:你⽤这种⽅法“撤销”的任何修改真的会完全消失。因为它们从来没有被提交过,所以之后 Git 也⽆法帮助我们恢复它们。你要确保⾃⼰了解你在这个操作⾥扔掉的东西是什么!(也许可以先利⽤ git diff 确认⼀下)
重置“本地的”修改
场景: 你在本地提交了⼀些东西(还没有 push),但是所有这些东西都很糟糕,你希望撤销前⾯的三次提交 — 就像它们从来没有发⽣过⼀样。
⽅法: git ret <last good SHA>或git ret --hard <last good SHA>
原理: git ret会把你的代码库历史返回到指定的 SHA 状态。这样就像是这些提交从来没有发⽣过。缺省情况下, git ret 会保留⼯作⽬录。这样,提交是没有了,但是修改内容还在磁盘上。这是⼀种安全的选择,但通常我们会希望⼀步就“撤销”提交以及修改内容 — 这就是 --hard 选项的功能。
在撤销“本地修改”之后再恢复
场景: 你提交了⼏个 commit,然后⽤ git ret --hard 撤销了这些修改(见上⼀段),接着你⼜意识到:你希望还原这些修改!
⽅法: git reflog 和 git ret 或git checkout
原理: git reflog对于恢复项⽬历史是⼀个超棒的资源。你可以恢复⼏乎任何东西 — 任何你 commit 过的东西 — 只要通过reflog。
你可能已经熟悉了 git log 命令,它会显⽰ commit 的列表。 git reflog 也是类似的,不过它显⽰的是⼀个 HEAD 发⽣改变的时间列表.
hge⼀些注意事项:
它涉及的只是 HEAD 的改变。在你切换分⽀、⽤ git commit 进⾏提交、以及⽤ git ret 撤销 commit 时,HEAD 会改变,但当你⽤git checkout -- <bad filename> 撤销时(正如我们在前⾯讲到的情况),HEAD 并不会改变 — 如前所述,这些修改从来没有被提交过,因此 reflog 也⽆法帮助我们恢复它们。
git reflog不会永远保持。Git 会定期清理那些 “⽤不到的” 对象。不要指望⼏个⽉前的提交还⼀直躺在那⾥。
你的 reflog 就是你的,只是你的。你不能⽤git reflog 来恢复另⼀个开发者没有 push 过的 commit。
reflogjapaneschoolchild21
那么…你怎么利⽤ reflog 来“恢复”之前“撤销”的 commit 呢?
它取决于你想做到的到底是什么:
如果你希望准确地恢复项⽬的历史到某个时间点,⽤ git ret --hard <SHA>
如果你希望重建⼯作⽬录⾥的⼀个或多个⽂件,让它们恢复到某个时间点的状态,⽤ git checkout <SHA> -- <filename>如果你希望把这些 commit ⾥的某⼀个重新提交到你的代码库⾥,⽤ git cherry-pick <SHA>
利⽤分⽀的另⼀种做法
场景: 你进⾏了⼀些提交,然后意识到你开始 check out 的是 master 分⽀。你希望这些提交进到另⼀个特性(feature)分⽀⾥。
⽅法: git branch feature, git ret --hard origin/master, and git checkout feature
原理: 你可能习惯了⽤git checkout -b <name>创建新的分⽀ — 这是创建新分⽀并马上 check out 的流⾏捷径 — 但是你不希望马上切换分⽀。这⾥, git branch feature 创建⼀个叫做 feature 的新分⽀并指向你最近的 commit,但还是让你 check out 在 master 分⽀上。
下⼀步,在提交任何新的 commit 之前,⽤ git ret --hard 把 master 分⽀倒回 origin/master 。不过别担⼼,那些 commit 还在feature 分⽀⾥。
最后,⽤git checkout切换到新的 feature 分⽀,并且让你最近所有的⼯作成果都完好⽆损。
及时分⽀,省去繁琐
场景: 你在 master 分⽀的基础上创建了 feature 分⽀,但 master 分⽀已经滞后于 origin/master 很多。现在 master 分⽀已经和origin/master 同步,你希望在 feature 上的提交是从现在开始,⽽不是也从滞后很多的地⽅开始。
米饭的英语⽅法: git checkout feature 和git reba master
原理: 要达到这个效果,你本来可以通过 git ret (不加 --hard, 这样可以在磁盘上保留修改) 和 git checkout -b <new branch name> 然后再重新提交修改,不过这样做的话,你就会失去提交历史。我们有更好的办法。
git reba master会做如下的事情:
⾸先它会找到你当前 check out 的分⽀和 master 分⽀的共同祖先。
然后它 ret 当前  check out 的分⽀到那个共同祖先,在⼀个临时保存区存放所有之前的提交。
然后它把当前 check out 的分⽀提到 master 的末尾部分,并从临时保存区重新把存放的 commit 提交到 master 分⽀的最后⼀个 commit 之后。
peavey
⼤量的撤销/恢复
场景: 你向某个⽅向开始实现⼀个特性,但是半路你意识到另⼀个⽅案更好。你已经进⾏了⼗⼏次提交,但你现在只需要其中的⼀部分。你希望其他不需要的提交统统消失。
curriculum⽅法: git reba -i <earlier SHA>
原理: -i 参数让 reba 进⼊“交互模式”。它开始类似于前⾯讨论的 reba,但在重新进⾏任何提交之前,它会暂停下来并允许你详细地修改每个提交。
reba -i 会打开你的缺省⽂本编辑器,⾥⾯列出候选的提交。如下所⽰:
前⾯两列是键:第⼀个是选定的命令,对应第⼆列⾥的 SHA 确定的 commit。缺省情况下, reba -i  假定每个 commit 都要通过  pick 命令被运⽤。
要丢弃⼀个 commit,只要在编辑器⾥删除那⼀⾏就⾏了。如果你不再需要项⽬⾥的那⼏个错误的提交,你可以删除上例中的1、3、4⾏。
如果你需要保留 commit 的内容,⽽是对 commit 消息进⾏编辑,你可以使⽤ reword 命令。把第⼀列⾥的 pick 替换为 reword (或者直接⽤ r)。有⼈会觉得在这⾥直接重写 commit 消息就⾏了,但是这样不管⽤ —reba -i 会忽略 SHA 列前⾯的任何东西。它后⾯的⽂本只是⽤来帮助我们记住 0835fe2 是⼲啥的。当你完成 reba -i 的操作之后,你会被提⽰输⼊需要编写的任何 commit 消息。
如果你需要把两个 commit 合并到⼀起,你可以使⽤ squash 或 fixup 命令,如下所⽰:
squash 和 fixup 会“向上”合并 — 带有这两个命令的 commit 会被合并到它的前⼀个 commit ⾥。在这个例⼦⾥, 0835fe2 和6943e85 会被合并成⼀个 commit, 38f5e4e 和 af67f82 会被合并成另⼀个。
如果你选择了 squash, Git 会提⽰我们给新合并的 commit ⼀个新的 commit 消息; fixup 则会把合并清单⾥第⼀个 commit 的消息直接给新合并的 commit 。这⾥,你知道 af67f82 是⼀个“完了完了….” 的 commit,所以你会留着 38f5e4e as的 commit 消息,但你会给合并了 0835fe2 和 6943e85 的新 commit 编写⼀个新的消息。
在你保存并退出编辑器的时候,Git 会按从顶部到底部的顺序运⽤你的 commit。你可以通过在保存前修改 commit 顺序来改变运⽤的顺序。如果你愿意,你也可以通过如下安排把 af67f82 和 0835fe2 合并到⼀起:
修复更早期的 commit
场景: 你在⼀个更早期的 commit ⾥忘记了加⼊⼀个⽂件,如果更早的 commit 能包含这个忘记的⽂件就太棒了。你还没有push,但这个 commit 不是最近的,所以你没法⽤ commit --amend.
⽅法: git commit --squash <SHA of the earlier commit>和git reba --autosquash -i <even earlier SHA>
原理: git commit --squash 会创建⼀个新的 commit ,它带有⼀个 commit 消息,类似于 squash! Earlier commit。 (你也可以⼿⼯创建⼀个带有类似 commit 消息的 commit,但是 commit --squash 可以帮你省下输⼊的⼯作。)
billionaire如果你不想被提⽰为新合并的 commit 输⼊⼀条新的 commit 消息,你也可以利⽤ git commit --fixup 。在这个情况下,你很可能会⽤commit --fixup ,因为你只是希望在 reba 的时候使⽤早期 commit 的 commit 消息。
口译reba --autosquash -i  会激活⼀个交互式的 reba 编辑器,但是编辑器打开的时候,在 commit 清单⾥任何 squash! 和fixup! 的 commit 都已经配对到⽬标 commit 上了,如下所⽰:
在使⽤ --squash 和 --fixup 的时候,你可能不记得想要修正的 commit 的 SHA 了— 只记得它是前⾯第 1 个或第 5 个 commit。你会发现 Git 的 ^ 和 ~ 操作符特别好⽤。HEAD^ 是 HEAD 的前⼀个 commit。 HEAD~4 是 HEAD 往前第 4 个 – 或者⼀起算,倒数第 5 个 commit。
停⽌追踪⼀个⽂件
场景: 你偶然把 application.log 加到代码库⾥了,现在每次你运⾏应⽤,Git 都会报告在 application.log ⾥有未提交的修改。你把 *.login 放到了 .gitignore ⽂件⾥,可⽂件还是在代码库⾥ — 你怎么才能告诉 Git “撤销” 对这个⽂件的追踪呢?
⽅法: git rm --cached application.log
原理: 虽然 .gitignore 会阻⽌ Git 追踪⽂件的修改,甚⾄不关注⽂件是否存在,但这只是针对那些以前从来没有追踪过的⽂件。⼀旦有个⽂件被加⼊并提交了,Git 就会持续关注该⽂件的改变。类似地,如果你利⽤ git add -f 来强制或覆盖了 .gitignore,Git 还会持续追踪改变的情况。之后你就不必⽤-f  来添加这个⽂件了。
如果你希望从 Git 的追踪对象中删除那个本应忽略的⽂件, git rm --cached 会从追踪对象中删除它,但让⽂件在磁盘上保持原封不动。因为现在它已经被忽略了,你在  git status ⾥就不会再看见这个⽂件,也不会再偶然提交该⽂件的修改了。
总结扑灭英文
以上这就是如何在 Git ⾥撤销任何操作的⽅法,希望本⽂的内容对⼤家的学习或者⼯作能带来⼀定的帮助,如果有疑问⼤家可以留⾔交流。

本文发布于:2023-05-16 20:08:53,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/90/111053.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:提交   修改   撤销   恢复
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图