我检查了一大堆文件到一个分支并合并,然后不得不删除它们,现在我留下了一个大的.pack文件,我不知道如何摆脱它。
我使用git rm -rf xxxxxx
删除了所有文件,并且我也运行了--cached
选项。
有人可以告诉我如何删除当前位于以下目录中的大型.pack文件:
.git/objects/pack/pack-xxxxxxxxxxxxxxxxx.pack
我是否只需要移除我仍然拥有但不再使用的分支?或者还有其他我需要运行的东西吗?
我不确定它有多大的不同,但它显示了一个挂锁文件。
由于
修改
以下是我的bash_history的一些摘录,它应该让我知道我是如何设法进入这种状态的(假设我在这一点上工作的是一个名为' my-branch'的git分支。我有一个包含更多文件夹/文件的文件夹):
git add .
git commit -m "Adding my branch changes to master"
git checkout master
git merge my-branch
git rm -rf unwanted_folder/
rm -rf unwanted_folder/ (not sure why I ran this as well but I did)
我以为我也运行了以下内容,但它与其他人一起出现在bash_history中:
git rm -rf --cached unwanted_folder/
我还以为我运行了一些git命令(比如git gc
)来尝试整理包文件,但它们也不会出现在.bash_history文件中。
答案 0 :(得分:156)
问题是,即使您删除了文件,它们仍然存在于以前的版本中。这就是git的重点,即使你删除了某些东西,你仍然可以通过访问历史记录来恢复它。
您要做的事情称为重写历史记录,它涉及git filter-branch
命令。
GitHub在其网站上对此问题有一个很好的解释。 https://help.github.com/articles/remove-sensitive-data
为了更直接地回答您的问题,您基本上需要运行的是unwanted_folename_or_folder
替换此命令:
git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch unwanted_folename_or_folder' --prune-empty
这将从存储库的活动历史记录中删除对文件的所有引用。
接下来,执行GC循环以强制对文件的所有引用都过期并从packfile中清除。在这些命令中不需要替换任何内容。
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --aggressive --prune=now
答案 1 :(得分:6)
一个选项:
手动运行git gc
以将多个包文件压缩为一个或几个包文件。
此操作是持久的(即大包文件将保留其压缩行为),因此使用git gc --aggressive
定期压缩存储库可能是有益的
另一种选择是将代码和.git保存在某处,然后删除.git并使用此现有代码重新启动,创建一个新的git存储库(git init
)。
答案 2 :(得分:5)
方案A :如果您的大型文件仅添加到分支机构,则无需运行git filter-branch
。您只需要删除分支并运行垃圾收集:
git branch -D mybranch
git reflog expire --expire-unreachable=all --all
git gc --prune=all
方案B :但是,根据您的bash历史记录,您确实将更改合并到master中。如果您尚未与任何人分享更改(尚未git push
)。最简单的方法是将master重新设置为与具有大文件的分支合并之前。这将消除分支中的所有提交以及合并后对master进行的所有提交。因此,您可能会失去更改 - 除了大文件 - 您可能真正想要的更改:
git checkout master
git log # Find the commit hash just before the merge
git reset --hard <commit hash>
然后运行方案A中的步骤。
方案C :如果您希望保留合并后,主服务器上的分支或发生了其他更改,则最好将主服务器和选择性服务器进行更改包括你想要的提交:
git checkout master
git log # Find the commit hash just before the merge
git rebase -i <commit hash>
在编辑器中,删除与添加大文件的提交相对应的行,但保留其他所有内容。保存并退出。您的主分支应该只包含您想要的内容,而不包含大文件。请注意,git rebase
没有-p
将会消除合并提交,因此您将在<commit hash>
之后留下母版的线性历史记录。这可能对您有好处,但如果没有,您可以尝试-p
,但git help rebase
说combining -p with the -i option explicitly is generally not a good idea unless you know what you are doing
。
然后运行方案A中的命令。
答案 3 :(得分:2)
正如loganfsmyth在他的answer中已经说过的那样,你需要清除git历史记录,因为文件在从repo中删除后仍然存在。官方GitHub文档recommend BFG我觉得比filter-branch
更容易使用:
Download BFG来自他们的网站。确保安装了Java,然后创建镜像克隆并清除历史记录。请务必将YOUR_FILE_NAME
替换为您要删除的文件的名称:
git clone --mirror git://example.com/some-big-repo.git
java -jar bfg.jar --delete-files YOUR_FILE_NAME some-big-repo.git
cd some-big-repo.git
git reflog expire --expire=now --all && git gc --prune=now --aggressive
git push
与上述相同,但使用--delete-folders
java -jar bfg.jar --delete-folders YOUR_FOLDER_NAME some-big-repo.git
BFG还允许更加漂亮的选项(参见docs),如下所示:
从历史记录中删除所有大于100M的文件:
java -jar bfg.jar --strip-blobs-bigger-than 100M some-big-repo.git
运行BFG时,请注意YOUR_FILE_NAME
和YOUR_FOLDER_NAME
确实只是文件/文件夹名称。 他们不是路径 ,所以foo/bar.jpg
之类的东西不起作用!相反,所有具有指定名称的文件/文件夹都将从回购历史记录中删除,无论它们存在哪个路径或分支。
答案 4 :(得分:1)
我对节目有点迟,但如果上述答案没有解决问题,那么我找到了另一种方式。只需从.pack中删除特定的大文件即可。我有这个问题,我偶然检查了一个2GB的大文件。我按照此链接中说明的步骤进行操作:http://www.ducea.com/2012/02/07/howto-completely-remove-a-file-from-git-history/
答案 5 :(得分:0)
运行以下命令,将PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA
替换为要删除文件的路径,而不仅仅是文件名。这些参数将:
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA" --prune-empty --tag-name-filter cat -- --all
这将从存储库的活动历史记录中强行删除对文件的所有引用。
下一步,执行GC循环,以强制对文件的所有引用都过期并从打包文件中清除。这些命令不需要替换。
git update-ref -d refs/original/refs/remotes/origin/master
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --aggressive --prune=now
答案 6 :(得分:-3)
与编码相比,这更是一种方便的解决方案。压缩文件。以文件视图格式打开zip(与解压缩不同)。删除.pack文件。解压缩并替换文件夹。奇迹般有效!