git - 在上游项目强制推送到 master 后,如何修复 git 子树?

标签 git subtree

我一直在尝试使用 git subtree 并遇到以下情况。

我使用 git subtree 将一个外部项目添加到我的 repo 中,我故意保留了上游项目的所有历史记录,因为我希望能够引用该项目的历史记录,并在以后为上游项目做出贡献。

事实证明,上游项目的另一个贡献者不小心将一个大文件推送到主分支。为了解决这个问题,上游项目重写了历史并强制推送到 master 上。在创建我的“monorepo”时,我包含了这个提交,我也想删除它。

如何更新我的存储库以反射(reflect)子树的新历史记录?

我的第一次尝试是使用 filter-branch 来完全删除子树和所有历史记录。

git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch upstream-project-dir' --prune-empty HEAD

删除旧版本的子树后,我可以使用新的上游主节点重新添加子树。但是,这不起作用,因为出于某种原因,提交历史记录仍然显示在 git log 输出中。

更新

我已经编写了创建最小可重现示例的步骤。
  • 首先创建一个空的 git 仓库。
    git init test-monorepo
    cd ./test-monorepo
    
  • 创建初始提交。
    echo hello world > README
    git add README
    git commit -m 'initial commit'
    
  • 现在为外部项目添加一个子树。
    git remote add thirdparty git@github.com:teivah/algodeck.git
    git fetch thirdparty
    git subtree add --prefix algodeck thirdparty master
    
  • 在 monorepo 上做一些提交
    echo dont panic >> algodeck/README.md
    git commit -a -m 'test commit'
    
  • 现在尝试使用 git filter-branch 删除子树。
    git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch algodeck' --prune-empty HEAD
    
  • 检查 git log 输出,我希望只看到我的初始提交。
    git log
    
  • 最佳答案

  • 在你的 repo 上,清理这个远程的提交历史:
    git fetch upstream
    
  • 如果您自己的一个提交包含包含大文件的提交,请重写您的历史记录,以便不再引用该大文件
    # using one or more of the following commands :
    git rebase --interactive
    git filter-branch
    ...
    

  • 通过这两个步骤,您的存储库中的任何提交将不再引用大文件。
    它还会在某个时间点从您的硬盘驱动器中删除,当 git 运行其垃圾收集器并且已达到悬空 blob 的过期延迟时。

    如果您迫切需要尽快从硬盘中删除这个大文件:

    手动运行
    git gc --prune=now
    

    关于git - 在上游项目强制推送到 master 后,如何修复 git 子树?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58750777/

    相关文章:

    Java XPath API - 获取表示子树的字符串

    python - 有没有比标准 "recursive"更快的方法从 python 中的树状结构获取子树?

    Git 在将更新 merge 到我的子树时感到困惑

    git - merge 具有不同行尾字符的文件

    java - 多模块(multi scm)gradle项目开发

    git - 如何将 git 存储库的 COPY(存档,而不是克隆)连接到其远程?

    windows - Windows下的Git Hook

    git - 如何使用 GitLab CI/CD 获取整个存储库?