在新克隆上使用git-filter-repo从git历史中删除文件

jq6vz3qz  于 2023-02-02  发布在  Git
关注(0)|答案(3)|浏览(347)

我使用this answer命令从git history中删除一个包含凭据的文件,我使用的是git 2.35.1和filter-repo 22826 b5 a68 b6,我需要的命令显然是:

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 checkout 了一个新副本,命令成功运行:

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 git@git.example.com: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.

但是我知道在 checkout 之后没有任何东西被推送到这个repo。重复这个过程会有相同的结果。如果我执行git pull来更新它,它会再次失败,并出现this does not look like a fresh clone错误,就回到了我开始的地方。
我绕着这个问题转了几圈,最终克服了所有的错误,却发现这一切对我的回购协议没有任何影响-文件仍然存在。
因此,我的问题是,要使这个过滤过程在新克隆的回购协议上工作,我应该采取哪些具体步骤?

wlp8pajw

wlp8pajw1#

你差一点...
在上一步中你需要git push --force的原因是因为你要清除遥控器上的提交,并用新的提交替换它们,因为你的遥控器已经没有了,跳过第一个强制推送命令,然后你只需要在最后一个推送命令中添加force:

git push --set-upstream origin master --force

**旁注:**我几乎总是喜欢使用--force-with-lease而不是--force,因为它稍微安全一点,因为如果有人在你最后一次获取(或者在这个例子中,克隆)和推送之间添加新的提交到远程分支,你还没有看到,它会出错。直接把它们吹走可能是不礼貌的。当使用--force-with-lease时,如果你遇到错误,就执行git fetch,查看新的提交,然后决定是否可以删除它们。如果可以,然后再次使用--force-with-lease,它会工作(除非新的提交在你获取后的最后一分钟 * 再次 * 出现)。

在这个特殊的例子中,你要重新添加你的远程数据库,你必须先提取,否则--force-with-lease将无法工作,如果是我,我可能会考虑这样做,如果在你克隆的时间和你要强制推送重写的repo之间,远程数据库上可能会出现新的提交。在这种情况下,我会把你的最后一个命令改为以下步骤:

git fetch
# inspect origin/master to see if new commits appeared after your clone
git push --set-upstream origin master --force-with-lease

或者,在你的情况下,一旦你决定重写一个分支,暂时锁定分支(或者删除权限),然后在强制推送后解锁,这样你就可以确定在你完成之前没有人会添加提交。

wrrgggsh

wrrgggsh2#

TTT的回答很有帮助,特别是关于filter-repo执行git init的评论-a问题在于操作的顺序。在它成功之前,我做了很多次,我把它变成了一个脚本,以明确需要什么以及以什么顺序:

#!/usr/bin/env bash
set -xv
git clone git@git.example.com:abc/xyz.git project
cd project
git filter-repo --path auth.json --invert-paths
git remote add origin git@git.example.com:abc/xyz.git
git push --set-upstream origin main --force

在这样做之后,我在更新现有的克隆时遇到了很多问题,但一般来说,这些问题都是通过接受来自远程的所有更改来解决的。

dkqlctbz

dkqlctbz3#

要解决此问题,您需要在运行git-filter-repo之前运行preserve your .git/config file,然后将其恢复为原始状态,例如:

git clone <...> .
cp ./.git/config ../
git filter-repo --invert-paths --path <...>
mv -f ../config ./.git
git push --force --all

相关问题