git 怎么删除 指定 commit 快照 ?

2019-01-27 21:27:05 +08:00
 frylkrttj

git reset --hard <commit_id>

我运行该命令为什么不是删除这个快照而是调到这个快照了。前几个小时实验的,应该不会记错。

7132 次点击
所在节点    git
45 条回复
frylkrttj
2019-01-28 09:40:11 +08:00
@thinkmore @thinkmore @youstu
我找的有些教程说,删除中间的 commit 其实是合并,那么问题来了,我到底找合并还是删除 commit 的方法。

我自己实验的结果:删除 头部 commit, 跟中部 commit,跟尾部 commit,都是不一样的。

谁可以把这个说的清楚! @all
youstu
2019-01-28 09:41:51 +08:00
@frylkrttj
不熟悉当然就觉得复杂。 也就看你要达到什么目的,如果你只是想把某几次提交回退,revert 就好。如果你是想让你的 log 好看,让某个 commit 消失,rebase 交互就可以达到目的。 至于 reset hard,你可以先 checkout 一个分支备份当前分支,然后 reset hard 到你想删除的前一个 commit,然后从备份分支上把之后的提交全部 pick 过来,中间那个 commit 也就看不见了,实际上跟 rebase 是一样的。
youstu
2019-01-28 09:44:03 +08:00
建议把教程看一遍吧: https://git-scm.com/book/zh/v2
thinkmore
2019-01-28 09:56:29 +08:00
Hilong
2019-01-28 10:03:28 +08:00
https://juejin.im/entry/5b0c0dac6fb9a00a2d3970e3 看看我这篇文章?写了怎么删除特定提交,就是通过 rebase,带截图操作的。
boileryao
2019-01-28 10:05:03 +08:00
说一个不用 rebase 的方法吧
对于 ABCDE 五个 commit,想删掉 B,可以从 A checkout 新分支然后 cherry-pick C..E,这个新分支就已经把 B 删掉了。

删掉一个 commit 很可能会丢数据,尽量 revert 或者通过新的提交“抵消”掉原来的更改
justicelove
2019-01-28 10:08:43 +08:00
git revert commit
itskingname
2019-01-28 10:13:57 +08:00
https://www.kingname.info/2015/01/08/清空 Github 上某个文件的历史 /
RoshanWu
2019-01-28 10:14:22 +08:00
revert 是正解,但可能会产生冲突。所以简单的建议 revert,复杂的建议 rebase。
lazyfighter
2019-01-28 10:24:00 +08:00
rebase
capric
2019-01-28 14:18:02 +08:00
@frylkrttj 退出的时候,自动生成的备注是 commit msg,是可以全部删除,自己编辑的,也可以保留一部分,删除不要的
lyb11232345688
2019-01-28 18:16:12 +08:00
git revert 取消某次提交。 删除是没有的,除非你重写提交记录
0xNone
2019-01-28 20:32:06 +08:00
你说的是这个吗?

我们在使用 git 的时候可能会出现提交了错误的版本,这时候我们将代码修改完成了,需要覆盖之前错误的版本,这时候就可以使用一些小技巧。

注意: 操作会覆盖掉错误版本之后其他人提交的 commit,使用需谨慎

使用 git pull 保持代码同步状态
设置 git reset <commit-id> 当前 git 版本指针到错误的版本上
使用 git stash 错误版本之后的修改,以及我们修改的内容
使用 git push --force 强制覆盖当前远程服务器上的 commit 历史
使用 git stash pop,释放暂存的修改,或继续修改代码
接下来就是一套连招,git add . -> git commit -m "message" -> git push
frylkrttj
2019-01-28 21:32:03 +08:00
@0xNone #33 你这是单个场景,认真看我#21。

假设我仓库现在只有两个 commit 快照,恐怕你这方法不适用。
yuikns
2019-01-28 23:16:40 +08:00
commit 本质是计算上一个和当前两个版本得到 diff,然后生成的 patch。 第一个 commit 的 diff 是从 orphan 开始算。see https://git-scm.com/docs/git-checkout/1.7.3.1#git-checkout---orphan

因此“删除”最近一个或若干 commit,简单回滚即可。( reset )
“删除”某个中间的 commit,后面其实全部改了,只是用 rebase 可以快速编辑一下某几个 commit,然后后面 replay 一下。但实际上 sha1 全变了。
“删除”第一个 commit,那么就需要重开一个 branch, 从什么都没有开始做。

git checkout --orphan brand-new-branch [first-sha-1, in case you need to edit]

replay 也不能用 merge 了,因为它们并没有共同祖先节点。非要用也可以用 cherry-pick ( https://git-scm.com/docs/git-cherry-pick )
wbswjc
2019-01-29 01:59:44 +08:00
# 如果你想要删除该提交及其中内容:

你需要 rebase 中的 drop 操作。

git 仓库中有 a, b, c, d 4 个文件,依次提交,形成以下内容:

$ git log
> commit f3fe836c34642927f57e8f2e6cc8a62382c93c0c
> d
> commit 0e4f4862a0ab3256d28ced2f26950e2e4312c5b4
> c
> commit a4c409545f056bb6a21f9f82d2749f6faadde70a
> b
> commit f3134e02ebfe4d5b70999c3dc03c8f31161cf209
> a

以首个提交,即 a 为基准,进入 rebase 模式:

$ git rebase -i f313
> pick a4c4095 b
> pick 0e4f486 c
> pick f3fe836 d

修改 rebase 策略如下,表示删除第 3 次提交,即 c:
> pick a4c4095 b
> drop 0e4f486 c
> pick f3fe836 d

:wq 或 :x 退出 vim,开始 rebase:

因为只有一个 drop 操作,且没有影响其后任何一个 commit,所以直接全部成功:

> Successfully rebased and updated refs/heads/master.

这时候:

$ git log
> commit 7eafc41ab349feed33c060e5898278509a71d373
> d
> commit a4c409545f056bb6a21f9f82d2749f6faadde70a
> b
> commit f3134e02ebfe4d5b70999c3dc03c8f31161cf209
> a
wbswjc
2019-01-29 02:01:44 +08:00
# 如果你想要删除该提交,不过保留其修改的文件:

你需要 rebase 中的 squash 操作。

git 仓库中有 a, b, c, d 4 个文件,依次提交,形成以下内容:

$ git log
> commit f3fe836c34642927f57e8f2e6cc8a62382c93c0c
> d
> commit 0e4f4862a0ab3256d28ced2f26950e2e4312c5b4
> c
> commit a4c409545f056bb6a21f9f82d2749f6faadde70a
> b
> commit f3134e02ebfe4d5b70999c3dc03c8f31161cf209
> a

以首个提交,即 a 为基准,进入 rebase 模式:

$ git rebase -i f313
> pick a4c4095 b
> pick 0e4f486 c
> pick f3fe836 d

修改 rebase 策略如下,表示把 c 并入其前一个 commit,即 b:
> pick a4c4095 b
> squash 0e4f486 c
> pick f3fe836 d

:wq 或 :x 退出 vim,开始 rebase:

因为只有一个 squash 操作,所以直接进入该操作:

> # This is a combination of 2 commits.
> # This is the 1st commit message:
> b
> # This is the commit message #2:
> c

可以修改 b 和 c 合并( squash )后的提交信息,修改完(也可不改)后 :wq 或 :x 退出。

后面没有其他操作,所以成功:

> Successfully rebased and updated refs/heads/master.

这时候:

$ git log
> commit db58ecd2a2cd017a34274781dc8b8c61531147b9
> d
> commit 0baa7789a1533c9178874d2ab3b93c44f2adf1b3
> b
> c
> commit f3134e02ebfe4d5b70999c3dc03c8f31161cf209
> a
fan123199
2019-01-29 07:14:59 +08:00
LZ 到底后续试了之后出现什么问题啊?理论上 rebase -i 是可以解决开头说的问题。
limuyan44
2019-01-29 08:16:54 +08:00
revert 呀,干嘛要删除啊....
frylkrttj
2019-01-29 09:41:59 +08:00
@fan123199 #38 之前用 rebase -i commit_id 认为是删除该 快照,哪知道它弹出编辑器还带一堆备注我看了就懵了根本不知道怎么回事,以为是没用的废话,就关闭保存了,结果不是我要得结果,根本没有删除该快照。所以就再也没考虑这个命令了。

我一直以为删除一个 commit_id 应该跟 rm 删除一个文件一样,看来不是。 @all 请问你有没有直接删除一个快照的命令。

@wbswjc #37 #38 的回复让我知道那一堆备注是怎么回事了。不这样删除一个快照也太绕了吧,正常人的脑子都不会想到 rebase -i commit_id 选中的这个 commit_id 不是用来删除的。特别鸣谢 @wbswjc

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/531078

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX