用 17 种方法纠正 Git 错误

2025-05-26

用 17 种方法纠正 Git 错误

错误!软件开发中并非必然存在错误。但它们总能找到办法玷污软件开发之美。

错误难免,我们不妨坦然接受。但如何从错误中恢复过来呢?

版本控制系统的一个实用功能就是撤销功能。Git
是一个绝佳的安全网,即使你犯了错,也能给你另一次机会。

摘要:在本文中,我概述了您可能遇到的错误场景以及可以帮助您摆脱错误的 Git 技术。

  1. 停止跟踪已跟踪的文件

    你有一个node_modules不想被 Git 跟踪的文件夹。
    你提交了node_modules该文件夹,现在才意识到忘记用.gitignore文件忽略它了。你添加了该文件,并在其中.gitignore列出了该文件夹,然后提交。 但 Git 仍然在跟踪它🤬。这是因为,一旦文件被添加并提交到 Git 数据库,Git 就会继续跟踪对该文件所做的更改。node_modules

    如果你想要停止 Git 跟踪该node_modules文件夹,

    只需运行:

    git rm -r  --cached node_modules
    

    --cached该选项还可以防止从磁盘中删除文件。

  2. 修改最后一次提交

    您已将文件提交到本地 Git 数据库。之后,您意识到忘记将文件更改添加到该提交(您可能尚未保存该文件)。或者,您添加了一个新文件,希望将其与最近提交的同一提交关联。

    Git 可以解锁之前的提交并允许你添加新文件。

    只需执行以下操作:

    首先,使用以下命令添加缺少的文件:

    git add newfile.ts
    

    然后运行:

    git commit --amend --no-edit
    

    --no-edit标志修改提交但不改变提交消息。

  3. 修改上次提交信息

    这个场景和上面的类似。但这次,你已经向 git 提交了,但你对指定的提交消息不太满意。你希望提交消息能够更清晰地描述你所做的事情。

    Git 再次宽容地让你修复之前糟糕的提交信息。

    只需运行:

    git commit --amend -m "Phew! A better commit message this time"
    
  4. 放弃工作目录中的所有更改

    您正在开发项目。例如,您可能正在重构代码,以遵循更好的模式和简洁的代码原则。在重构过程中,您破坏了应用程序中的某个功能,却无法弄清楚到底出了什么问题。现在,您想回到应用程序运行良好的先前状态(提交),以便重新找到方向。

    因此,您需要丢弃所有未提交的更改,并将 Git 工作树恢复到上次提交时的状态。

    使用以下命令:

    git restore .
    

    注意:此命令会将您的工作副本恢复到本地 git 数据库中的最新提交。您尚未提交的更改将永久丢失。

  5. 放弃对文件所做的所有更改

    您修改了本地 git 仓库中的文件。后来您意识到对某个文件(connect.js)所做的更改不够智能,应该丢弃。但您想保留对其他文件的更改。

    如果你想让文件connect.js回到上次提交的状态,

    Git 可以帮你实现:

    git restore connect.js
    
  6. 将文件恢复到旧版本

    与上述命令不同,在这种情况下,您希望项目中的特定文件返回到比上次提交更深的状态。

    例如,如果版本 3 是您之前的提交,您希望此特定文件看起来像是早于版本 3 的版本 2。

    使用 Git:

    查找并复制您想要的提交哈希值:

    git log
    

    然后:

    git restore --source <commit-hash> <filename>
    

    就这么简单,对吧?

  7. 恢复已删除的文件(先前提交的)

    您正在对项目进行新的更改,然后发现了一个过时的文件。您直接删除了该文件,释放了空间。过了一会儿,您意识到需要这个刚刚删除的文件。

    要恢复您的文件:

    git restore deleted-file.css
    

    这将向您显示上次提交的文件。

  8. 放弃本地仓库中的所有更改,以在远程仓库中保持精确状态

    你在本地仓库分支上做了一些修改和提交。你重新连接了代码,现在不禁自问:“我当初为什么要做这些修改?”

    所以,如果你想要删除当前本地分支上的所有内容,并使其与远程主分支完全相同,

    只需像这样撤消:

    git reset --hard origin/main
    

    警告:未提交的更改将永久丢失。

  9. 删除未跟踪的文件

    您在项目中创建了几个新文件,也修改了一些文件。您改变了方法,现在决定不再需要这些新创建的文件,而是保留修改后的文件。

    Git 为您提供了删除未跟踪文件的命令:

    git clean -f
    

    git clean命令需要一个-f暗示 force 指令的标志(也--force)。由于此操作需要删除未跟踪的文件,因此必须要求您确定自己在做什么,因为在 Git 中清除未提交的工作是不可撤销的

    默认情况下,此命令不会删除 指定的未跟踪文件夹或文件.gitignore。指定-x选项可删除忽略的文件。

    此外,git clean它也不会对目录进行递归操作。这是另一种防止意外永久删除的安全机制。

    要同时删除目录,请使用-d如下标志:

    git clean -df
    

    这将清除未跟踪的文件和目录,但不会删除.gitignore文件中列出的文件和目录。

  10. 切换提交到不同的分支

    项目已经发展起来,您目前正在处理两个功能:添加新闻稿和微调页脚布局。您已经创建了两个单独的分支:newsletterfooter-layout,每个分支分别专用于相关功能:新闻稿页脚布局

    您目前正在添加新闻稿功能并从newsletter分支进行一些提交。下次您回到项目时,您想要处理页脚布局功能,但忘记切换到相关footer-layout分支。您从错误的分支添加了页脚布局newsletter功能并提交给它。后来,您注意到

    添加分支的提交实际上属于newsletterfooter-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提交

  11. 恢复已删除的分支

    你觉得某个功能分支已经不再需要了,于是就把它扔到垃圾桶里(删除它)。下次再删除它时,你又惊恐万分,原来删除它是个错误。现在你陷入了“恐慌模式”。你渴望回到过去,把它找回来,尽管这是不可能的。

    如果你想找回已删除的分支,

    可以按照以下步骤操作:

    查找并复制已删除分支的提交哈希,该哈希将在您运行以下命令时列出:

    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>

    不用说,成功恢复已删除分支的关键是找到正确的提交哈希,因此请明智地命名您的提交;这会很有帮助。

  12. 回退/撤消错误提交

    您的团队刚刚发布了一个项目的新版本。大家都确信所有新增的功能都堪称大师级水准。然而片刻之后,团队负责人突然打来紧急电话,告知新版本存在一个严重缺陷,需要立即修复。工程团队需要立即采取行动,而坐下来查找缺陷显然无法及时解决紧急问题。

    最快的应对方法之一就是撤销对易出错版本的更改

    如果你想撤消对某个提交所做的更改。

    在 Git 中操作如下:

    查找并复制您想要撤消更改的提交的提交哈希(损坏的提交):

    git log
    

    恢复该提交指定的更改:

    git revert <broken-commit-hash>
    

    git revert创建一个包含已还原(反向)更改的新提交。所有在损坏的提交中指定的更改都将在新提交中回滚(撤消)。例如,在损坏的提交中删除的任何内容都将添加到新提交中,而在损坏的提交中添加的任何内容都将在新提交中被删除。将弹出一个默认编辑器,其中包含即将创建的“还原提交”的默认提交消息。您可以根据需要进行修改。

  13. 撤消 Git 合并

    你对分支中的新更改感到满意feature。你觉得可以将feature分支合并到你的分支中。于是,你main从你的分支合并分支,并将新的更改推送到远程仓库。mainfeature

    过了一会儿,你意识到合并实际上并不是一个漂亮的举动。

    如果你想撤消合并,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分支。

  14. 回滚到旧版本

    您可以将项目回滚到之前的某个版本。这也可以用于处理错误的提交:即您希望回到最近一次损坏的提交之前正常运行的版本

    警告:此处显示的 git 命令会重写历史记录。这不适用于与他人合作软件项目的情况。

    如果你想通过回退仓库的历史记录来恢复项目的先前版本,那么

    在 git 中:

    查找并复制您希望项目倒回的提交哈希:

    git log
    

    将您的存储库重置为提交哈希指定的状态

    git reset --hard <commit-hash>
    

    git resetHEAD将指针(以及你的工作树)移动到旧版本 ( <commit-hash> )。
    此版本之后的提交将从项目历史记录中删除

    --hard标志将重置暂存区和工作树。

    使用--mixed类似 的标志git reset --mixed <commit-hash>,会将您的代码库重置回指定的提交哈希值,并在您的工作树中保留文件。那些在后续提交中,但不在我们重置的提交中的文件,将保留为untracked文件。

    --mixed标志与 标志类似--soft,区别在于它们处理索引(暂存区)的方式。

    --mixed标志将重置暂存区域(索引),但不会重置工作树。因此,要在下一次提交中添加未跟踪文件,您必须git add执行git commit

    --soft标志既不会重置暂存区域,也不会重置工作树。因此,要在下一次提交中添加未跟踪文件,您只需执行git commit

  15. 修改旧的提交信息

    你对项目的进展感到满意。你正在浏览项目历史记录。你注意到一条提交信息非常模糊。

    所以你想把这条消息改成一条更符合逻辑语义的消息(也就是一条解释更清楚的消息)。

    在 Git 中,你可以使用交互式 rebase 命令,在更深的历史记录中编辑一条提交消息

    查找并复制要更改其提交消息的提交的提交哈希

    git log
    

    打开 rebase 交互式会话:

    git rebase -i <commit-hash>
    

    将会弹出一个编辑器。

    交互式变基会话

    从上面的交互式 rebase 会话示例中,您可以看到第 1 行有一个拼写错误:pick 21c21b6 udating。让我们修复这个拼写错误,并提供更好的描述性消息。

    在编辑器中,只需指定要执行的操作即可。您可能很想立即重写提交消息,但这样做行不通;rebase -i因为 SHA(提交哈希)列之后的所有内容都会被忽略。之后的文本实际上只是为了帮助您记住提交哈希的含义。

    由于您想要保留提交的内容但编辑提交消息,请reword针对您想要更改其消息的提交指定操作命令;只需将pick第一列中的单词替换为单词reword(或只是r,如下所示:

    重新表述 rebase 动作

    然后保存并关闭编辑器。

    最后,git 会打开一个编辑器供你修改提交信息。将提交信息改成更好的:

    更新旧提交信息

    最后,您可以保存并关闭编辑器。提交将使用新的提交消息进行更新。

  16. 删除旧提交

    旧的提交可能会困扰您,您希望将其从项目历史记录中删除。

    如果你希望此提交不再出现在项目历史记录中,

    你可以像这样删除此提交:

    首先,找到并复制失败的提交的提交哈希。

    git log
    

    然后:

    git rebase -i <commit-hash>
    

    指定drop删除提交的动作动词:

    删除提交

    保存并关闭编辑器。这个注定失败的提交就从项目历史记录中被移除了。

  17. 编辑旧提交以添加新更改

    您可能会遇到这样的情况:您想在项目中添加一项更改。但此更改与您处理特定更改时(该更改的提交信息更能描述该更改)的某个提交相关。

    例如,您的项目已经历了多次提交,并且假设最近的提交是项目的版本 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 rebase 交互式编辑操作

    保存并关闭编辑器。

    您的工作树和项目历史记录现在处于您之前进行此提交时的状态。运行后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
PREV
准备新环境时,我总会在 git 中设置 10 多个项目
NEXT
13 个让你肾上腺素飙升的 CSS 技巧