git 我提交了,但我又后悔了

背景

在实际的开发工作中,使用git commit 总会遇到一些令人抓狂的提交,一切源于手欠和脑子不清醒,把一些不该提交的东西一起提交了。
在这里插入图片描述

不过还在Git还是能给我们后悔的机会。

场景模拟

    @PostMapping("/hhh")
    public String  test1(){
        AbsBatch batch = mapper.selectByPrimaryKey("dd");
        return  batch.toString();
    }

    @PostMapping("/hhhh")
    public String  test3(){
        AbsBatch batch = mapper.selectByPrimaryKey("dd");
        return  batch.toString();
    }

在这一次的提交中,我本来只需要提交test1这个方法,但是一不小心把test3也一起提交了o((⊙﹏⊙))o

case 1 已提交未push

这种情况处理起来比较简单。如果你适用的开发工具是idea时,就显得尤为简单。

undo commit

直接就是 右键 -> undo commit
在这里插入图片描述
直接把本地的git提交记录给去掉了,但是你之前对代码的修改还在(✪ω✪) 然后你就可以回到未提交的状态,然后重新提交。

case 2 已提交 未push 或已push

reset

注意:

  1. 如果已经push了,再使用reset命令时取消更改时。提交代码时,需要强制覆盖远程代码而且请确保其他人没有pull你提交的错误代码,不然其他人再次提交并push时,错误代码又会上远程
  2. reset 的节点请正确选择,不要选到其他分支的提交记录。

git reset --soft,–hard的区别

git reset 命令可以将当前的HEAD重置到特定的状态。
首先要搞清楚下面几个概念

  • HEAD: HEAD就是指向当前分支当前版本的游标
  • Index: Index即为暂存区,当你修改了你的git仓库里的一个文件时,这些变化一开始是unstaged状态,为了提交这些修改,你需要使用git add把它加入到index,使它成为staged状态。当你提交一个commit时,index里面的修改被提交。
  • working tree: 即当前的工作目录。

git reset 的用法
git reset [<mode>] [<commit>]
git reset 将当前分支的HEAD指向给定的版本,并根据模式的不同决定是否修改index和working tree。
常用的有三种模式,–soft, --mixed, --hard,如果没有给出则默认是–mixed

1 --soft

已经有未提交的更改:如果在执行软重置之前有未提交的更改,Git 可能会拒绝执行软重置操作。您可以通过提交或保存当前工作目录中的更改来解决此问题。
请一定注意这个

reset --soft相当于后悔药,给你重新改过的机会。对于上面的场景,就可以再次修改重新提交,保持干净的 commit 记录。

以上说的是还未 push 的commit。对于已经 push 的 commit,也可以使用该命令,不过再次 push 时,由于远程分支和本地分支有差异,需要强制推送git push -f来覆盖被 reset 的 commit。

还有一点需要注意,在reset --soft指定 commit 号时,会将该 commit 到最近一次 commit 的所有修改内容全部恢复,而不是只针对该 commit。
使用 --soft参数将会仅仅重置HEAD到制定的版本,不会修改index和working tree

三次提交
第一次:test1.txt
第二次:test2.txt
第三次:test3.txt

在这里插入图片描述在这里插入图片描述
本地文件的内容并没有发生变化,而index中仍然有最近一次提交的修改,这时执行git status会显示这些修改已经在再暂存区中了,无需再一次执行git add。接下来就可以重新修改提交了。

2 --mixed

使用 --mixed参数与 --soft的不同之处在于, --mixed修改了index,使其与第二个版本匹配。index中给定commit之后的修改被unstaged。需要重新 git add .
在这里插入图片描述

3. --hard

使用–hard同时也会修改working tree,也就是当前的工作目录,如果我们执行git reset --hard HEAD~,那么最后一次提交的修改,包括本地文件的修改都会被清楚,彻底还原到上一次提交的状态且无法找回。所以在执行reset --hard之前一定要小心
不建议使用!

reset idea 页面操作版

如果你不习惯操作 命令行,那么直接使用idea也可以完成这一步。

  1. 第一步找到 git 提交记录,复制需要回退的版本号
    在这里插入图片描述
  2. 项目根目录上找到 reset 入口
    在这里插入图片描述
  3. 设置回退版本号
    在这里插入图片描述
  4. 强制覆盖远程。(谨慎操作)
    在这里插入图片描述
    或 使用命令行
    使用 git push 命令并添加 --force-f参数,强制覆盖远程分支。
git push --force origin <branch-name>

例如,强制覆盖 main 分支:

git push --force origin main

revert

原理: git revert 是用于 “反做” 某一个版本,以达到撤销该版本的修改的目的。比如,我们 commit 了三个版本(版本一、版本二、 版本三),突然发现版本二不行(如:有 bug),想要撤销版本二,但又不想影响撤销版本三的提交,就可以用 git revert 命令来反做版本二,生成新的版本四,这个版本四里会保留版本三的东西,但撤销了版本二的东西。如下图所示:

在这里插入图片描述

适用场景: 如果我们想撤销之前的某一版本,但是又想保留该目标版本后面的版本,记录下这整个版本变动流程,就可以用这种方法。

具体操作:

举个例子,现在库里面有三个文件:READ.md、text.txt、text2.txt。
在这里插入图片描述

  1. 查看版本号:
    可以通过命令行查看(输入 git log):
    如图,最近的两个版本分别叫:“add text.txt”(即新增了文件 text.txt)、“add text2.txt”(新增了文件 text2.txt)。这个时候我们不需要 text.txt 这个文件了,那就是说不想要 “add text.txt” 那个版本的操作,那可以通过反做 “add text.txt” 这个版本来实现。
    在这里插入图片描述

也可以通过 github 网站图形化界面查看版本号:
在这里插入图片描述

2. 使用 “git revert -n 版本号” 反做,并使用 “git commit -m 版本名” 提交:
(1)反做,使用 “git revert -n 版本号” 命令。如下命令,我们反做版本号为 8b89621 的版本:

git revert -n 8b89621019c9adc6fc4d242cd41daeb13aeb9861

注意: 这里可能会出现冲突,那么需要手动修改冲突的文件。而且要 git add 文件名。
(2)提交,使用 “git commit -m 版本名”,如:

git commit -m "revert add text.txt"

此时可以用 “git log” 查看本地的版本信息,可见多生成了一个新的版本,该版本反做了 “add text.txt” 版本,但是保留了 “add text2.txt” 版本:
在这里插入图片描述

3. 使用 “git push” 推上远程库:

git push

查看 github 上显示的远程库版本信息:

在这里插入图片描述

此时查看仓库的文件,剩下两个:READ.md、text2.txt
在这里插入图片描述

反做成功!

冲突

revert 如果之前和之后版本有改到同一个地方也会触发冲突(需要手动解决冲突)

idea 操作

选择要 revert 的版本进行 revert(是 revert 选中的本版)
在这里插入图片描述

也可以复制版本号进行 revert

管理端操作

在浏览器选择要回滚的版本进行回滚(示例 gitlab

比如某个需求开发完成后(A 分支)需要合并到主分支,却不小心把 B 分支合到主分支,B 分支还在开发中未能达到合并的要求,这种场景正常情况直接 reset 掉就行,假如选择了 revert 也可以达到目的。
但是后面 B 开发完成需要合并主分支后,发现主分支合不上原因是之前已经有个 revert 的记录,遇到这种情况只需要把之前的 revert 记录再 revert 一次就行(不推荐这种操作行为)。所以正确的选择回滚的方式可以避免不必要的麻烦。

这一点 ,同样适用于开发到一半,误提交的情况下。revert 之后,开发完提交无法更新远程仓库

提交错分支了

git cherry-pick 是一个强大的 Git 工具,它的核心作用是将某个分支上的单个(或多个)提交“单独复制”到当前分支,而不是合并整个分支。以下我会用通俗易懂的方式解释它的应用场景、原理和实际案例。

一、应用场景:什么时候需要 cherry-pick?

  1. ​跨分支应用特定修复
    ​场景:你在 develop 分支上修复了一个 Bug(提交 abc123),但这个 Bug 同样存在于master分支上。你不想合并整个 develop 分支到 master,而是只想将这一个修复提交应用到 master
    ​操作:切换到 master 分支,运行 git cherry-pick abc123。这个提交会被“复制” 到 master 分支。
  2. ​移植功能到旧版本
    ​场景:你正在维护一个旧版本的代码分支(比如 v1.x),但某个新功能(提交 def456)在 v2.x 分支上开发,现在需要单独将这个功能移植到旧版本。
    ​操作:在v1.x 分支上运行 git cherry-pick def456
  3. ​避免合并无关代码
    ​场景:你只想提取某个分支上的几个关键提交,而该分支上还有其他不想合并的代码(比如未完成的实验性代码)。
    ​操作:用 cherry-pick 仅复制需要的提交。
  4. ​修复误提交到错误分支的代码
    ​场景:你本应在 feature/login 分支开发,但不小心在main分支上提交了代码。此时可以:
    将误提交的提交git cherry-pick 到正确的分支。
    main 分支删除误提交(用 git revertgit reset)。

二、cherry-pick 和 merge / rebase 的区别

merge:合并两个分支的所有差异,生成一个新的合并提交。
rebase:将当前分支的提交“重新播放”到目标分支上,改变提交历史。
cherry-pick:只复制特定提交的内容到当前分支,不关心其他提交。
👉 ​关键区别:cherry-pick 是精准的“复制粘贴”,而 merge 和 rebase 是“整体迁移”。

三、实际案例演示

假设有以下提交历史:


develop 分支:A → B → C (修复 Bug)
master 分支:X → Y → Z
现在需要将 develop 上的提交 C 复制到 master:
# 1. 切换到 master 分支
git checkout master

# 2. 复制提交 C
git cherry-pick C

结果:

master 分支:X → Y → Z → C'(C 的副本)

注意:C’ 的哈希值会改变,但内容与 C 相同。

四、cherry-pick 的注意事项

  1. 可能引发冲突:
    如果复制的提交依赖其他提交的代码,可能会冲突。需要手动解决冲突后,运行 git cherry-pick --continue
  2. 谨慎使用:
    滥用 cherry-pick 可能导致代码重复或逻辑混乱(尤其是提交之间有依赖关系时)。
  3. 历史记录污染:
    cherry-pick 会生成新的提交,可能导致提交历史冗余。建议在明确需要时才使用。

五、高级用法

​复制多个提交:

git cherry-pick commit1 commit2 commit3

​复制连续提交范围:

git cherry-pick start_commit^..end_commit

​仅应用代码修改,不生成提交​(需手动提交):

git cherry-pick -n commit_hash

六、总结
git cherry-pick 的核心价值是“精准移植代码”。它适用于需要从其他分支“摘取”特定提交的场景,但需注意避免滥用,尤其是当提交之间有依赖关系时。合理使用它能极大提升工作效率,尤其是在多分支协作开发中!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值