将上游项目推到master上后,如何修复git子树?


13

我一直在尝试使用git子树,并遇到了以下情况。

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

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

如何更新存储库以反映子树的新历史记录?

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

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

一旦删除了旧版本的子树,我就可以使用新的上游母版重新添加子树。但是,这不起作用,因为由于某种原因,提交历史记录仍显示在git日志输出中。

更新资料

我已经写好了创建最小可复制示例的步骤。

  1. 首先创建一个空的git repo。

    git init test-monorepo
    cd ./test-monorepo
    
  2. 创建一个初始提交。

    echo hello world > README
    git add README
    git commit -m 'initial commit'
    
  3. 现在为外部项目添加一个子树。

    git remote add thirdparty git@github.com:teivah/algodeck.git
    git fetch thirdparty
    git subtree add --prefix algodeck thirdparty master
    
  4. 在monorepo上进行一些提交

    echo dont panic >> algodeck/README.md
    git commit -a -m 'test commit'
    
  5. 现在尝试使用git filter-branch删除子树。

    git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch algodeck' --prune-empty HEAD
    
  6. 检查git日志输出,我希望仅看到我的初始提交。

    git log
    

您是否尝试过git gc --prune = now放弃旧的提交?是否有对旧版本提交的引用?
Damiano

1
我还没有尝试过,但是会不会git gc --prune=now只删除未出现在其中的提交git log
csnate19年

使用git branch -all(我想您正在使用它来查看“旧”提交)也应该显示与当前分支无关的提交。
达米阿诺

1
实际上,我只是在做git log,没有任何争论,而且我仍然看到旧的提交。
csnate19年

请您发布git log --pretty --all --graph吗?只是为了了解您的情况
Damiano

Answers:


0

您已经在历史中犯下了错误的承诺,需要先消除它,然后再继续

假设您master上次提交的指令已被转移,并且无法执行其他任何操作(我真的看不到您的分支机构,因此我需要假设有一些开始)

您可以签出到上一个提交,然后将分支标记后退1步(或X退后),这在任何情况下都是无害的,然后再次拉出

例如

git checkout master~1
git branch master -f
git checkout master
git pull
  1. git checkout master~1 检出master的父提交,git警告我们离开了分支机构
  2. git branch master -f 强制当前结帐再次成为主结帐,即实际上将主分支倒回其先前的提交(或X先前的提交),并且从此处开始,上游是否执行强制都无关紧要,我们可以正常恢复,甚至如果需要,请返回上一步,我们只能再次拉动master,而不会从上游丢失任何内容(对我们来说这也可能是只读的,为此我们不会做任何事情)
  3. git checkout master 在我们的“倒带”主分支上,我们正在执行相同的提交,但是现在在分支上
  4. git pull再次拉动主控(可以带或不带--prune),如果上游转向了,我们将从这里重新走回正轨;如果不行,我们将得到与以前一样的东西;如果我们得到了相同的东西并且不应该被认为是,也许我们需要返回到上面的第一步并回退更多的提交,例如git checkout master~5(根据需要)

我认为这git subtree
不适

@csnate可以从子存储库中签出先前的提交,并遵循非常类似的过程,如果您构建MCVE,则告诉您要遵循stackoverflow.com/help/minimal-reproducible-example
arhak

我将尝试在GitHub上创建示例存储库。
csnate

我在显示问题的原始问题中创建了一组步骤。
csnate

0
  1. 在您的仓库中,清除此远程服务器的提交历史:

    git fetch upstream
    
  2. 如果您自己的提交中有一个包含大文件的提交,请重写您的历史记录,以便不再引用该大文件

    # using one or more of the following commands :
    git rebase --interactive
    git filter-branch
    ...
    

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


如果您迫切需要尽快从硬盘驱动器中删除此大文件:

手动运行

git gc --prune=now
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.