从git仓库中删除'.git'目录?

27

我正在尝试将一个git仓库从Kiln迁移到Github。我可以成功地添加新的远程仓库,但是当我尝试将主分支推送到新的远程仓库时,会出现以下错误:

Counting objects: 8691, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3000/3000), done.
remote: error: object a9ee490ac00987835de30bdbc851da5e8d45d28b:contains '.git'
remote: fatal: Error in object
error: pack-objects died of signal 13
error: failed to push some refs to 'git@github.com:Account/repo.git'

提交记录 a9ee490ac00987835de30bdbc851da5e8d45d28b 包含以下文件:

.git/
CHANGELOG.md
JSONKit.h
JSONKit.m
README.md

显然,过去的某个人使用 hg 在子目录中检入了一个完整的 git 存储库。

我想彻底删除那个目录,但是在从 git 历史记录中删除该文件时遇到了问题。

在推送 git 存储库时出现错误:包含 '.git' 的答案没有帮助,因为我已经将存储库作为 git 存储库,而不是 mercurial 存储库。

我尝试了 git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch .git',但是我得到了这个错误:

Rewrite 7dbd0970d6c79215d11994b4a9b8091b2e954cfb (326/442)error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/HEAD'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/config'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/description'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/hooks/applypatch-msg.sample'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/hooks/commit-msg.sample'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/hooks/post-update.sample'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/hooks/pre-applypatch.sample'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/hooks/pre-commit.sample'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/hooks/pre-rebase.sample'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/hooks/prepare-commit-msg.sample'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/hooks/update.sample'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/index'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/info/exclude'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/logs/HEAD'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/logs/refs/heads/master'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/objects/pack/pack-43fac03d375df5c1e380c5e522ba6bcb9b4e1ec1.idx'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/objects/pack/pack-43fac03d375df5c1e380c5e522ba6bcb9b4e1ec1.pack'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/packed-refs'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/refs/heads/master'
error: Invalid path 'Account/Libraries/ShareKit/Submodules/JSONKit/.git/refs/remotes/origin/HEAD'

历史似乎没有被改变。我已经达到了我的git知识极限。有人可以帮忙吗?


这个仓库是开源的吗?您能分享一份副本吗? - Roberto Tyley
啊,不需要分享相关的 repo 副本,我已经成功构建了一个带有类似错误树的 Git 仓库,可以用于测试目的。 - Roberto Tyley
可能是重复问题:推送 Git 存储库失败,错误为:“包含 '.git'” - Laurens Holst
谢谢@dana!我现在正面临着完全相同的问题(.git文件夹之前错误地添加到hg仓库中)。 - Per Lundberg
5个回答

39
使用BFG Repo-Cleaner,这是一个更简单、更快速的选择,专门用于从Git历史记录中删除文件。请按照此处的步骤仔细操作:https://rtyley.github.io/bfg-repo-cleaner/#usage - 但核心部分只需要下载BFG jar(需要Java 8或以上版本),然后运行以下命令即可:
$ java -jar bfg.jar --delete-folders .git --delete-files .git --no-blob-protection my-repo.git

您的整个存储库历史记录将被扫描,并删除任何名为.git的文件或文件夹。我已针对一个特别构建的测试资料库(包含一个.git文件夹)进行了测试,它完全正常运行。
感谢Michel Jouvin 提醒我,在Git中,以'.git'命名的文件也是非法的(Git报告的错误消息并不立即表明它们是文件而不是文件夹),因此我更新了这个答案来反映这一点。 完整披露:我是BFG Repo-Cleaner的作者。

我曾经遇到过同样的问题,而这个解决方案对我很有帮助。 - Marek Dzikiewicz
1
谢谢!我也遇到了完全相同的问题,这个解决方案救了我的命。如果可以的话,我会将其标记为正确答案。 - Jan Segre
1
我尝试了git filter-branch方法,但它没有起作用,但使用bfg repo-cleaner却非常成功。谢谢! - omarshammas
1
第一次使用就成功了,非常感谢这个优秀的工具,Roberto! - John Walthour
1
这对我有用。非常感谢。BFG工具完成了任务。 - jbobbylopez
显示剩余2条评论

2
从 git 2.2.22 开始,使用 git-filter-repo 工具可以完成此操作。
简单快捷:
git filter-repo --force --invert-paths --path-glob '*/.git' --path '.git'

运行得非常好,谢谢!对我来说,一个18-GB的仓库只需要4.5分钟。 - Trevor

1
另一种处理Mercurial(Hg)存储库中嵌入了.git文件夹的情况的方法是,在导出到Git之前先“修复”Hg存储库。@laurens-holst有一个很好的方法来做这件事。
如果.git文件夹在项目根目录中,则创建一个名为my-filemap的文本文件,其内容如下:
exclude ".git"

在你的.hgrc文件中启用Convert扩展:

[extensions]
convert =

然后使用Hg转换扩展过滤掉.git文件夹:
hg convert --filemap my-filemap originalrepo newrepo

现在你可以从新的仓库中导出,不会再有嵌入的.git文件夹的问题。 在推送之前,您还可以使用git fsck确保新的Git仓库没有问题。

1
你尝试过使用以下命令吗?
git filter-branch --tree-filter 'rm -Rf .git' HEAD

git filter-branch documentation指出这比--index-filter慢,但它可以完成任务。


1
很遗憾,我认为这种方法行不通——在我构建的测试repo上运行,这是我得到的输出:$ git filter-branch --tree-filter 'rm -Rf foo/.git' HEAD ..... 重写6652877677cf01a7b668704134d5e8bb62bfe317 (6/6)错误:无效路径“foo/.git/folder/zero” 错误:无效路径“foo/.git/hero” 错误:无效路径“foo/.git/zero” 忽略路径foo/.git/folder/zero 忽略路径foo/.git/hero 忽略路径foo/.git/zero警告:Ref 'refs/heads/master'未更改 - Roberto Tyley
看起来即使使用“git filter-branch --tree-filter”,也存在@dana在问题中遇到的问题。我认为现在使用The BFG可能是一个更好的选择。 - Roberto Tyley

0
据我所知,现在Kiln可以让你将存储库克隆为git或Mercurial,因此请将其克隆为Mercurial,使用您已经找到的Mercurial文件映射解决方案将该Mercurial存储库作为新存储库推送到Kiln,然后将其作为git克隆下来。然后,您将拥有一个可以推送到GitHub的git存储库。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接