【问题标题】:How to remove redundant commits after 'git reset --soft' and 'git commit'如何在“git reset --soft”和“git commit”之后删除多余的提交
【发布时间】:2019-10-23 02:47:11
【问题描述】:

假设我有一个像这样设置的 Git 存储库:

$ git init test && cd test
$ touch a && git add . && git commit -m "add a"
$ touch b && git add . && git commit -m "add b"
$ touch c && git add . && git commit -m "add c"
$
$ git --no-pager log --pretty="%h %s" # print short SHA and message subject
176d6d0 add c
495991e add b
1d8444a add a

现在由于某些原因,我想将最近的 2 个提交(176d6d0 add c495991e add b)压缩为一个 [1]:

$ git reset --soft 1d8444a # go back to the first commit ("add a")
$ git add . && git commit -m "bc"
$
$ git --no-pager log --pretty="%h %s"
c01e64a bc
1d8444a add a

是的,看起来我们已经完成了!

不完全是!

如果我们查看git reflog show,旧的提交仍然存在:

$ git --no-pager reflog show
c01e64a (HEAD -> master) HEAD@{0}: commit: bc
1d8444a HEAD@{1}: reset: moving to 1d8444a9747bd5e4176c
176d6d0 HEAD@{2}: commit: add c                           # old commit
495991e HEAD@{3}: commit: add b                           # old commit
1d8444a HEAD@{4}: commit (initial): add a

如果我们签出旧的提交,我们仍然可以恢复它。

$ git --no-pager show -s 176d6d0 # this is the "add c" commit
commit 176d6d0aa92b230f4dd1e4ed8ae028b7c5fbb2d5
Author: XXX <XXX@XXX.com>
Date:   Tue Oct 22 22:19:23 2019 -0400

    add c

$ git checkout 176d6d0
Note: checking out '176d6d0'.

You are in 'detached HEAD' state. You can look around
... # omitted

HEAD is now at 176d6d0 add c

我试图删除这些陈旧的旧提交,但这些都不起作用,旧提交在 git reflog showgit checkout-able 中仍然可见:

git gc
git gc --prune=all
git reflog expire --all
git reflog expire --expire=now
git reflog expire --expire-unreachable=now
git reflog expire --expire=now --all # tricky, see update below

问题

  1. 我应该如何真的丢弃旧的提交(176d6d0 add c495991e add b)?
  2. 这些旧提交(176d6d0 add c495991e add b)的术语是什么,例如它们真的是“无法访问的提交”、“陈旧的提交”吗?
    删除它们的行为的行话是什么,例如是“修剪”、“垃圾回收”吗?
  3. 人们一直在做git resetgit rebase -i。如果他们不以某种方式删除这些陈旧的提交,他们是否会得到一个臃肿的 Git 存储库,尤其是对于有很多合作者(如 Chromium)的大型项目?
  4. (很高兴)请解释为什么您对 1 的回答有效。

脚注:

[1] 我可以使用git rebase -i,但我想以编程方式而不是交互方式进行操作,以便可以通过脚本自动执行,但这不是重点)

[2] this answer 没有完全回答我的问题

更新:

这会删除git reflog show 显示的所有条目,但我不太明白为什么 阅读文档..还有其他问题(请参见上文)

    git reflog expire --expire=now --all

然而,旧的提交虽然没有显示在git reflog show,但仍然是git checkout——如果你记得 SHA,这意味着这些旧的提交并没有真正被删除!!

所以这不是答案。

【问题讨论】:

  • 实际上你的问题 is 在那里回答了,至少在 cmets 中:“除了 reflog 条目(在 reflog 条目本身被删除之前保持对象存活)之外,所有对象都得到宽限期,默认为 14 天 [...] --prune-all"
  • @o11c 我试过了,git gc --prune=all 没有删除它们..(添加到不起作用的命令列表中)
  • 软重置后不需要添加,索引条目仍然指向相同的位置(软重置不会触及索引)

标签: git


【解决方案1】:

您需要使 reflogs 过期并然后修剪这些提交:

git reflog expire --expire=now --all
git gc --prune=now

正如您所知道的,运行上述任何一个命令都不起作用。您需要按顺序运行

但通常您不需要手动执行此操作 - git 擅长维护这些记录,手动清理它们并不会带来太多好处。

【讨论】:

  • 你的意思是git reflog expire --expire=now --all
  • @Leedehai 是的,这是一个错字。
  • 谢谢!所以git reflog expire 真的只是将提交标记为“过期”,但实际上并没有删除它们?
  • 每一点灰尘落下的那一刻你都会捡起来吗?让 Git 的定期吸尘在碎屑堆积过多之前将其清除,这非常有效。
  • @jthill 是的,我知道,我知道,但是假设我有想要删除的敏感信息
猜你喜欢
  • 1970-01-01
  • 2019-03-11
  • 1970-01-01
  • 2020-05-13
  • 2018-08-27
  • 1970-01-01
  • 2020-06-22
  • 2013-07-19
  • 2017-05-14
相关资源
最近更新 更多