我有一个包含一些提交的本地仓库。因为我想将其公开给其他人,所以我需要将其推送到 Github 上新创建的远程仓库。新创建的远程仓库使用许可证文件进行初始化(因为本地仓库没有许可证文件)。
使用推送git push -u origin main
(我的本地分支也使用main
而不是作为主分支)会由于在远程存储库中添加文件master
而产生错误。license
C:\test>git push -u origin main
To https://github.com/pstricks-fans/test.git
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'https://github.com/pstricks-fans/test.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
然后我按照提示进行如下操作。
C:\test>git pull origin main
From https://github.com/pstricks-fans/test
* branch main -> FETCH_HEAD
fatal: refusing to merge unrelated histories
无法进行合并。
有人告诉我,我必须按照下列步骤重新设定基准。
C:\test>git pull origin main --rebase
From https://github.com/pstricks-fans/test
* branch main -> FETCH_HEAD
Successfully rebased and updated refs/heads/main.
问题
有没有其他无需重新定基的解决方案(出于学习目的)?不建议对公共 repo 进行重新定基(正如 git 文档所述)。
答案1
对于你的最终病史,你有三种选择。
您的本地提交保持不变,而且您还有另一个包含许可证文件的本地提交。一种实现方法是使用
git cherry-pick origin/master
将公共提交重新定位到您的本地分支,然后git push --force-with-lease
用您的分支覆盖公共分支。虽然覆盖公共分支通常是不建议的,但如果还没有其他人真正克隆它,那就不是问题。如您所知,您可以重新设置本地提交的历史记录,以便它们的历史记录现在遵循许可证文件提交的历史记录。
你合并了本地和远程分支,但由于它们没有共同的祖先,Git 担心你可能会犯错误,因此为了确保万无一失,你需要使用
git pull origin main --allow-unrelated-histories
,如这个 Stack Overflow 问题。
答案2
如果你想让许可证文件显示在你所有的现存的提交,那么重新定基(或某种其他形式的历史记录重写)是唯一的选择。如果不更改提交 ID,则无法将文件添加到现有提交中。
(虽然合并本地和 GitHub 初始化的历史记录完全可行,但实际上无法实现这一点——GitHub 提供的文件只会出现在“合并”的提交及以后,但合并不会改变存储库的过去内容。)
如果你只希望许可证文件显示在新的提交(这可能没问题),然后正常地将其添加+提交到您的本地存储库,然后git push --force
提交到 GitHub,丢弃它已初始化的所有内容。
GitHub 的“初始化...”功能仅适用于全新存储库——发布现有存储库时它毫无用处。
答案3
为什么会发生这种情况
git pull
默认情况下会进行合并。但是您的两个main
分支(远程和本地存储库)具有不相关的历史记录(没有共同的祖先),因此合并默认拒绝进行此类合并。
为什么 rebasing 完全没问题
不建议使用 git-rebase(1) 是因为已发布的历史记录,即其他人可以拉取/获取的内容。但你自己的更改仍然是本地的,所以这样做完全没问题
git pull --rebase origin main
git push origin main
因为远程历史记录没有被破坏。
为什么 git-merge(1) 默认不会合并这些历史记录
因为这很可能是一个错误。
显然,当对现有存储库做出贡献时(而不是像您那样创建一个新的存储库),可能会(或至少曾经)意外地创建一个与您打算合并的分支无关的“孤立分支”。
这发生在Linux 内核 [1] 当有人使用 readme 文件创建新的 root 提交时(提交快照仅包含该文件)。这并非作者的本意。[2]
但这种不相关的合并是有时是故意的,比如当你想将整个其他项目合并到你自己的项目时。但这种情况非常罕见,因此
--allow-unrelated-histories
在这种情况下,人们希望提供长期切换。
笔记
git-merge(1)
--allow-unrelated-histories
在 e379fdf34f (合并:默认拒绝创建太酷的合并,2016-03-18)中了解到,当它被教导在没有该开关的情况下禁止此类合并时:合并:默认拒绝创建太酷的合并
虽然允许将两个独立启动的项目的不相关历史合并为一个是合理的,但就像“gitk”合并到“git”本身(又名“有史以来最酷的合并”)一样,这种合并仍然是一种不寻常的事件。更糟糕的是,如果有人从已建立项目的 tarball 开始创建独立历史并向原始项目发送拉取请求,“git merge”却愉快地创建了这样的合并,没有任何不寻常的迹象。
教导“git merge”默认拒绝创建这样的合并,除非用户传递新的“--allow-unrelated-histories”选项来告诉它用户知道有两个不相关的项目被合并。
由于这种“两个项目合并”的情况很少见,因此没有添加始终允许这种合并的配置选项。
[…]