我在github上托管了一个存储库,用于开发一些代码,我们称之为https://github.com/foo/bar.git.
在另一个完全独立的本地存储库中,我开发了一些其他代码。现在我想将此本地存储库的内容推送到https://github.com/foo/bar.git,完全替换旧内容(分支、标签等)。如何实现这一点?
我知道我可以简单地删除github上的repo并创建一个新的repo,但我想避免这种情况。
我在本地repo中设置了远程URL。我也做了git push
,但这导致新内容与原始内容共存(例如,由于main
与master
分支不匹配)。有办法解决它吗?
由于您现在有一个
main
,而替换存储库中没有master
,因此您可能希望GitHub设置名称main
,而不是名称master
。然后,您可能希望完全删除旧名称master
,但在执行此操作之前,您可能需要告诉GitHub更改他们对GitHub侧存储库的默认分支的概念,因为您无法删除建议的克隆默认分支名称。或者,您可能希望在远程设备上继续使用名称
master
。如果是,则需要决定是否在自己的本地存储库中重命名分支。简单的方法是git branch -m main master
,然后根据需要强制推送。
要执行前者(将GitHub分支名称切换为main
),您可以从开始
git remote add origin https://github.com/foo/bar.git
git push -u origin main
这会将与现有提交没有关系的新提交(如果不是全部的话)发送到GitHub,然后要求GitHub端软件在那里创建一个新的分支名称main
。成功后,它将本地main
的上游设置为新创建的origin/main
。
现在main
已经存在,您可以使用GitHub网页或gh
cli命令将那里的默认分支名称设置为main
:
gh repo edit --default-branch main
(或者使用浏览器和常见的点击按钮)。
更多
您可能还想删除GitHub端所有现有的标记和其他分支名称,然后为任何新的分支和标记名称创建新的名称。
你可以——但不必;请参阅下文——使用git push --delete
删除GitHub的所有分支和标记名称,除了您刚刚创建的新main
或刚刚更新的master
。要获得此类名称的列表,请考虑使用:
git ls-remote origin
这会把它们全部泄露出去(你可能想把它重定向到一个可以编辑的文件)。请确保过滤掉名称HEAD
和main
。您可以为带有或不带有refs/heads/
和refs/tags/
前缀的单个git push origin --delete
提供剩余名称,例如:
git push origin --delete br1 br2 master tag1 tag2 tag3
现在,如果您有更多的分支和/或标记名称要设置,您可以使用一个git push
同时完成所有这些操作,例如:
git push -u origin newbr1 newbr2 newtag1 newtag2
(注意:我实际上不确定-u
在推送标记时是否正确工作;如果它会引起问题,请考虑将其拆分为两个单独的git push
命令,一个用于带-u
的分支名称,另一个用于不带-u
的标记名称)。
作为一条捷径,可以考虑:
git push --mirror origin
--mirror
选项将删除而非推送的名称,并尝试推送(使用--force
)所有分支和标记名称。因此,这应该涵盖";删除旧名称";以及";更新新的";。不过,我认为这不能与-u
相结合。您可以在之后运行git fetch
,根据需要创建origin/*
名称,然后执行一系列git branch --set-upstream-to
命令(很容易编写脚本)。
如果您有任何受保护的分支名称,您可能需要在执行所有这些操作之前解除对它们的保护。
洞穴
从GitHub端存储库中删除分支名称会导致无法找到旧的提交。然而,它实际上并没有删除这些提交。GitHub有一个内部保留策略(由于与GitHub分叉有关的内部原因),即永远保留此类提交,而不是Git典型的本地30或90天的到期期。(你可以要求支持人员清除死提交,就像你可能对包含敏感数据的提交所做的那样。不过,我不确定这种情况的政策是什么。)
所有这些都意味着(a)完全删除你的GitHub端存储库要容易得多;(b) 这样做可能会为GitHub本身节省一些磁盘空间,尤其是在没有私有存储库分支的情况下。因此,我不会麻烦以更复杂的存储库保留方式来做这件事。当然,删除和重新创建存储库也会破坏只有GitHub的问题、PR等数据库,这可能是一个考虑因素。