git - 如果您已经将文件推送到远程分支、 merge 到开发分支并且不是最新提交,如何从 git 中完全删除该文件

标签 git

我看过很多教程解释如何在不同的场景中执行此操作,但似乎其中许多都讨论了最新的提交。所以我需要的是从两个分支中完全删除这个敏感文件:feature-branchdevelop

我该怎么做?

我找到了这个食谱:

git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch path_to_file" HEAD

它适用于我的情况吗?也就是说,它会从所有分支中完全删除这个文件吗?

编辑:

我决定使用 BFG,这是我运行后它给我的输出

bfg --delete-files 'filename_of_the_file_to_delete'

输出:

Found 273 objects to protect
Found 198 commit-pointing refs : HEAD, refs/heads/develop, refs/heads/develop-with-relative-paths, ...

Protected commits
-----------------

These are your protected commits, and so their contents will NOT be altered:

 * commit 7d97ab00 (protected by 'HEAD') - contains 1 dirty file :
    - src/email/filename_of_the_file_to_delete (16.1 KB)

WARNING: The dirty content above may be removed from other commits, but as
the *protected* commits still use it, it will STILL exist in your repository.

Details of protected dirty content have been recorded here :

/Users/albert/Documents/projects/rjx/rjxfp/.git.bfg-report/2020-08-25/21-50-38/protected-dirt/

If you *really* want this content gone, make a manual commit that removes it, and then run the BFG on a fresh copy of your repo.


Cleaning
--------

Found 486 commits
Cleaning commits:       100% (486/486)
Cleaning commits completed in 699 ms.

Updating 7 Refs
---------------

    Ref                                                    Before     After
    --------------------------------------------------------------------------
    refs/heads/develop                                   | e9c3c4ba | 53c5dd39
    refs/heads/feature-icons-for-top-level-cats          | d7dde80c | 377ae820
    refs/heads/feature-user-profile                      | 7d97ab00 | e3b1b336
    refs/remotes/origin/develop                          | e9c3c4ba | 53c5dd39
    refs/remotes/origin/feature-icons-for-top-level-cats | d7dde80c | 377ae820
    refs/remotes/origin/feature-user-profile             | 7d97ab00 | e3b1b336
    refs/stash                                           | 9fc9a356 | 39945789

Updating references:    100% (7/7)
...Ref update completed in 54 ms.

Commit Tree-Dirt History
------------------------

    Earliest                                              Latest
    |                                                          |
    ..........................................................DD

    D = dirty commits (file tree fixed)
    m = modified commits (commit message or parents changed)
    . = clean commits (no changes to file tree)

                            Before     After
    -------------------------------------------
    First modified commit | 6a211a6b | 35597e71
    Last dirty commit     | e9c3c4ba | 53c5dd39

Deleted files
-------------

    Filename                          Git id
    ------------------------------------------------------
    filename_of_the_file_to_delete    | 4121d724 (16.1 KB)


In total, 37 object ids were changed. Full details are logged here:

    /Users/albert/Documents/projects/rjx/rjxfp/.git.bfg-report/2020-08-25/21-50-38

BFG run is complete! When ready, run: git reflog expire --expire=now --all && git gc --prune=now --aggressive

我想要删除的文件仍在创建它的目录中,至少在我运行 bfg 命令的分支上。那么我认为我不完全理解它对某些 protected 脏内容的说法。谁保护它以及为什么? 它说:如果您*真的*希望删除此内容,请手动提交将其删除,然后在存储库的新副本上运行 BFG。

我不明白我到底应该做什么。

据我了解,它提到的提交7d97ab00(现在是e3b1b336)是我运行命令的分支上的最后一次提交,所以我必须删除该文件(但我必须使用 rm 或 git-rm 删除它吗?)然后提交并再次运行 BFG?

最佳答案

虽然我没有使用过 BFG,但我从它的文档中了解到,它认为每个分支的最尖端提交是“正确的状态”。也就是说,假设您想要从每次提交中删除文件 secret.txt。如果您将 BFG 与指令“删除文件 secret.txt”一起使用,它将从所有提交中删除它,除了当前提交(以及任何其他分支提示提交)里面有该文件)。

请记住,分支名称只是通过提交哈希 ID 来标识某些提交。 提交本身中包含文件。每次提交都有每个文件的完整快照。因此,如果您在四次提交前添加了 secret.txt,并且具有以下内容:

... <-H <-I <-J <-K <-L   <--master

其中每个大写字母代表一次提交,文件 secret.txt 位于提交 LKJ 中。它不在 H 中,因为 H5 之前提交的。

这里的向后箭头是 Git 的工作方式:每次提交都会向后引导到上一个提交。任何提交的任何部分都不能更改(BFG 也不能更改),因此 BFG 必须做的是创建新的和改进的提交,然后完全丢弃旧的提交。

BFG 会将现有提交 I 复制到新的改进的 I',其中 secret.txt 不存在。然后,它会将 J 复制到新改进的 J',其中 secret.txt 不存在,并对 重复此操作>K。但 L最后提交,由名称标识,因此 BFG 假设您打算保留 secret.txt 那里,因为它现在就在那里并且由名称标识。这是“ protected ”的提交。因此,BFG 将 L 复制到 L' — 它必须这样做,因为它将 K 复制到 K' 并且现有的 L 指向现有的 K,但这次它将 secret.txt 保留在提交 L' 中.

你最终会得到:

... <-H [ XXX deleted: <-I <-J <-K <-L ]
       \
        I' <-J' <-K' <-L'   <-- master

其中 secret.txt 现在仅存在于 protected 最后一次提交 L' 中。

BFG 的文档建议您这样做:

git rm secret.txt
git commit

在开始之前,以便您开始:

... <-H <-I <-J <-K <-L <-M   <--master

其中新提交M包含secret.txt。现在提交 IL 都可以修复,因为 L 不是最后一个 不再提交。它不是通过名称来识别的。名称 master 找到的不是 L,而是 M;只有 M 本身才能找到 L

注释

一旦您更新了自己的存储库以进行新的和改进的提交,并丢弃了旧的错误提交,您将需要使用git push --force来获取任何< em>其他 Git 仍然拥有并仍在使用旧的错误提交,以切换到新的和改进的提交。

始终假设,如果 secrets.txt 在网络上可用,即使只有几秒钟,有人就会获取它的副本。

关于git - 如果您已经将文件推送到远程分支、 merge 到开发分支并且不是最新提交,如何从 git 中完全删除该文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63584840/

相关文章:

git - 在 Docker 中使用私有(private) gitlab 模块构建 Go 应用程序

git - 在 Azure DevOps 中,cherry pick 是如何工作的

git - 如何将现有的 git 存储库 merge 到一个空的存储库中并保留历史记录?

git - 覆盖 merge 中的本地更改

Git:如何恢复分支中删除的每个文件的最新版本?

git - 为什么 git submodule update 失败并显示 "fatal: remote error: upload-pack: not our ref"?

windows - Windows 上的 Git : Force use of OpenSSH

git - 如何查看特定 git 提交时的文件?

git - 您如何管理项目中的第三人称 git 存储库? (例如 Twig/Assetic/..)

git cherry 采摘到不同的基本目录