git:如何从 git 历史记录中删除当前不存在的*所有*文件?

Cam*_*son 13 git

我看过几篇关于如何从所有 git 历史记录中删除单个文件的文章和问题。示例:如何从 Git 存储库的提交历史记录中删除/删除大文件?

\n

我想要做的是删除当前不存在于 master 分支头部的所有文件。

\n

我的用例是,我small从一个整体存储库(称为 )中分离出一个较小的存储库(称为monolith)。我想在创建时保留 git 历史记录small,但仅保留相关的git 历史记录。

\n

首先,我small在 GitHub 上创建了一个新的存储库。然后,在我的笔记本电脑上,我将其作为远程名称添加origin-small到我的本地monolith存储库中,并将 master 分支的当前状态推monolith送到origin-small

\n

origin-small然后,我从 中删除了远程monolith,更改了目录,并small从 GitHub 进行了克隆。Voil\xc3\xa0,我有一份原始存储库的副本,monolith及其完整的历史记录。

\n

但是,历史上有大量文件small不再相关,并且它们使存储库变得臃肿。

\n

我想做的是:

\n
    \n
  1. 从 中删除所有不需要的文件small
  2. \n
  3. 运行命令来清除我刚刚删除的文件的整个 git 历史记录。
  4. \n
\n

有没有办法用一个命令来做到这一点?或者我是否需要git filter-branch为每个要删除的文件/目录运行一次?

\n

Cam*_*son 18

我最终使用了git-filter-repo. 警告:此方法无法更新遥控器上的标签(如果有)。

  1. 安装git-filter-repo

    brew install git-filter-repo
    
    Run Code Online (Sandbox Code Playgroud)
  2. 以镜像形式克隆您所需的存储库。

    git clone --mirror <my-repo-url>
    
    Run Code Online (Sandbox Code Playgroud)
  3. 输入存储库目录。

    cd <my-repo-name>
    
    Run Code Online (Sandbox Code Playgroud)
  4. 分析存储库以识别历史记录中但不再存在的所有文件。

    git filter-repo --analyze
    
    Run Code Online (Sandbox Code Playgroud)
  5. analysis输出目录中,将有一个名为 的文件path-deleted-sizes.txt,其中包含在某个时刻提交、后来被删除但仍然存在于 git 历史记录中的所有文件的列表。

    创建一个缺少标题和其他列的新文件。

    tail +3 ./filter-repo/analysis/path-deleted-sizes.txt \
        | tr -s ' ' \
        | cut -d ' ' -f 5- \
        > ./filter-repo/analysis/path-deleted.txt
    
    Run Code Online (Sandbox Code Playgroud)
  6. 清除所有不再存在的文件的 git 历史记录。这还将清理脏提交、删除空提交并为您重新压缩所有内容。

    git filter-repo --invert-paths --paths-from-file ./filter-repo/analysis/path-deleted.txt
    
    Run Code Online (Sandbox Code Playgroud)
  7. 清理./filter-repo目录,否则您将无法推送更改。

    rm -rf ./filter-repo
    
    Run Code Online (Sandbox Code Playgroud)
  8. 将所有引用强制推送到原点。即使命令没有指示,它也会强制推送。此外,它还会更新远程上的所有分支,这很方便。如果您在 GitHub/Bitbucket/等中的某些分支上启用了分支保护,那么您将需要允许强制推送。如果您发现某些引用无法强制推送,您可以随时重新运行此命令。

    git push
    
    Run Code Online (Sandbox Code Playgroud)

  • 这很棒,但是“./filter-repo”应该替换为“.git/filter-repo”,以使其开箱即用。这是 `git-filter-repo` 现在默认放置结果的地方。 (2认同)
  • 实际上,如果您镜像存储库并且没有 .git 文件夹,并且帖子中描述的路径是正确的。 (2认同)