简介
Git 是一个强大的版本控制系统,可帮助开发人员有效地管理其代码库。但是,有时会发生错误,你可能需要撤销尚未推送到远程存储库的 Git 提交。本教程将指导你完成撤销未推送的 Git 提交的过程,并提供防止意外推送的提示。
理解 Git 提交
Git 是一个强大的版本控制系统,它允许开发人员随时间跟踪其代码库中的更改。Git 的核心是提交,它代表项目在特定时间点的快照。了解 Git 提交的工作原理对于有效管理项目历史记录和撤销不需要的更改至关重要。
什么是 Git 提交?
Git 提交是对项目文件所做更改的记录。当你对文件进行更改并想要保存这些更改时,你会创建一个新的提交。每个提交包含以下信息:
- 唯一标识符:每个提交都有一个唯一的哈希值作为其标识符,使 Git 能够跟踪和引用该提交。
- 作者:进行更改并创建提交的人。
- 时间戳:创建提交的日期和时间。
- 提交消息:对提交中所做更改的简要描述。
- 更改内容:对项目文件所做的具体修改。
Git 提交工作流程
典型的 Git 提交工作流程包括以下步骤:
- 进行更改:你修改项目中的一个或多个文件。
- 暂存更改:你将修改后的文件添加到暂存区,为下一次提交做准备。
- 创建提交:你创建一个新的提交,它捕获你所做的更改并已暂存的内容。
一旦创建了提交,它就成为项目历史记录的一部分,可以被引用、审查,甚至在必要时撤销。
graph LR
A[进行更改] --> B[暂存更改]
B --> C[创建提交]
C --> D[项目历史记录]
查看提交历史记录
你可以使用 git log 命令查看项目的提交历史记录。此命令将显示所有提交的列表,包括它们的唯一标识符、作者信息、时间戳和提交消息。
$ git log
commit 1234567890abcdef1234567890abcdef12345678
Author: John Doe <john.doe@example.com>
Date: Tue Apr 18 14:32:00 2023 -0400
实现新功能 X
commit 0987654321fedcba9876543210fedcba9876543
Author: Jane Smith <jane.smith@example.com>
Date: Mon Apr 17 10:15:30 2023 -0400
修复模块 Y 中的错误
通过了解 Git 提交的基础知识,你将更有能力管理项目历史记录并撤销不需要的更改,我们将在下一节中介绍这部分内容。
撤销未推送的提交
提交之后,有时你可能想在将更改推送到远程存储库之前撤销或修改这些更改。根据你的具体需求,Git 提供了几种方法来处理这种情况。
修改最后一次提交
如果你已经进行了一次提交,之后又意识到需要进行一些小的更改,可以使用 git commit --amend 命令来修改最近的一次提交。这将允许你更新提交消息、添加或删除文件,或者进行其他小的更改。
## 对你的文件进行更改
$ git add <修改后的文件>
$ git commit --amend
运行 git commit --amend 之后,你的 Git 编辑器将会打开,让你更新提交消息。你所做的更改将包含在修改后的提交中,并且提交的哈希值也会更新。
重置到上一次提交
如果你想撤销多个提交或者恢复更重大的更改,可以使用 git reset 命令。这个命令允许你将分支指针移动到特定的提交,从而有效地撤销该提交之后的所有提交。
## 撤销最后 3 次提交,但保留工作目录中的更改
$ git reset HEAD~3
## 撤销最后 3 次提交并丢弃所有更改
$ git reset --hard HEAD~3
在第一个示例中,git reset HEAD~3 会将分支指针向后移动三次提交,但工作目录中的更改仍然会保留。在第二个示例中,git reset --hard HEAD~3 会将分支指针向后移动三次提交,并丢弃工作目录中的所有更改。
graph LR
A[提交 1] --> B[提交 2]
B --> C[提交 3]
C --> D[提交 4]
D --> E[提交 5]
E --> F[提交 6]
F --> G[提交 7]
G --> H[提交 8]
H --> I[提交 9]
I --> J[提交 10]
J --> K[提交 11]
K --> L[提交 12]
L --> M[提交 13]
M --> N[提交 14]
N --> O[提交 15]
O --> P[提交 16]
P --> Q[提交 17]
Q --> R[提交 18]
R --> S[提交 19]
S --> T[提交 20]
subgraph 撤销 3 次提交
D --> G
end
subgraph 撤销 3 次提交并丢弃更改
D --> A
end
通过了解如何撤销未推送的提交,你可以有效地管理项目历史记录,并在与他人共享之前纠正任何错误或不需要的更改。
防止意外推送
虽然撤销未推送的提交是一项很有用的技能,但首先防止意外推送通常更好。LabEx 提供了几种工具和技术来帮助你避免将不需要的更改推送到远程存储库。
使用 Git 钩子
Git 钩子是 Git 在某些事件(如提交或推送)之前或之后运行的脚本。你可以利用 Git 钩子来实现自定义检查和保护措施,以防止意外推送。
一个常见的钩子是 pre - push 钩子,它在 git push 操作之前运行。你可以使用这个钩子来执行检查,比如确保所有测试通过,或者提交消息遵循特定格式。
以下是一个 pre - push 钩子的示例,它检查提交消息中是否包含 “WIP”(进行中的工作):
#!/bin/bash
## 获取将要推送的提交列表
commits=$(git rev - list --reverse HEAD..origin/main)
for commit in $commits; do
message=$(git log --format=%B -n 1 $commit)
if [[ $message == *"WIP"* ]]; then
echo "拒绝推送消息中包含 'WIP' 的提交:"
echo "$message"
exit 1
fi
done
exit 0
将此脚本保存为 .git/hooks/pre - push(确保使用 chmod +x.git/hooks/pre - push 使其可执行),它将阻止你推送消息中包含 “WIP” 的任何提交。
使用 Git 别名
Git 别名允许你创建自定义命令,这有助于你避免意外推送。例如,你可以为 “安全推送” 创建一个别名,在执行实际推送之前运行额外的检查。
以下是在你的 Git 配置中创建 “安全推送” 别名的示例:
[alias]
safepush =!git log -n 1 --pretty = format:%s | grep -q WIP || git push
有了这个别名,运行 git safepush 仅当最后一条提交消息不包含 “WIP” 时才会允许推送继续。
通过利用 Git 钩子和别名,你可以实施强大的保护措施来防止意外推送,并维护项目历史记录的完整性。
总结
在本 Git 教程中,你已经学会了如何撤销尚未推送到远程存储库的 Git 提交。通过了解可用的不同方法,你可以维护一个干净且有条理的 Git 历史记录,确保你的项目按计划进行。请记住,有效使用 Git 的关键是保持了解、养成良好习惯,并利用你所掌握的强大工具。



