撤消 Git 中的更改 - git checkout、stash、reset、clean、revert、rebase -i、amend 的备忘单目录

2025-05-25

撤消 Git 中的更改 - git checkout、stash、reset、clean、revert、rebase -i、amend 的备忘单

目录

原帖发布于michaelzanggl.com。订阅我的新闻通讯,不错过任何新内容。

Git 是那种需要循序渐进学习的东西。你从git add .暂存文件开始,git commit -m “message”在本地提交,最终git push推送到远程仓库。
但随着时间的推移,你会犯错。如果你总是在 Google 上搜索,然后随意粘贴命令,你可能会很容易被大量的命令搞晕,比如、 、 、 、git reset等等git revertgit cleangit checkout .我们一一了解一下!git rebase -igit commit --amend

目录

理解关键术语

您总是可以在这里找到更多帮助,但了解一些关键术语很重要。

  • 索引:使用索引暂存文件时,git add会将文件添加到索引文件中。因此,暂存与索引相同。

  • 未跟踪:如果您创建一个新文件,它将不会被跟踪,直到您将其暂存为止。

  • HEAD:HEAD 指向当前分支的最新提交。这就是为什么有时detached HEAD在检出旧提交时会看到一个奇怪的选择。

  • 点号 ingit add .表示当前目录。因此,当前目录及其所有子目录中的所有文件都将被暂存。我们将学习更多使用点号的命令。

不要撤消:保存更改以供日后使用

git stash -u

这将保存每个未跟踪的文件(-u 标志)、暂存和未暂存的修改。

要再次检索最新的存储,请运行

git stash apply
Enter fullscreen mode Exit fullscreen mode

为了保持存储列表整洁,您也可以git stash pop改为执行。它会执行与应用相同的操作,但还会从存储列表中删除已应用的存储。

用于git stash list检索所有储藏物的列表。

用例:您正在处理某件事,但突然需要更改分支(例如,为突然出现的紧急错误创建修补程序)

奖励:要知道哪个储藏属于什么,您可以通过运行以下命令为您的储藏添加注释:git stash push -u -m "your message"

不要撤消:在最新提交中添加内容或更改消息

git commit --amend -m "added file and changed message to this"

amend允许您向最新提交添加更多文件。

用例:您忘记暂存本应作为提交一部分的某个文件。

奖励:即使没有添加文件,您仍然可以使用“修改”选项来简单地更改消息。

如果其他人正在你的分支上工作:请注意不要在最新提交已经发布(推送)的情况下进行修改。否则需要git push --force

取消暂存文件(预提交)

git reset .

也常常被视为git reset

例子:

echo "code code code" >> index.js
git add .
git reset .
Enter fullscreen mode Exit fullscreen mode

它只会取消暂存index.js并将更改放回你的工作树中。你可以应用该--hard标志来彻底删除你的更改。

用例:出于习惯,您使用暂存所有修改git add .,但想要取消暂存某些文件以单独提交它们。

额外提示:要取消暂存特定文件,你可以使用与git add

git add User.js UserController.js UserService.js
git reset UserService.js User.js
Enter fullscreen mode Exit fullscreen mode

这种情况一直在UserController.js上演。

恢复更改(预提交)

git checkout .

git checkout用于更改分支,但如果您检出文件路径,它就会有不同的用途。

如果您在本地更改了任何文件,这将使用索引或提交中的内容还原您的更改。稍后会详细介绍。

例子:

echo -n "1" >> newfile
git add .
git commit -m "added newfile"

echo -n "2" >> newfile
Enter fullscreen mode Exit fullscreen mode

因此,我们创建了一个新文件,暂存并提交了它,然后将文本“2”附加到该文件。

如果你现在运行git checkout newfile它,它将删除所有本地更改,在本例中为“2”。你的工作树将再次变得干净。

让我们看看当你开始在中间进行暂存时会发生什么。这将为你提供新的视角git add,使命令比以往任何时候都更加强大。

echo -n "1" >> newfile
git add .
git commit -m "added newfile"

echo -n "2" >> newfile
git add .

echo -n "3" >> newfile
Enter fullscreen mode Exit fullscreen mode

这是不同状态下的文件内容

  • 头:“1”
  • 索引:“12”
  • 工作树:“123”

如果您现在运行,git checkout newfile它只会删除3您本地更改的内容。换句话说,如果它在索引中找到该文件,它会根据索引中的内容(而不是 HEAD 中的内容)还原更改。它仍然会newfile暂存内容“12”。

要删除“2”,您必须先按照我们所了解的方式取消暂存文件,然后再次检查它。

git reset
git checkout .
Enter fullscreen mode Exit fullscreen mode

因为它只用索引/HEAD 中的文件替换文件,所以git checkout不会对未跟踪的文件执行任何操作。

用例:您对文件 A 进行了修改,当修改文件 B 时,您意识到文件 A 中的更改实际上是不必要的,最好再次检查一下。

奖励:如果您想要检出的文件不幸与分支同名,则必须像这样检出git checkout -- master以避免检出主分支。

删除新的/未跟踪的文件和目录

git clean -f

类似于,git checkout .不同之处在于它仅适用于未跟踪的文件。您可以运行git clean --dry-rungit clean -n查看哪些文件将被永久删除。添加-d标志以包含目录。

touch newfile
git clean -d -n
Enter fullscreen mode Exit fullscreen mode

输出将是Would remove newfile

奖励:用于git clean -i启动交互式清理,为您提供更多关于如何处理每个文件的选项。

在新的提交中恢复提交

git 恢复commit-id

恢复提交 ID 的更改并为其创建一个新的提交。

用例:已推送的提交导致错误并且必须恢复。

额外提示:使用-e--edit标志可以修改提交信息。例如,你可以添加此提交必须被撤销的原因。

删除没有新提交的最新提交

git 重置 HEAD^

假设你意外提交了某个提交,现在想要撤消该提交。它git reset HEAD^会将最新的提交还原为从未发生过,并将修改放回到你的本地工作树中。它不会创建新的提交,最新的提交也会从历史记录中消失。

我们git reset之前已经了解过如何取消暂存文件。但是,当你传递提交时,你实际上可以将 HEAD 重置为你想要的任何提交。假设你有提交 A、B 和 C。如果git reset AA 成为最新的提交,那么git log你将找不到 B 和 C。

我们之前说过,这git reset HEAD^会将更改保留在工作树中。换句话说,git reset HEAD^这会重置 HEAD 和索引。

使用--soft标志仅重置 HEAD,这意味着更改将保留staged
使用--hard标志重置 HEAD、索引和工作树,这意味着更改将被完全删除。

您也git reset HEAD^可以写git reset HEAD^1,git reset HEAD~1git reset HEAD~

如果其他人正在你的分支上工作:请注意,如果你重置的提交已经发布,不要将 HEAD 重置为之前的提交。这需要git push --force

用例:您在本地提交了修改,但意识到您提交到了错误的分支。

奖励:除了最新的提交之外,总共有四种方法可以重置。

这四行代码重置了最后两次提交

git reset HEAD^2
git reset HEAD^^

git reset HEAD~2
git reset HEAD~~
Enter fullscreen mode Exit fullscreen mode

额外福利2git reset它实际上不会删除最新的提交,只是将 HEAD 回滚到你想要的提交。B 和 C 仍然会保存 30 天。

变更历史记录

让我们快速了解一下交互式变基。我们之前学习过git reset HEAD~1 --hard它是一种移除最新提交的方法。交互式变基也能实现同样的效果,只是它的功能更强大。rebase这次它实际上改变了提交对象,而不仅仅是将 HEAD 指向特定的提交。

git rebase -i HEAD~4
Enter fullscreen mode Exit fullscreen mode

我们看到的内容HEAD~4git reset之前相同。4 指的是您要重新设定的提交次数。

这将打开一个编辑器(vim?),其中包含以下内容

pick 123a44b0 your latest commit
pick C23a44b0 commit 3
pick B23a44b0 commit 2
pick A23a44b0 commit 1

# Rebase ...
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
Enter fullscreen mode Exit fullscreen mode

让我们替换

pick 123a44b0 your latest commit
pick C23a44b0 commit 3
pick B23a44b0 commit 2
pick A23a44b0 commit 1
Enter fullscreen mode Exit fullscreen mode

经过

pick 123a44b0 your latest commit
fixup C23a44b0 commit 3
f B23a44b0 commit 2
drop A23a44b0 commit 1
Enter fullscreen mode Exit fullscreen mode

如您所见,在这种情况下,您可以写出选项fixup,也可以使用缩写f

C23a44b0这会将和压缩(合并)B23a44b0123a44b0,从而生成一个提交。至于A23a44b0,此提交将被完全删除。因此,一旦 rebase 完成,您将只剩下一个提交123a44b0

如果其他人正在你的分支上工作:请注意,当你想 rebase 的提交已经发布时,不要 rebase。这需要git push --force

用例:您正在自己的分支上独自工作,并希望拥有 PR/MR 的干净提交列表。

奖励:您甚至可以通过更改提交在列表中出现的顺序来移动提交。

删除本地分支

git checkout master

git branch -D branch-to-delete

用例:有时,删除本地分支并再次检查会更快,而不是恢复一堆提交。

删除远程分支

git push origin branch-to-delete --delete

用例:推送后,您意识到所选的名称没有意义,并且想要更改它(奖励:使用 执行此操作git branch -m "new-name"


结论

Git 确实很难掌握,我相信肯定还有其他方法可以完成其中一些任务。如果您知道任何方法,请留言,我会将它们添加到列表中。

如果这篇文章对您有帮助,我这里还有更多关于简化编写软件的提示

文章来源:https://dev.to/michi/undo-changes-in-git-cheat-sheet-for-git-checkout-stash-reset-clean-revert-rebase-i-amend-2h1h
PREV
7 个 DevOps 误区 – 破除误区 1:DevOps 就是 CI/CD 误区 2:DevOps 意味着 NoOps 误区 3:自动化消除所有瓶颈 误区 4:一刀切的持续交付管道 误区 5:DevOps 就是工具 误区 6:软件发布与 Amazon/Facebook/Google 相同 误区 7:始终发布 总结
NEXT
布尔变量命名技巧 - 更简洁的代码