所以,让我说我有一个10个提交的本地git仓库,有SHA消化0-9所以我的git日志看起来像这样
9 (HEAD -> master)
8
7
6
5
4
3
2
1
0 <- initial commit
我决定提交5-9是垃圾,我想永久从repositoy 和他们引入的磁盘空间中删除它们的所有记录。在一般情况下,我希望我的回购状态与提交4时的状态相同,并且让它像5-9甚至从未发生过。
我知道git reset --hard 4
会使我的repo 显示被重新提交到提交4,但据我所知,这只会将提交master
点更改为9到4但实际上并没有删除任何东西。所有数据仍然存在,如果您知道提交9的SHA,则可以恢复。
我也知道git filter-branch
,但只删除历史记录中的文件,而不是提交。
我尝试过:
git reset --hard 4
git gc --prune=now
但执行此操作后,我的.git
目录的磁盘空间使用量相同或更大,我仍然可以使用git checkout 9
恢复历史记录。为什么git gc --prune=now
不修剪提交5-9?我是否需要使reflog
过期?
如果我有一个包含许多分支,标签,提交,合并和发展历史的复杂仓库,我怎样才能永久地自动删除所有提交,以及它们引入的更改以及它们消耗的磁盘空间,在一定时间后发生。有效地将整个仓库倒回到那个时间并永久销毁在该日期之后发生的所有活动。
答案 0 :(得分:0)
git reset
不会删除内容。它只需更改您的HEAD即可指向您要求的新SHA-1。
我也知道git filter-branch,但只删除了历史记录中的文件,而不是提交。
让我纠正你。
一旦你执行git过滤器分支,它就会更新内容并创建一个新的提交。
旧的提交它仍在您的存储库中。它成为一个悬垂的对象,这意味着有一些内容无法从任何分支到达。
首先阅读这个答案,了解什么是HEAD。
现在您必须使用BFG的git filter-branch
而不是执行git gc
。
...我认为提交5-9是垃圾,我想从存储库和它们引入的磁盘空间中永久删除它们的所有记录
你有几个选择来实现它。这是一个简单的:
# Get back to the desired commit
git checkout <commit> # in your case 4
# now delete the old branch with the 5-9 commits
git branch -D <branch name>
# now create a new branch from commit #4
git checkout -b <branch>
# now you have to clean the leftovers.
# first lets see them (not required just for us to prove that we delete them)
git fsck --full
# now you will get a list of all the "removed" commit.
# lets clean the repo right now.
git gc --aggressive --prune=now
为什么git gc --prune =现在不修剪提交5-9?
它不会删除提交,因为重置只会更改HEAD而不是存储库的内容。
答案 1 :(得分:0)
让我们分一部分......
我知道
git reset --hard 4
会让我的repo似乎被重新提交为4,但据我所知,这只是将提交master
点从9改为4但实际上并没有删除任何东西所有数据仍然存在,如果您知道提交9的SHA,则可以恢复。
这是对的。此外,有两个reflog可以保留指向提交5,6,7,8和9的指针:HEAD
一个,它会记住HEAD
何时指向这些提交(如果HEAD
曾经指出过它们,还有一个master
,它记得master
指向那些提交时(如果master
指向它们 - 我们肯定它指向{{} 1}}因为它在9
之前的位置,但是我们不知道它是否单独指向以前的每一个,或者你是否可能以某种方式将它们全部带入不知何故,例如,来自另一个分支)。
可能有也可能没有指向这些提交的其他分支和/或reflog。
我也知道
reset
,但只删除历史记录中的文件,而不是提交。
这是不正确的,尽管Wolfgang Pauli对其他事情说了些什么,&#34;这是不对的。这甚至都不对!&#34;特别是,这种措辞意味着git filter-branch
删除了东西。它没有:添加新的提交。
Git基本上是围绕添加新内容的想法而构建的,并且永远不会删除任何内容。其中包括git filter-branch
,git commit --amend
和git rebase
:他们添加了新的提交。真正删除过期内容的唯一Git命令是与gc相关的命令(git filter-branch
,git prune
,git reflog expire
,git repack
等等,当然还有{{1本身)。
我已经尝试过:
git prune-packed
但执行此操作后,我的
git gc
目录的磁盘空间使用量相同或更大,我仍然可以使用git reset --hard 4 git gc --prune=now
恢复历史记录。为什么.git
不修剪提交5-9?我是否需要使我的reflog过期?
是
要让旧物体消失,你必须:
git checkout 9
部分) git gc --prune=now
处理最后两个步骤,但不处理第一个步骤。使用--prune=now
清除所有reflog(这是过度杀伤:git gc --prune=now
可能就是你所需要的)。如果你有其他的迷路引用(其他分支,标签,松散的git reflog --expire=now --expire-unreachable=now
或两个,甚至可能是--expire-unreachable
和stash
),你必须手动清理它们。另请注意,ORIG_HEAD
会在CHERRY_PICK_HEAD
中保留原始引用集,并保留所有原始(预过滤后复制)对象。