示例
因此,假设我有一个本地git与10提交,让SHA消化0-9,所以我的git日志如下所示
9 (HEAD -> master)
8
7
6
5
4
3
2
1
0 <- initial commit
我决定提交5-9是垃圾,我希望永久地从存储库中删除它们的所有记录,并删除它们引入的磁盘空间。我希望我的回购状态与提交4的状态相同,并且让它像5-9从未发生过一样。
我知道git reset --hard 4
会使我的回购看起来被重新卷到提交4,但据我所知,这只是将提交master
点从9更改为4,但实际上并没有删除任何内容。如果您知道commit 9的SHA,那么所有的数据都仍然存在,并且是可以恢复的。
我也知道git filter-branch
,但这只是从历史记录中删除文件,而不是提交。
我试过这样做:
git reset --hard 4
git gc --prune=now
但是这样做之后,我的.git
目录的磁盘空间使用情况是相同或更大的,我仍然可以用git checkout 9
恢复历史。为什么git gc --prune=now
不修剪提交5-9?我需要终止我的reflog
吗?
更广泛地说:
如果我有一个包含多个分支、标记、提交、合并和分叉历史的复杂回购,那么如何永久和自动地删除所有提交、及其引入的更改以及在一定时间后使用的磁盘空间。有效地将整个回购退回到那个时间,并永久销毁该日期之后发生的所有活动。
发布于 2016-05-27 13:09:36
git reset
不删除内容。它只需将您的头更改为指向您所要求的新的SHA-1。
如何删除内容?
我也知道git过滤器分支,但这只是从历史中删除文件,而不是提交。
让我纠正你。
完成git筛选器后,它将更新内容并创建新的提交。
那么旧的承诺在哪里呢?
旧的提交仍然在您的存储库中。它变成了一个悬空的对象,这意味着有一些内容是无法从任何分支访问的。
首先,阅读这个答案来理解什么是头。
现在,您必须使用git filter-branch
of BFG,并且只能执行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 =现在不提交5-9?
它不会删除提交,因为重置只会更改存储库的头,而不是内容。
发布于 2016-05-27 15:21:55
让我们把这个分成几个部分。
我知道
git reset --hard 4
会使我的回购看起来被重新卷到提交4,但据我所知,这只是将提交master
点从9更改为4,但实际上并没有删除任何内容。如果您知道commit 9的SHA,那么所有的数据都仍然存在,并且是可以恢复的。
这是正确的。此外,还有两个可以保留指向提交5、6、7、8和9的指针:一个用于HEAD
,用于HEAD
指向那些提交(如果HEAD
曾经指向它们),另一个用于master
,后者记得master
指出这些提交(如果master
曾经指向它们)--我们知道它确实指向了9
,因为这是在reset
之前的位置,但我们不知道它是否单独地指向了以前的每个提交,或者你可能会以某种方式同时把它们带来,例如,从另一个分支)。
可能有或可能没有指向这些提交的附加分支和/或重浮点。
我也知道
git filter-branch
,但这只是从历史记录中删除文件,而不是提交。
这是不对的,尽管正如沃尔夫冈·保利所说的那样,“这是不对的,这甚至都不是错的!”特别是,这个短语意味着git filter-branch
删除了一些东西。它没有:它添加了新的提交。
Git从根本上讲是围绕着添加新东西的想法而建立的,而且永远不会删除任何东西。这包括git commit --amend
、git rebase
和git filter-branch
:它们添加了新的提交。唯一真正删除过期内容的Git命令是与gc相关的命令(git prune
、git reflog expire
、git repack
、git prune-packed
等,当然还有git gc
本身)。
我试过: git重置-硬4 git gc -修剪=现在 但是这样做之后,我的
.git
目录的磁盘空间使用情况是相同或更大的,我仍然可以用git checkout 9
恢复历史。为什么git gc --prune=now
不修剪提交5-9?我需要结束我的重捕吗?
是。
要使旧的对象消失,您必须:
--prune=now
部分)git gc --prune=now
处理最后两个步骤,但不是第一个步骤。使用git reflog --expire=now --expire-unreachable=now
可以清除所有的重触发器(这太过分了:--expire-unreachable
可能就是您所需要的)。如果您有其他杂乱的引用(其他分支、标记、一两个松散的stash
,甚至是ORIG_HEAD
和CHERRY_PICK_HEAD
之类的东西),则必须手动清理这些引用。还请注意,git filter-branch
保留了.git/refs/original/
中的原始引用集,而这些引用保留了所有原始(预过滤-复制)对象。
https://stackoverflow.com/questions/37484026
复制相似问题