git reset 和 git revert使用

本文详细解析了Git中reset和revert命令的使用场景和区别。reset用于撤销提交,将HEAD指针移至指定commit,有三种模式(--hard, --mixed, --soft);revert则创建新的commit来撤销之前的更改,避免直接修改历史。适用于恢复误提交的代码,保持仓库历史的清晰。

使用背景

很多时候当我们使用git管理我们的代码仓库时,会错误的提交代码,这时候我们想要恢复到我们提交之前的样子,这就需要使用

git reset 和 git revert。

使用区别

git reset

大家都知道HEAD是指向当前分支的最新commit,而git reset 就是将HEAD指向你想要指向的位置,并且抛弃掉这之后的提交。

1.查看git提交记录 
git log

2.回退到想要回退的conmmitId
git reset --hard commitId  

3.用“git push”会报错,因为我们本地库HEAD指向的版本比远程库的要旧:
git push -f

commitId是你想要回退到的版本。

git reset有三种模式

--hard:恢复的最彻底,工作区,暂存区,仓库全部恢复;

--mixed:默认模式,暂存区,仓库恢复,只保留工作区;

--soft:最温柔,只恢复仓库,暂存区,仓库仍然保留;

如果不小心git reset --hard

不要慌

git reflog可以查看所有分支的所有操作记录(只要本地磁盘git记录没有被清除),而git log只是显示提交记录并不会看到git reset的结果。这时候就可以看到被git reset删除的commitId,从而通过git reset重新让head指向被删除的commitId。

git revert

相比较与git reset而言,git revert并不会撤销抛弃之前的commit,而是通过提交修改删除掉提交到错误代码。

1.查看git提交记录
git log
2.查找到要删除的commitId
git revert -n commitId
3.将修改加入到缓存区
git add .
4.提交
git commmit -m "message"
5.提交到远程仓库,因为是新的提交,所以不会出现本地HEAD指向旧于远程分支的HEAD指向
git push

参考文章:

1.Git恢复之前版本的两种方法reset、revert(图文详解)_游笑天涯-优快云博客_git revert

<think>我们正在讨论Git中的两个撤销更改的命令:`git reset` `git revert`。根据用户提供的引用,我将总结它们的区别、使用场景及作用。 ### 1. **核心区别** `git reset` `git revert` 都是用于撤销更改的命令,但它们在实现方式影响上存在本质差异: | **特性** | **`git reset`** | **`git revert`** | |------------------|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------| | **操作对象** | 移动当前分支的HEAD指针到指定的提交(commit) | 创建一个新的提交,该提交会撤销指定提交的更改 | | **历史记录** | 会重写历史,删除目标提交之后的所有提交(如果目标提交不是最新提交) | 保留原始历史,通过新增提交来实现撤销,历史记录不会被修改 | | **适用场景** | 本地分支、私有分支(尚未推送的提交) | 公共分支(已推送的提交) | | **风险** | 高风险:会删除历史记录,可能导致协作问题(如强制推送覆盖他人工作) | 低风险:安全撤销,不影响他人工作 | | **工作区影响** | 可选:通过参数控制是否重置暂存区工作目录(`--soft`、`--mixed`、`--hard`) | 不影响:只生成新提交,工作目录暂存区不变(需手动处理冲突) | ### 2. **详细命令行为** #### (1) `git reset` - **核心作用**:将分支的HEAD指针移动到目标提交(`<commit>`),可选是否重置暂存区工作目录。 - **参数控制**: - `--soft`:仅移动HEAD指针,不修改暂存区工作目录。 *示例*:`git reset --soft HEAD~1` → 撤销最近一次提交,改动保留在暂存区。 - `--mixed`(默认):移动HEAD指针并重置暂存区,但不修改工作目录。 *示例*:`git reset HEAD~1` → 撤销提交且取消暂存,改动保留在工作目录。 - `--hard`:彻底回退,重置HEAD、暂存区工作目录到目标提交状态。 *示例*:`git reset --hard a1b2c3d` → 丢弃所有未提交的更改提交记录,慎用! - **适用场景**: - 本地撤销未推送的提交(如提交信息错误、临时调试代码)。 - 清理实验性分支的历史记录(例如:合并多个临时提交为一个整洁提交)。 #### (2) `git revert` - **核心作用**:生成一个新提交,该提交的内容是撤销指定提交的更改。 *示例*:`git revert HEAD` → 撤销最近一次提交,生成一个新提交记录这次撤销操作。 - **行为特点**: - 可撤销单个或多个提交(如`git revert commit1 commit2`)。 - 若撤销的更改与其他提交冲突,需手动解决冲突后完成`revert`(`git revert --continue`)。 - **适用场景**: - 撤销已推送到远程仓库的提交(如修复引入严重Bug的提交)。 - 需要保留完整历史记录的公共分支(团队协作时避免历史重写)。 ### 3. **关键使用场景对比** | **场景** | **推荐命令** | **原因** | |------------------------------|--------------------|--------------------------------------------------------------------------| | 本地撤销未推送的提交 | `git reset` | 彻底清理历史,避免无效提交污染记录[^1][^3] | | 撤销已推送的提交 | `git revert` | 安全撤销,不影响其他协作者的工作[^1][^3] | | 合并多个本地提交以简化历史 | `git reset --soft` | 灵活重组提交记录,便于代码审查[^4] | | 紧急修复生产环境Bug | `git revert` | 快速生成修复补丁,无需重写公共历史[^2][^5] | ### 4. **操作示例** #### 场景1:撤销未推送的本地提交(使用`reset`) ```bash # 查看提交历史(假设最新提交是123abc) git log --oneline # 输出:123abc (HEAD) Fix typo # 撤销提交(保留改动到工作目录) git reset --mixed HEAD~1 # 或直接 git reset HEAD~1(默认mixed) # 此时提交被移除,修改保留在工作目录 git status # 显示未暂存的修改 ``` #### 场景2:撤销已推送的提交(使用`revert`) ```bash # 撤销指定提交(如456def) git revert 456def # 解决可能的冲突并完成revert git add . git revert --continue # 推送修复提交 git push origin main ``` ### 5. **注意事项** - **`reset` 的风险**:重置已推送的历史后,再次推送需强制覆盖(`git push -f`),可能导致协作者的本地分支与远程不一致[^3]。 - **`revert` 的链式反应**:若撤销的提交是后续提交的基础(如功能提交A被撤销,但提交B依赖A),可能需要连续撤销多个提交或手动修复代码。 --- 通过以上分析可以看出,`git reset` 是历史重写工具,适合本地操作;`git revert` 是安全撤销工具,适用于公共分支[^4]。理解两者的差异能帮助您在版本控制中做出更安全高效的决策。 §§相关问题§§ 1. 如何撤销 `git reset --hard` 操作以恢复丢失的代码? 2. `git rebase` `git reset` 在整理提交历史时有何异同? 3. 团队协作中如何规范使用 `git revert` 处理已发布的错误提交? </think>### Git ResetGit Revert 的核心区别与使用场景 基于引用内容,以下是两者对比的数学化总结($ \Delta H $ 表示历史记录变化,$ \mathcal{R} $ 表示风险等级): | **特性** | **`git reset`** | **`git revert`** | **数学表达** | |------------------|------------------------------------------------|------------------------------------------------|--------------------------------| | **本质** | 移动 HEAD 指针(历史重写) | 创建新提交(历史追加) | $ \Delta H_{\text{reset}} < 0 $ <br> $ \Delta H_{\text{revert}} > 0 $ | | **历史影响** | 删除后续提交(不可逆) | 保留原始提交(可追溯) | $ \text{reset} \Rightarrow \text{历史截断} $ <br> $ \text{revert} \Rightarrow \text{历史延续} $ | | **安全风险** | 高风险(公共分支禁用) | 低风险(协作友好) | $ \mathcal{R}_{\text{reset}} \gg \mathcal{R}_{\text{revert}} $ | | **工作区影响** | 通过参数控制:<br> `--soft`:保留改动<br> `--hard`:清除所有改动 | 不改动工作区(需手动解决冲突) | 设 $ W $ 为工作区状态:<br> $ \text{reset} \to W = f(\text{参数}) $ <br> $ \text{revert} \to \Delta W = 0 $ | | **适用场景** | 本地未推送的提交撤销 | 已推送提交的公共撤销 | | --- ### 一、核心机制详解 #### 1. **`git reset`(回退)** - **作用原理**: 移动分支指针到目标提交 $ C_{\text{target}} $,丢弃后续提交: $$ \text{HEAD} \xrightarrow{\text{reset}} C_{\text{target}} \quad \text{(删除 } C_{\text{target}+1} \text{ 至 } C_{\text{current}} \text{)} $$ - **参数控制**: - `--soft`:仅移动 HEAD(改动保留在 **暂存区**) $$ \text{HEAD} \downarrow, \quad \text{暂存区} = \text{未提交改动} $$ - `--mixed`(默认):移动 HEAD + 重置暂存区(改动保留在 **工作目录**) $$ \text{HEAD} \downarrow, \quad \text{暂存区} \to \emptyset $$ - `--hard`:彻底回退(丢弃所有未提交改动) $$ \text{HEAD} \downarrow, \quad \text{暂存区} \to \emptyset, \quad \text{工作目录} \to C_{\text{target}} $$ - **典型场景**: - 撤销本地未推送的临时提交 - 合并多个提交(`reset --soft` + 重新提交)[^4] ```bash # 撤销最近2次提交(保留改动到工作目录) git reset HEAD~2 ``` #### 2. **`git revert`(反做)** - **作用原理**: 为目标提交 $ C_{\text{target}} $ 生成一个 **逆向补丁**,创建新提交 $ C_{\text{new}} $: $$ C_{\text{new}} = -C_{\text{target}} \quad \text{(历史追加)} $$ 例如:原提交添加一行代码,revert 提交会删除该行[^3]。 - **冲突处理**: 若逆向补丁与当前代码冲突,需手动解决: $$ \text{revert} \xrightarrow{\text{冲突}} \text{手动修复} \xrightarrow{\text{continue}} C_{\text{new}} $$ - **典型场景**: - 撤销已推送到远程的提交(如修复生产环境 Bug) ```bash # 撤销指定提交(生成新提交) git revert a1b2c3d ``` --- ### 二、关键区别对比 | **维度** | **`git reset`** | **`git revert`** | |------------------|-------------------------------------------|------------------------------------------| | **历史记录** | 重写历史(原提交消失) | 追加历史(原提交保留) | | **协作影响** | 需强制推送(`git push -f`),破坏他人历史 | 直接推送(`git push`),安全协作 | | **撤销范围** | 可撤销连续提交(`HEAD~3`) | 可撤销任意提交(按需选择) | | **恢复难度** | 需 reflog 找回(复杂) | 直接再次 revert 逆转(简单) | --- ### 三、使用场景决策树 ```mermaid graph TD A[需要撤销提交] --> B{是否已推送?} B --> |未推送| C[使用 git reset] B --> |已推送| D{是否需要保留历史?} D --> |是| E[使用 git revert] D --> |否| F[禁用!强制重置会导致协作灾难] C --> G{需保留改动?} G --> |是| H[git reset --soft] G --> |暂存改动| I[git reset --mixed] G --> |彻底丢弃| J[git reset --hard] ``` --- ### 四、最佳实践建议 1. **私有分支**:优先用 `reset` 整理历史(如合并临时提交)[^4] $$ \small \text{优化:} \underbrace{C_1 + C_2 + \cdots + C_n}_{\text{临时提交}} \xrightarrow{\text{reset --soft}} C_{\text{clean}} $$ 2. **公共分支**:强制使用 `revert` 撤销错误(如修复线上 Bug)[^3] 3. **紧急回滚**: - 未推送:`reset --hard` - 已推送:`revert` + 立即推送 > 关键原则:**已共享的历史不可重写**(Golden Rule of Git)[^2][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值