使用 git 修复错误
有时,我们都会编写一些不应该成为代码库一部分的代码。或者至少现在还不应该。Git 提供了多种方法可以移除此类代码,了解何时使用每种方法可以让你成为更高效的 Git 用户。那么,让我们来看看根据代码中意外发生的情况,你应该采取哪些措施。
我只在命令行上使用 git,所以我会用命令行来展示所有内容。Git 的 GUI 可能会以不同的方式显示部分信息,但我相信术语通常不会改变,所以命令应该很容易找到。
我还没有提交
如果您尚未提交代码,git status
这是一个很有用的命令。它会显示所有尚未提交的更改列表,并会告诉您如何忽略某些未提交的更改。输出包含以下部分:
On branch feature-user-account
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
...
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
如果您要忽略的更改位于第一部分,建议的命令git reset HEAD
会将它们带入第二组。对于第二组中的更改,建议的命令git checkout --
(--
很重要)将从给定文件中删除所有更改。因此,在运行该命令之前,请确保这些文件中的所有更改都是您想要删除的。
我承诺了,但没有推动
如果您尚未推送更改,它们目前仅存在于您的本地计算机上。因此,您可以随意进行任何更改。Git 有一个命令git reset
,它的形式我们上面已经见过,可以将当前分支重置为其他状态。如果您只想回到提交之前的状态,请运行 ,git reset HEAD^
它将当前分支设置为最近一次提交之前的状态(这就是^
after 的HEAD
含义;您可以输入多个^
' 来返回多个提交),并将更改保持在未提交状态。
如果你真的想删除最新的提交,git reset
有一种方法可以做到。如果你运行,git reset --hard HEAD^
最新的提交将被删除,就像它从未发生过一样。提交中包含的所有代码都将被删除,所以只有当你确定整个提交都是错误时才这样做。(你可以用任何命令代替 来HEAD^
重置分支;我有时会用它来将我的本地分支重置为远程服务器上的分支,因为我想删除我在该分支上本地执行的所有操作。)
我提交并推送到我自己的分支
在基于功能分支的软件开发流程中,开发人员通常会拥有自己的“分支”来开发他们正在实现的功能。如果没有其他人在某个分支上工作,您可以将该分支的远程版本视为与本地分支几乎相同的版本。因此,只需执行git reset
上述操作,然后执行git push --force
(称为强制推送)即可使远程版本与本地重置的分支版本匹配。
仓库管理员可以配置远程仓库以拒绝强制推送。如果您遇到这种情况,请遵循下一个标题下的建议。
我提交并推送到共享分支
在多人协作的分支上重置并强制推送的问题在于,其他人可能已经拉取了不该发生的提交,并在此基础上构建了一些工作。在这种情况下,对强制推送的响应可能会变得棘手。
幸运的是,git 也提供了无需更改历史记录即可撤销更改的方法。要删除最新提交中的更改,请运行 。git revert HEAD
这将创建一个与上次提交完全相反的新提交HEAD
,从而撤消上次提交中的所有更改。
正如您所料,您可以将任何提交标识符git revert
替换为HEAD
,它会执行您所期望的操作,即创建一个仅撤消您指定的提交的提交。这是使用 无法实现的git reset
,因此即使您的工作流程通常不包括使用 ,记住它也是一个有用的工具git revert
。
我提交并推送了一次不应该发生的合并
假设你正在使用功能分支模型,因此你正在处理的任何功能都需要从你的分支合并到主开发分支。你或其他人在分支尚未准备好合并之前就意外地合并了该分支,因此你需要撤消合并。
同样,git revert
它可以用来撤消合并提交。但有一个问题:合并提交有多个父提交(通常是两个)。git 应该撤消哪些更改?用于撤消合并提交的命令是,git revert -m 1 <commit>
选项-m 1
指示选择父提交 1 作为要撤消的父提交。
注意,父提交编号不是提交标识符。相反,合并提交有一行
Merge: 8e2ce2d 86ac2e7
当您使用git log
或查看它时git show
。父编号是此行中所需父级的从 1 开始的索引,也就是说,第一个标识符是编号 1,第二个是编号 2,依此类推。编号 1 是合并到的分支,因此在功能分支工作流中,撤消合并意味着-m 1
选择git revert
。
我提交并推送了一些不应该存在于存储库中的内容
有时,你会在工作树中保留一些不该提交的内容。请.gitignore
为你的项目设置一个合适的文件,以避免意外提交此类内容。但有时,你可能会遇到一些你没有发现的新内容,.gitignore
最终不小心提交并推送了它们。这些内容可能是应该保密的凭证,也可能是使用仓库时遇到的大量二进制文件,也可能是其他什么东西。
这里的做法是,当你提交并推送到你自己的分支时,遵循建议,也就是git reset
。git push --force
但如果你在共享分支上执行了此操作,请记住告知你的团队发生了这种情况,以便他们可以调整到在共享分支上强制推送。
最后,如果您不小心将私钥、凭证、密码等信息推送到公共存储库,请将其视为已泄露。立即撤销所有凭证、更改所有密码等。
我想要回我的代码
如果您所做的更改还为时过早,并且您确实希望稍后再进行更改,则可以根据您摆脱更改的方式,采用以下方法恢复更改:
git checkout --
:如果您这样做了,您的更改就消失了。Git 从未见过它们,所以它无法帮助您恢复它们。git reset HEAD
,git reset
:更改仍保留在您的工作树中,只是状态有所不同。如果您记得将它们保存在某个地方,请从那里获取它们。git reset --hard
:更改已消失,但 git 已经看到它们,并且可能记住了它们。请仔细查看git reflog
(这个话题太大,无法在此详述,而且我也无法提供很好的建议)。git revert
:另一种方法是git revert
,这次提供为原始还原创建的提交的标识符。这会给你一些有趣的提交信息“还原为“还原为...””,但这是最简洁的方法。如果你要撤消功能分支的过早合并,请记住在合并功能分支的正确版本之前执行此操作。否则,git 会搞不清楚哪些来自功能分支的更改已经存在于主开发分支上。