简体   繁体   English

上游项目强制推送到主节点后,如何修复 git 子树?

[英]How do I fix a git subtree after the upstream project force pushed onto master?

I've been experimenting with using git subtree and have run into the following situation.我一直在尝试使用 git 子树并遇到以下情况。

I used git subtree to add an external project to my repo, I intentionally kept all of the history for the upstream project as I want to be able to refer to the project's history and also contribute back to the upstream project later.我使用 git 子树将外部项目添加到我的 repo 中,我有意保留上游项目的所有历史记录,因为我希望能够参考项目的历史记录并稍后回馈上游项目。

As it turns out, another contributor to the upstream project accidentally pushed a large file into the master branch.事实证明,上游项目的另一个贡献者不小心将一个大文件推送到了主分支。 To fix this, the upstream project rewrote history and force pushed onto master.为了解决这个问题,上游项目重写了历史并强制推送到 master。 When creating my "monorepo", I included this commit and I would also like to remove it.在创建我的“monorepo”时,我包含了这个提交,我也想删除它。

How can I update my repository to reflect the new history of the subtree?如何更新我的存储库以反映子树的新历史?

My first attempt was to use filter-branch to completely remove the subtree and all history.我的第一次尝试是使用 filter-branch 完全删除子树和所有历史记录。

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

Once the old version of the subtree was removed, I could re-add the subtree using the new upstream master.删除旧版本的子树后,我可以使用新的上游主节点重新添加子树。 However, this didn't work because for some reason the commit history still shows up in the git log output.但是,这不起作用,因为由于某种原因,提交历史记录仍然显示在 git 日志 output 中。

Update更新

I've wrote up the steps to create a minimally reproducible example.我已经编写了创建最小可重现示例的步骤。

  1. First create an empty git repo.首先创建一个空的 git 存储库。

     git init test-monorepo cd./test-monorepo
  2. Create an initial commit.创建初始提交。

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

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

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

     git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch algodeck' --prune-empty HEAD
  6. Examine git log output, I am expecting to see only my initial commit.检查 git 日志 output,我希望只看到我的初始提交。

     git log
  1. on your repo, cleanup the history of commits for this remote:在您的存储库中,清理此遥控器的提交历史记录:

     git fetch upstream
  2. if one of your own commits has a commit that includes the large file, rewrite your history so that this large file is no longer referenced如果您自己的某个提交有一个包含大文件的提交,请重写您的历史记录,以便不再引用该大文件

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

With these two steps, the big file will not be referenced anymore by any commit in your repo.通过这两个步骤,您的仓库中的任何提交都不会再引用大文件。
It will additionally be deleted from your hard drive at some point in time, when git runs its garbage collector and the expiration delays for dangling blobs has been reached.当 git 运行其垃圾收集器并且已达到悬空 blob 的过期延迟时,它还会在某个时间点从您的硬盘驱动器中删除。


If you have an urgent need to delete this big file ASAP from your hard drive:如果您迫切需要尽快从硬盘中删除这个大文件:

Manually run手动运行

git gc --prune=now

you already got the bad-commit in your history and you need to get rid of it before continuing你已经在你的历史中得到了 bad-commit 并且你需要在继续之前摆脱它

let's assume you got master last commit diverted and haven't been able to do anything else (I really don't have your branches at sight, so I need to assume something to start with)假设您的master last commit 被转移并且无法做任何其他事情(我真的看不到您的分支,所以我需要假设一些事情开始)

you can checkout to the previous commit and push your branch marker 1 step back (or X steps back) which would be harmless in any case and then pull again您可以签出上一个提交并将您的分支标记向后推 1 步(或 X 步),这在任何情况下都是无害的,然后再次拉

eg例如

git checkout master~1
git branch master -f
git checkout master
git pull
  1. git checkout master~1 to checkout master's parent commit, git warns we are off branches git checkout master~1到 checkout master 的父提交,git 警告我们不在分支
  2. git branch master -f to force current checkout to become master again, ie it actually rewinds master branch to its previous commit (or X previous commit), and from here, it doesn't matter whether upstream did a force or not, we can resume normally, or even go back to above step if needed, we can only pull master again, without losing anything from upstream (which for us could be read-only as well, we won't be pushing anything for this) git branch master -f强制当前 checkout 再次成为 master,即它实际上将 master 分支倒回到其上一次提交(或 X 上一次提交),从这里开始,上游是否强制并不重要,我们可以正常恢复,甚至 go 如果需要返回到上述步骤,我们只能再次拉主,而不会丢失上游的任何内容(对我们来说也可以是只读的,我们不会为此推送任何内容)
  3. git checkout master to be on our "rewound" master branch, the same commit we are stepping at, but now being on the branch instead git checkout master在我们的“rewound” master 分支上,我们正在执行相同的提交,但现在在分支上
  4. git pull to pull master again (can be with or without --prune ), if upstream diverted, we'll get back on track from here, if not, we'll get the same we had, if we got the same and was not supposed, perhaps we need to go back to the 1st step above and rewind more commits, eg git checkout master~5 or whatever (as needed) git pull to pull master again(可以带或不带--prune ),如果上游转向,我们将从这里回到正轨,如果没有,我们将得到相同的结果,如果我们得到相同并且是不应该,也许我们需要 go 回到上面的第一步并回退更多提交,例如git checkout master~5或其他(根据需要)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Git 子树 - 项目中我想从上游接收更改的子目录 - Git subtree - a subdirectory in the project that I want to receive changes from upstream 忽略并删除本地Git主服务器中的文件,但强制推送时,更改不会反映在上游/主服务器中 - Ignored and deleted files in local Git master, but changes aren't reflected in upstream/master when force pushed 使用 Git 部署到 Heroku 时,如何解决子树上的“pushed branch tip is behind”? - How do I solve “pushed branch tip is behind” on subtree when deploying to Heroku with Git? 如何强制覆盖我推送并重新设置的git分支? - How do I force the overwriting of a git branch I pushed and rebased? 当我做git merge up / master和git push origin时如何不导入提交消息 - How to not import commit messages when I do git merge upstream/master & git push origin 如何修复我的本地存储库,以便我可以保存尚未推送到主 git 存储库的提交的工作? - How do I fix my local repo so I can save work from commits that haven’t been pushed to the master git repo? 如果我将工作合并到主数据库但没有推送后,有人将新提交提交到git存储库的主数据库,该怎么办? - What shall I do if someone pushed new commits to master of git repository after I merged my work to master but didn't push? 如何强制git始终使用master分支? - How do I force git to always use the master branch? 如何将 git master 分支重置为分叉存储库中的上游分支? - How do I reset the git master branch to the upstream branch in a forked repository? Git:如何删除已经提交,推送并合并到master的分支? - Git: How do I remove a branch that has already been committed, pushed, and merged into master?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM