用 17 种方法纠正 Git 错误
错误!软件开发中并非必然存在错误。但它们总能找到办法玷污软件开发之美。
错误难免,我们不妨坦然接受。但如何从错误中恢复过来呢?
版本控制系统的一个实用功能就是撤销功能。Git
是一个绝佳的安全网,即使你犯了错,也能给你另一次机会。
摘要:在本文中,我概述了您可能遇到的错误场景以及可以帮助您摆脱错误的 Git 技术。
-
停止跟踪已跟踪的文件
你有一个
node_modules
不想被 Git 跟踪的文件夹。
你提交了node_modules
该文件夹,现在才意识到忘记用.gitignore
文件忽略它了。你添加了该文件,并在其中.gitignore
列出了该文件夹,然后提交。 但 Git 仍然在跟踪它🤬。这是因为,一旦文件被添加并提交到 Git 数据库,Git 就会继续跟踪对该文件所做的更改。node_modules
如果你想要停止 Git 跟踪该
node_modules
文件夹,
只需运行:git rm -r --cached node_modules
--cached
该选项还可以防止从磁盘中删除文件。 -
修改最后一次提交
您已将文件提交到本地 Git 数据库。之后,您意识到忘记将文件更改添加到该提交(您可能尚未保存该文件)。或者,您添加了一个新文件,希望将其与最近提交的同一提交关联。
Git 可以解锁之前的提交并允许你添加新文件。
只需执行以下操作:首先,使用以下命令添加缺少的文件:
git add newfile.ts
然后运行:
git commit --amend --no-edit
该
--no-edit
标志修改提交但不改变提交消息。 -
修改上次提交信息
这个场景和上面的类似。但这次,你已经向 git 提交了,但你对指定的提交消息不太满意。你希望提交消息能够更清晰地描述你所做的事情。
Git 再次宽容地让你修复之前糟糕的提交信息。
只需运行:git commit --amend -m "Phew! A better commit message this time"
-
放弃工作目录中的所有更改
您正在开发项目。例如,您可能正在重构代码,以遵循更好的模式和简洁的代码原则。在重构过程中,您破坏了应用程序中的某个功能,却无法弄清楚到底出了什么问题。现在,您想回到应用程序运行良好的先前状态(提交),以便重新找到方向。
因此,您需要丢弃所有未提交的更改,并将 Git 工作树恢复到上次提交时的状态。
使用以下命令:git restore .
注意:此命令会将您的工作副本恢复到本地 git 数据库中的最新提交。您尚未提交的更改将永久丢失。
-
放弃对文件所做的所有更改
您修改了本地 git 仓库中的文件。后来您意识到对某个文件(
connect.js
)所做的更改不够智能,应该丢弃。但您想保留对其他文件的更改。如果你想让文件
connect.js
回到上次提交的状态,
Git 可以帮你实现:git restore connect.js
-
将文件恢复到旧版本
与上述命令不同,在这种情况下,您希望项目中的特定文件返回到比上次提交更深的状态。
例如,如果版本 3 是您之前的提交,您希望此特定文件看起来像是早于版本 3 的版本 2。
使用 Git:
查找并复制您想要的提交哈希值:
git log
然后:
git restore --source <commit-hash> <filename>
就这么简单,对吧?
-
恢复已删除的文件(先前提交的)
您正在对项目进行新的更改,然后发现了一个过时的文件。您直接删除了该文件,释放了空间。过了一会儿,您意识到需要这个刚刚删除的文件。
要恢复您的文件:
git restore deleted-file.css
这将向您显示上次提交的文件。
-
放弃本地仓库中的所有更改,以在远程仓库中保持精确状态
你在本地仓库分支上做了一些修改和提交。你重新连接了代码,现在不禁自问:“我当初为什么要做这些修改?”
所以,如果你想要删除当前本地分支上的所有内容,并使其与远程主分支完全相同,
只需像这样撤消:git reset --hard origin/main
警告:未提交的更改将永久丢失。
-
删除未跟踪的文件
您在项目中创建了几个新文件,也修改了一些文件。您改变了方法,现在决定不再需要这些新创建的文件,而是保留修改后的文件。
Git 为您提供了删除未跟踪文件的命令:
git clean -f
该
git clean
命令需要一个-f
暗示 force 指令的标志(也--force
)。由于此操作需要删除未跟踪的文件,因此必须要求您确定自己在做什么,因为在 Git 中清除未提交的工作是不可撤销的。默认情况下,此命令不会删除 指定的未跟踪文件夹或文件
.gitignore
。指定-x
选项可删除忽略的文件。
此外,git clean
它也不会对目录进行递归操作。这是另一种防止意外永久删除的安全机制。
要同时删除目录,请使用-d
如下标志:git clean -df
这将清除未跟踪的文件和目录,但不会删除
.gitignore
文件中列出的文件和目录。 -
切换提交到不同的分支
项目已经发展起来,您目前正在处理两个功能:添加新闻稿和微调页脚布局。您已经创建了两个单独的分支:
newsletter
和footer-layout
,每个分支分别专用于相关功能:新闻稿和页脚布局。
您目前正在添加新闻稿功能并从newsletter
分支进行一些提交。下次您回到项目时,您想要处理页脚布局功能,但忘记切换到相关footer-layout
分支。您从错误的分支添加了页脚布局newsletter
功能并提交给它。后来,您注意到
添加到分支的提交实际上属于。newsletter
footer-branch
假设你想将添加页脚布局功能的提交从
newsletter
分支移动到其正确的footer-layout
分支。
在 Git 中可以这样做:检出
newsletter
分支:git checkout newsletter
查找并复制添加了footer-layout 功能的提交的哈希值。运行以下命令:
git log
检出你想要应用此提交的正确分支。在我们的例子中:
git checkout footer-layout
然后应用提交:
git cherry-pick <commit-hash>
然后签出
newsletter
分支:git checkout newsletter
并将其从这个不需要的提交中剥离出来,这是添加footer-layout的提交:
git reset HEAD~1 --hard
HEAD~1
意味着我们正在重置newsletter
分支,将一个提交移到最近的提交之后,并删除已移出的提交。记住,在我们的例子中,此分支上的最新提交是具有页脚布局功能的newsletter
提交。 -
恢复已删除的分支
你觉得某个功能分支已经不再需要了,于是就把它扔到垃圾桶里(删除它)。下次再删除它时,你又惊恐万分,原来删除它是个错误。现在你陷入了“恐慌模式”。你渴望回到过去,把它找回来,尽管这是不可能的。
如果你想找回已删除的分支,
可以按照以下步骤操作:查找并复制已删除分支的提交哈希,该哈希将在您运行以下命令时列出:
git reflog
然后重新创建你的分支:
git branch <branch-name> <deleted-branch-commit-hash>
这将重新创建一个分支,其中包含截至<deleted-branch-commit-hash> 的所有工作。如果<deleted-branch-commit-hash>不是已删除分支中的最新工作,您仍然可以找到新的提交哈希,直到找到包含最新工作的提交哈希为止。输入
git branch
,您将再次看到先前删除的分支被列出。即使分支在原点(远程)被删除,此方法也有效。
此外,如果<branch-name>不是您想要的名称,只需将其重命名为 即可git branch -m <branch-name> <new-branch-name>
。不用说,成功恢复已删除分支的关键是找到正确的提交哈希,因此请明智地命名您的提交;这会很有帮助。
-
回退/撤消错误提交
您的团队刚刚发布了一个项目的新版本。大家都确信所有新增的功能都堪称大师级水准。然而片刻之后,团队负责人突然打来紧急电话,告知新版本存在一个严重缺陷,需要立即修复。工程团队需要立即采取行动,而坐下来查找缺陷显然无法及时解决紧急问题。
最快的应对方法之一就是撤销对易出错版本的更改。如果你想撤消对某个提交所做的更改。
在 Git 中操作如下:查找并复制您想要撤消更改的提交的提交哈希(损坏的提交):
git log
恢复该提交指定的更改:
git revert <broken-commit-hash>
git revert
创建一个包含已还原(反向)更改的新提交。所有在损坏的提交中指定的更改都将在新提交中回滚(撤消)。例如,在损坏的提交中删除的任何内容都将添加到新提交中,而在损坏的提交中添加的任何内容都将在新提交中被删除。将弹出一个默认编辑器,其中包含即将创建的“还原提交”的默认提交消息。您可以根据需要进行修改。 -
撤消 Git 合并
你对分支中的新更改感到满意
feature
。你觉得可以将feature
分支合并到你的分支中。于是,你main
从你的分支合并分支,并将新的更改推送到远程仓库。main
feature
过了一会儿,你意识到合并实际上并不是一个漂亮的举动。
如果你想撤消合并,Git 可以帮你搞定。
首先检查
main
分支:git checkout main
然后运行
git log
以获取合并提交的提交哈希。git log
然后恢复如下:
git revert -m 1 <merge-commit-hash>
合并中的分支是该合并的父级。
通常,您无法还原合并,因为git不知道合并的哪一侧(父级)应该被视为主线。git revert -m 1
指定主线的父级编号,并允许使用还原操作来还原相对于指定父级的更改。通常,在合并过程中首先记录的父级
git merge
是您合并时所在的分支。在我们这个错误案例中,我们在某个分支feature
上签出时合并了该分支main
。因此,-m 1
指定了main
分支。 -
回滚到旧版本
您可以将项目回滚到之前的某个版本。这也可以用于处理错误的提交:即您希望回到最近一次损坏的提交之前正常运行的版本。
警告:此处显示的 git 命令会重写历史记录。这不适用于与他人合作软件项目的情况。
如果你想通过回退仓库的历史记录来恢复项目的先前版本,那么
在 git 中:查找并复制您希望项目倒回的提交哈希:
git log
将您的存储库重置为提交哈希指定的状态:
git reset --hard <commit-hash>
git reset
HEAD
将指针(以及你的工作树)移动到旧版本 ( <commit-hash> )。
此版本之后的提交将从项目历史记录中删除。该
--hard
标志将重置暂存区和工作树。使用
--mixed
类似 的标志git reset --mixed <commit-hash>
,会将您的代码库重置回指定的提交哈希值,并在您的工作树中保留文件。那些在后续提交中,但不在我们重置的提交中的文件,将保留为untracked
文件。
该--mixed
标志与 标志类似--soft
,区别在于它们处理索引(暂存区)的方式。该
--mixed
标志将重置暂存区域(索引),但不会重置工作树。因此,要在下一次提交中添加未跟踪文件,您必须git add
执行git commit
。
该--soft
标志既不会重置暂存区域,也不会重置工作树。因此,要在下一次提交中添加未跟踪文件,您只需执行git commit
。 -
修改旧的提交信息
你对项目的进展感到满意。你正在浏览项目历史记录。你注意到一条提交信息非常模糊。
所以你想把这条消息改成一条更符合逻辑语义的消息(也就是一条解释更清楚的消息)。
在 Git 中,你可以使用交互式 rebase 命令,在更深的历史记录中编辑一条提交消息:查找并复制要更改其提交消息的提交的提交哈希:
git log
打开 rebase 交互式会话:
git rebase -i <commit-hash>
将会弹出一个编辑器。
从上面的交互式 rebase 会话示例中,您可以看到第 1 行有一个拼写错误:
pick 21c21b6 udating
。让我们修复这个拼写错误,并提供更好的描述性消息。在编辑器中,只需指定要执行的操作即可。您可能很想立即重写提交消息,但这样做行不通;
rebase -i
因为 SHA(提交哈希)列之后的所有内容都会被忽略。之后的文本实际上只是为了帮助您记住提交哈希的含义。由于您想要保留提交的内容但编辑提交消息,请
reword
针对您想要更改其消息的提交指定操作命令;只需将pick
第一列中的单词替换为单词reword
(或只是r
),如下所示:然后保存并关闭编辑器。
最后,git 会打开一个编辑器供你修改提交信息。将提交信息改成更好的:最后,您可以保存并关闭编辑器。提交将使用新的提交消息进行更新。
-
删除旧提交
旧的提交可能会困扰您,您希望将其从项目历史记录中删除。
如果你希望此提交不再出现在项目历史记录中,
你可以像这样删除此提交:首先,找到并复制失败的提交的提交哈希。
git log
然后:
git rebase -i <commit-hash>
指定
drop
删除提交的动作动词:保存并关闭编辑器。这个注定失败的提交就从项目历史记录中被移除了。
-
编辑旧提交以添加新更改
您可能会遇到这样的情况:您想在项目中添加一项更改。但此更改与您处理特定更改时(该更改的提交信息更能描述该更改)的某个提交相关。
例如,您的项目已经历了多次提交,并且假设最近的提交是项目的版本 5。file.html
您创建了一个。您希望将此文件作为历史记录中更深层次的先前提交的一部分,例如项目的版本 2 。在 Git 中,你可以将新的更改合并到之前的提交中,从而编辑旧的提交。
具体步骤如下:查找并复制要标记为编辑的提交的提交哈希:
git log
启动 rebase 交互式会话:
git rebase -i "<commit-hash>^"
注意,我们在<commit-hash>
^
末尾添加了一个脱字符 ( ) 。这样,我们告诉 Git,在编辑完这个标记的提交后,我们希望回到原始的提交顺序。因为当你运行 时git rebase -i "<commit-hash>^"
,会将标记的<commit-hash>git log
显示为最近的提交。运行此命令后,会弹出一个默认编辑器。将动作动词修改
pick
为提及<commit-hash> 的edit
那一行,如下所示:保存并关闭编辑器。
您的工作树和项目历史记录现在处于您之前进行此提交时的状态。运行后
git log
,您将看到<commit-hash>现在是您的最新提交。您仍然file.html
在工作树中保留着之前创建的文件 ( ),这是一个将其修改为最新提交的好机会。请记住,此时,最新提交就是您要编辑的提交。
因此,请继续进行如下修改:git add file.html git commit --amend --no-edit
现在让项目历史恢复正常顺序:
git rebase --continue
这样,您就通过添加内容来编辑由<commit-hash>指定的提交。
file.html
警告:这将重写此后的历史记录。在团队环境中开展项目时,这不是一个好主意。
结论
这就是你扭转错误的方法。
仅需几点说明:
-
在团队环境中开展项目时,建议避免使用重写历史记录的命令。但是,您可以在本地仓库中专用的分支中重写历史记录。规则是,不要重写其他人基于其工作的分支的历史记录。否则情况可能会变得复杂。
-
您可能熟悉该
git log
命令,它显示提交列表。git reflog
类似,但显示更改时间的列表HEAD
。 -
您的引用日志仅供您个人使用。引用日志会跟踪自克隆存储库以来每个分支的所有更改或提交。
-
Git 默认 90 天内不会删除你的提交;你可以在引用日志中找到它们。因此,这是你犯错后的宽限期,让你有再次改正的机会。
感谢您的阅读✨。
如果您需要这样的信息,请在Twitter上找到我。
文章来源:https://dev.to/smitterhane/turn-around-your-git-mistakes-in-17-ways-2mn1