如何用不相关的历史替换远程存储库内容?

How to replace remote repository content with unrelated history?

我在 github 上托管了一个存储库,我用它来开发一些代码,我们称它为 https://github.com/foo/bar.git

在另一个完全独立的本地存储库中,我开发了一些其他代码。现在我想把这个本地仓库的内容推送到https://github.com/foo/bar.git,完全替换旧的内容(分支、标签等)。我该如何实现?

我知道我可以简单地删除 github 上的回购并创建一个新的,但我想避免这种情况。

我在本地仓库中设置了远程 URL。我也做了 git push,但这导致新内容与原始内容共存(例如,由于 mainmaster 分支不匹配)。有办法解决吗?

大体上是正确的,但遗漏了几个注释:

  • 由于您现在有一个 main 而替换存储库中没有 master,您可能希望 GitHub 设置名称 main,而不是名字 master。那么你可能想要 删除 名称 master 完全,但在你这样做之前,你可能需要告诉 GitHub 为您的 GitHub-side 存储库更改 默认分支 的概念,因为您无法删除克隆的推荐默认分支名称。

  • 或者,您可能希望在遥控器上继续使用名称 master。如果是这样,您将需要决定是否重命名您自己的本地存储库中的分支。简单的事情是 git branch -m main master 然后根据需要 force-push。

做前者(将GitHub分支名称切换为main),你可以从:

开始
git remote add origin https://github.com/foo/bar.git
git push -u origin main

这会将(如果不是全部的话)你的新提交发送到 GitHub,然后要求 GitHub-side 软件创建一个新分支名称 main 在那里。成功后,它将本地 main 的上游设置为新创建的 origin/main.

现在那里已经有了main,你可以使用GitHub网页或者gh cli command设置那里的默认分支名称为main

gh repo edit --default-branch main

(或使用浏览器和通常的点击按钮)。

更多

您可能还想删除 GitHub 端的所有现有标签和其他分支名称,然后为任何新分支和标签名称创建新的。

你可以——但不是必须;见下文—使用 git push --delete 删除 GitHub 拥有的所有分支和标签名称,除了您刚刚创建的新 main 或您刚刚更新的 master。要获取此类名称的列表,请考虑使用:

git ls-remote origin

这会将它们全部溢出(您可能希望将其重定向到您可以编辑的文件)。请务必过滤掉名称 HEADmain。您可以将剩余的名称提供给单个 git push origin --delete,带或不带 refs/heads/refs/tags/ 前缀,例如:

git push origin --delete br1 br2 master tag1 tag2 tag3

现在,如果您要设置更多的分支 and/or 标记名称,您可以一次完成,再设置一个 git push,例如:

git push -u origin newbr1 newbr2 newtag1 newtag2

(注意:我实际上不确定 -u 在推送标签时是否正常工作;如果它导致问题,请考虑将其拆分为两个单独的 git push 命令,一个用于分支名称 -u 和一个没有 -u).

的标签名称

作为 short-cut,考虑:

git push --mirror origin

--mirror 选项将 删除 名称 而不是 推送,并将尝试推送(使用 --force ) 所有分支和标记名称。所以这应该涵盖“删除旧名称”和“更新新名称”。不过,我认为这不能与 -u 结合使用。您可以改为 运行 git fetch 之后,根据需要创建 origin/* 名称,然后执行一系列 git branch --set-upstream-to 命令(很容易编写脚本)。

如果您有任何受保护的分支名称,您可能需要在执行所有这些操作之前 un-protect 它们。

警告

从您的 GitHub-side 存储库中删除 分支名称 会使那里的旧 提交 un-find-able。但是,它实际上并没有删除 那些提交。 GitHub 有一个内部保留政策(由于与 GitHub 分叉有关的内部原因)永远 保留此类提交,而不是 Git典型的本地 30 或 90 天有效期。 (您可以要求支持人员清除死提交,就像您可能对包含敏感数据的提交所做的那样。不过,我不确定针对这种情况的政策是什么。)

所有这些意味着 (a) 更容易 完全 删除 您的 GitHub-side 存储库; (b) 这样做可以 GitHub 自己节省一些磁盘空间 space,尤其是在您的私有存储库没有复刻的情况下。所以我不会费心用更复杂的 repository-retaining 方式来做这件事。当然,删除和re-creating仓库也会破坏GitHub-only问题、PR等数据库,可以考虑一下。