在新克隆上使用 git-filter-repo 从 Git 历史记录中删除文件
我按照这个答案从 Git 历史记录中删除包含凭据的单个文件。我有 Git 2.35.1 和 Git filter-repo 22826b5a68b6。我需要的命令显然是:
git-filter-repo --path auth.json --invert-paths
如果我尝试将其应用到我的工作存储库,我会收到此错误:
Aborting: Refusing to destructively overwrite repo history since
this does not look like a fresh clone.
(expected freshly packed repo)
因此,我使用 git clone 查看新副本,并且命令成功运行:
Parsed 861 commits
New history written in 0.69 seconds; now repacking/cleaning...
Repacking your repo and cleaning out old unneeded objects
HEAD is now at 7212384 Update app.css
Enumerating objects: 8203, done.
Counting objects: 100% (8203/8203), done.
Delta compression using up to 24 threads
Compressing objects: 100% (2310/2310), done.
Writing objects: 100% (8203/8203), done.
Total 8203 (delta 5630), reused 8196 (delta 5623), pack-reused 0
Completely finished after 2.85 seconds.
我可以看到该文件已被删除。但是当我去推送时:
git push --force
fatal: No configured push destination.
由于某种原因,它丢失了从中克隆的遥控器,所以我手动将其添加回来:
git remote add origin [email protected]:abc/xyz.git
这失败了:
fatal: The current branch master has no upstream branch.
所以我添加了
git push --set-upstream origin master
但这也失败了:
To git.example.com:abc/xyz.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to 'git.example.com:abc/xyz.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
但我知道没有任何东西被推送到这个自从签出以来就一直在存储库中。重复该过程会得到相同的结果。如果我执行 git pull 来更新它,它会再次失败,并出现 this does not look like a fresh clone
错误,就回到我开始的地方。
我绕了好几次,最终克服了所有错误,却发现这对我的存储库没有任何影响——文件仍然在那里。
要使此过滤过程在新克隆的存储库上运行,我应该执行哪些具体步骤?
I'm following this answer to remove a single file containing credentials from Git history. I have Git 2.35.1 and Git filter-repo 22826b5a68b6. The command I need is apparently:
git-filter-repo --path auth.json --invert-paths
If I try to apply this to my working repository, I get this error:
Aborting: Refusing to destructively overwrite repo history since
this does not look like a fresh clone.
(expected freshly packed repo)
So I check out a fresh copy with git clone
, and the command runs successfully:
Parsed 861 commits
New history written in 0.69 seconds; now repacking/cleaning...
Repacking your repo and cleaning out old unneeded objects
HEAD is now at 7212384 Update app.css
Enumerating objects: 8203, done.
Counting objects: 100% (8203/8203), done.
Delta compression using up to 24 threads
Compressing objects: 100% (2310/2310), done.
Writing objects: 100% (8203/8203), done.
Total 8203 (delta 5630), reused 8196 (delta 5623), pack-reused 0
Completely finished after 2.85 seconds.
And I can see that the file has been removed. But when I go to push:
git push --force
fatal: No configured push destination.
For some reason it's lost the remote it cloned from, so I add it back in manually:
git remote add origin [email protected]:abc/xyz.git
This fails with:
fatal: The current branch master has no upstream branch.
so I add that with
git push --set-upstream origin master
But this fails too:
To git.example.com:abc/xyz.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to 'git.example.com:abc/xyz.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
But I know that nothing has been pushed to this repository since checking it out. Repeating the process has the same result. If I do a git pull
to update it, it then fails again with the this does not look like a fresh clone
error, right back where I started.
I went round and around this a few times, eventually getting past all the errors, only to find that it has all made no difference to my repository—the file is still there.
What are the exact steps I should do to make this filtering process work on a freshly cloned repository?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您已经非常接近了...
您需要在上一步中使用 git push --force 的原因是因为您将删除远程上的提交并将其替换为新的提交。由于您的遥控器不见了,请跳过第一个强制推送命令,然后您只需在最后的推送命令中添加强制即可:
旁注: 我几乎总是喜欢使用
--force-with -lease
优于--force
,因为它稍微安全一些,因为如果有人在您上次获取(或者在本例中是克隆)之间向远程分支添加了新提交,则会出错)并推动,你还没有看到。直接把他们吹走可能是不礼貌的。使用--force-with-lease
时,如果出现错误,只需执行git fetch
,查看新提交并决定是否可以删除它们。如果是,请再次使用--force-with-lease
,它将起作用(除非在提取后的最后一分钟再次出现新的提交)。在这种特殊情况下,您要重新添加遥控器,您必须首先获取,否则
--force-with-lease
将不起作用,如果是我的话如果在您克隆的时间和您即将强制推送重写的存储库之间有可能在远程上出现新的提交,我可能会考虑这样做。在这种情况下,我会将您的最终命令更改为以下步骤:或者,也许在您的情况下,一旦您决定要重写分支,请暂时锁定该分支(或删除对其的权限),然后在之后解锁它你的推力。然后您就可以确定在您完成之前没有人会添加提交。
You were so close...
The reason you need to
git push --force
in the previous step is because you are going to blow away commits on the remote and replace them with your new ones. Since your remote is gone, skip the first force push command, and then you simply need to add force to your final push command:Side Note: I almost always prefer using
--force-with-lease
over--force
, as it's slightly safer in that it will error if someone added new commits to the remote branch between the time when you last fetched (or in this case, cloned) and pushed, that you haven't seen yet. It might be rude to just blow them away. When using--force-with-lease
if you get the error, just dogit fetch
, look at the new commits and decide if you're OK with deleting them. If you are, then use--force-with-lease
again and it will work (unless new commits appeared again in the last minute since you fetched).In this particular case where you are re-adding your remote, you must fetch first or else the
--force-with-lease
will not work, and if it were me I would probably consider doing this if there was a possibility of new commits appearing on the remote between the time you cloned and when you are about to force push your rewritten repo. In that case I would change your final command to these steps:Or, perhaps in your case, as soon as you decide you're going to rewrite a branch, temporarily lock the branch (or remove permissions to it), and unlock it after your force push. Then you know for sure no one is adding commits until you're done.
TTT 的回答很有帮助,特别是关于filter-repo执行
git init
的评论;问题出在操作顺序上。在它起作用之前我做了很多次,我把它变成了一个脚本,以明确需要什么以及按什么顺序:这样做之后,我在更新现有克隆时遇到了很多问题,但通常它们是通过接受解决的所有更改均来自远程。
TTT's answer helped, in particular the comment about filter-repo doing a
git init
; it was the order of operations that was the problem. I did this so many times before it worked, and I turned it into a script to make it clear exactly what's needed and in what order:After doing this, I ran into lots of issues updating existing clones, but generally they were solved by accepting all changes from the remote.