---
url: /blog/a24vkifx/index.md
description: >-
  在日常的开发中，我们经常使用Git来进行版本控制。有时候，我们可能会不小心将错误的代码 Push 到远程仓库，或者想要在本地回退到之前的某个版本重新开发。
  或者像我一样，写了一些感觉以后很有用的优化方
---
在日常的开发中，我们经常使用Git来进行版本控制。有时候，我们可能会不小心将错误的代码 Push 到远程仓库，或者想要在本地回退到之前的某个版本重新开发。

或者像我一样，写了一些感觉以后很有用的优化方案push到线上，又接到了一个新的需求。但是呢，项目比较重要，没有经过测试的方案不能轻易上线，为了承接需求只能先把push上去的优化方案先下掉。

现在我的分支是这样的，我想要在本地和远程仓库中都恢复到 **help文档提交** 的部分。

![](assets/Git%20如何撤回已%20Push%20的代码/Image.webp)

### 注意

* 在执行这些操作之前，请确保完全理解它们的影响，特别是在多人协作的项目中。
* 对于受保护的分支（如主分支或发布分支），可能无法执行强制推送。需要根据你的项目设置或团队规范来处理这种情况。
* 使用强制推送会改变远程仓库的历史，可能会给团队成员带来困扰。在这样做之前，最好与团队成员沟通。

## 最简单粗暴的方法

### IntelliJ IDEA方法

如果你的错误代码不是很多，那么你其实可以通过与你想要恢复到的commit进行对比，然后手动删除错误代码，然后删除不同的代码。

![](assets/Git%20如何撤回已%20Push%20的代码/Image%201.webp)

> 按住 ctrl 选择想要对比的两个commit，然后选择 **Compare Versions** 就能通过对比删除掉你想要删除的代码。

这个方案在代码很简单时时非常有效的，甚至还能通过删除后最新commit和想要退回的commit在 **Compare** 一下保障代码一致。

但是这个方法对于代码比较复杂的情况来说就不太好处理了，如果涉及到繁杂的配置文件，那更是让人头疼。

而且，这样还会 **保留错误提交的记录** ，对于有强迫症的我来说，有点接受不能。对此，git也有一套较为优雅的操作流程，同样能解决这个问题。

### Git命令方法

在Git中，要比较两个commit之间的代码变动，可以使用 `git diff` 命令。这个命令允许你查看两个不同commit之间的差异。以下是一些常用的方法：

1. **基本用法**:
   ```xml
   体验AI代码助手 代码解读复制代码git diff <commit1> <commit2>
   ```
   这里 `<commit1>` 和 `<commit2>` 分别代表你想要比较的两个commit的哈希值。
   这里注意一下，在使用 `git diff` 命令比较两个commit时，commit1和commit2的顺序会影响显示的差异内容。命令 `git diff <commit1> <commit2>` 的作用是显示从 `commit1` 变化到 `commit2` 时代码发生的变动。

* 如果你先指定较早的commit（ `commit1` ），然后指定较晚的commit（ `commit2` ），你会看到在这两个commit之间所做的更改。
* 相反，如果你先指定较晚的commit作为 `commit1` ，然后指定较早的commit作为 `commit2` ，你将看到要从较晚的commit回退到较早commit所需撤销的更改。

所以个人一般用法的话都是 **将较早的commit作为 `commit1` ，较晚的commit作为 `commit2` ，通常更符合查看代码变化的直观逻辑** 。

2. **比较指定文件的变化**: git diff -- \<file\_path> 这条命令将只显示指定文件在两个commit之间的差异。

## IDEA 中 Git 较为优雅的方法

### Reset Current Branch 到你想要恢复的commit记录

![](assets/Git%20如何撤回已%20Push%20的代码/Image%202.webp)

这个时候会跳出四个选项供你选择，我这里是选择 **hard** 。

其他选项的含义 **仅供参考** ，因为我也没有一一尝试过。

1. **Soft** ：你之前写的不会改变，你之前暂存过的文件还在暂存。
2. **Mixed** ：你之前写的不会改变，你之前暂存过的文件不会暂存。
3. **Hard** ：文件恢复到所选提交状态，任何更改都会丢失。 **你已经提交了，然后你又在本地更改了，如果你选hard，那么提交的内容和你提交后又本地修改未提交的内容都会丢失。**
4. **keep** ：任何本地更改都将丢失，文件将恢复到所选提交的状态，但本地更改将保持不变。 **你已经提交了，然后你又在本地更改了，如果你选keep，那么提交的内容会丢失，你提交后又本地修改未提交的内容不会丢失。**

![](assets/Git%20如何撤回已%20Push%20的代码/Image%203.webp)

![](assets/Git%20如何撤回已%20Push%20的代码/Image%204.webp)

![](assets/Git%20如何撤回已%20Push%20的代码/Image%205.webp)

然后，之前错误提交的commit就在本地给干掉了。但是远程仓库中的提交还是原来的样子，你要把目前状态同步到远程仓库。 **也就是需要把那几个commit删除的操作push过去。**

打开push界面，虽然没有commit需要提交，需要点击 **Force Push** ，强推过去。

![](assets/Git%20如何撤回已%20Push%20的代码/Image%206.webp)

需要注意的是对于一些被保护的分支，这个操作是不能进行的。需要自行查看配置，我这里因为不是master分支，所以没有保护。

![](assets/Git%20如何撤回已%20Push%20的代码/Image%207.webp)

可以看到，远程仓库中最新的commit只有我们的 **help文档** 。在其上的三个提交都没了。

![](assets/Git%20如何撤回已%20Push%20的代码/Image%208.webp)

## 我还是想用Git命令来完成恢复

### 1. 重置当前分支到特定commit

首先，找到你想要恢复到的commit的哈希值。可以通过 `git log` 查看提交历史来找到这个哈希值。

然后，使用 `git reset` 命令来重置当前分支。这里有四种不同的模式可选：

* **Soft** ： `git reset --soft <commit-hash>`
* **Mixed** ： `git reset --mixed <commit-hash>` （这是默认选项）
* **Hard** ： `git reset --hard <commit-hash>`
* **Keep** ： `git reset --keep <commit-hash>`

### 2. 将更改推送到远程仓库

在重置后，本地分支的状态可能与远程仓库不同步。为了同步这些更改，需要使用强制推送。但请注意，这个操作对于团队协作和共享仓库来说可能是危险的，因为它会覆盖远程仓库的历史。

使用以下命令进行强制推送：

```bash
体验AI代码助手 代码解读复制代码git push origin <branch-name> --force
```

或者，如果你使用的是Git版本2.5及以上，可以使用更安全的方式：

```bash
体验AI代码助手 代码解读复制代码git push origin <branch-name> --force-with-lease
```

这个命令在强制推送之前会检查远程分支的状态，确保没有被其他人更新过。

**注意: 以上使用的是2023版IDEA,如果有出入的话可以考虑搜索使用git命令代替，毕竟通用性会更好一点，可能就是有点不直观。**
