【发布时间】:2023-04-10 11:33:01
【问题描述】:
几年前我镜像了一个 GitHub 项目。本项目参与了盛大的“master”到“main”分支的更名。我有一段时间没碰我的叉子了,我的叉子里有一个分支,还有我的叉子的本地副本。但是我的 fork 和特殊分支是基于源项目使用“master”时的!如何将我的 fork 转换为使用“main”,包括同步到源的“main”?
【问题讨论】:
几年前我镜像了一个 GitHub 项目。本项目参与了盛大的“master”到“main”分支的更名。我有一段时间没碰我的叉子了,我的叉子里有一个分支,还有我的叉子的本地副本。但是我的 fork 和特殊分支是基于源项目使用“master”时的!如何将我的 fork 转换为使用“main”,包括同步到源的“main”?
【问题讨论】:
分支名称在 Git 中没有实际意义,可以随时更改。因此,尽管这只是简单的部分,但其中一些工作就是输入您自己的克隆并将它们的 master 重命名为 main。
包括同步到源的“主”?
我们将把它留到最后。
GitHub 上的“fork”本质上是具有一些额外功能的克隆。从这里开始,我将使用术语“fork”来指代 GitHub 克隆,并使用术语“克隆”或“您的克隆”来指代本地克隆。
(这些说明适用于其他人:您提到您已经有一个本地克隆。)
GitHub 不提供直接重命名分支的方法,所以如果你想在你的 fork 中重命名一个分支,你必须先将它克隆到你自己的机器本地:
git clone --no-checkout <url>
(例如,url 是ssh://git@github.com/name/repo.git、git@github.com:name/repo.git 或https://github.com/name/repo.git 之一)在您自己的机器上进行本地克隆。你需要为那台机器安装 Git。注意:我们正在使用--no-checkout,因此您的新克隆还有no 分支。你有所有的提交,并且没有分支。
输入你刚刚创建的克隆:
cd repo
例如。您的克隆将有一个远程跟踪名称origin/master,您可以使用它在您的 GitHub 克隆中创建一个新名称:
git push origin origin/master:main
您的 GitHub 分支现在对于同一个提交有两个不同的名称:master 和 main。您现在可以通过 Web 界面或命令行删除 GitHub fork 的 master:
git push origin --delete master
由于我们使用--no-checkout 创建了这个克隆,我们现在可以运行:
git checkout main
在本地创建分支名称main,并将origin/main 设置为其上游。
您的本地克隆可能已经有一个master。让我们确保你的 fork 是最新的:
cd my-local-clone
git fetch origin # if needed
git checkout master # if needed
git rebase origin/master # if needed
git branch -m master main
现在我们只需要在 GitHub 上创建名称 main,与上面的示例相同,但我们将使用本地的 main 来执行此操作,因为它有点短:
git push -u origin main && git push origin --delete master
我们可以使用-u 选项来更新我们的本地main 以引用origin/main,这完成了除了在fork 中删除名称master 之外的所有操作(参见上面的脚注1),所以我们这样做了有一个单独的步骤。
我不确定 GitHub 是否有任何智能功能可以在您删除名称 master 时自动执行此操作。我的猜测是他们没有。 (我还没有用我的任何叉子尝试过。)This web page also implies that they don't. 你需要进入设置页面并选择main 作为默认分支。
完成此操作后,使用git remote set-head 更新本地克隆不是一个坏主意:
git remote set-head origin --auto
这将使您的origin/HEAD 反映新的origin/main 设置。
(所有这些都是可选的,它们只是使一些非致命但奇怪的错误情况消失。)
现在是时候更新您自己的分叉了。这是困难的部分,因为:
我有一段时间没碰我的叉子了,我的叉子里有一个分支......
您必须在此处准确确定要更新的内容以及更新方式。要记住的关键是 Git 不关心分支名称。它只关心提交。使用 git log --graph 或一些 commit-graph-viewer 来查看提交及其相互之间的关系。
您需要为您的分支上游的分支命名 - 您在创建 GitHub 分支时使用的 GitHub 克隆。它的标准名称是upstream。 (我觉得这个名字有点混乱,因为每个分支也可以有一个上游集,谈论分支 X 的上游设置以及谈论远程命名为上游的东西有点奇怪,但让我们运行暂时。)
您可能已经为此命名。使用git remote 或git remote -v 查看您现有的远程名称。假设你只有origin,意思是添加upstream,使用git remote add创建upstream:
git remote add upstream <url>
其中 url 是他们 fork 的 GitHub URL。然后运行:
git fetch upstream
从他们那里获取任何新的提交,并在您的克隆中创建您自己的upstream/main 和其他远程跟踪名称。
您现在可以合并、快进、变基或以其他方式更新您的main。如果你还没有独立main:
git checkout main # or git switch main
现在运行git merge --ff-only upstream/main 或git rebase upstream/main,或者您可能想在这里执行的任何操作。如果你想扔掉你有的任何main(旧的master)提交,但他们没有——可能没有任何这样的提交,在这种情况下,合并或变基都会做同样的事情——你可以使用:
git reset --hard upstream/main
无论您使用其中的哪一个,您自己的本地 main 名称现在与您的 upstream/main 标识相同的提交:上游分支以其名称 main 标识的相同提交。现在你可以更新你的 GitHub 分支了:
git push origin main # add --force if needed and desired
如果您在此过程中丢弃某些提交,则仅需要 --force 选项。
然后,您必须对自己的分支做出相同类型的决定。你想保留你有但他们没有的任何提交吗?他们有没有这个名字的分支,如果有,它是否与你的这个名字的分支有关? (每个存储库都有自己的分支名称,并且不需要以相同的方式使用它们。)
假设他们没有丢弃任何提交——如果他们有,你的 Git 现在会认为这些提交是你的提交,并会尝试将它们用作你的分支——你现在可以自己rebase你的分支,不管它的名字是什么,main:
git checkout xyzzy
git rebase main
如果他们放弃了一些提交,您可能需要git rebase --onto 以防止这些提交在您的更新中出现;查看其他 StackOverflow 问题以了解如何执行此操作。
在复制您的提交时可能会出现合并冲突,具体取决于他们更改了多少代码。如果是这样,您将不得不解决它们。如果有很多大的冲突,我建议在开始 rebase 操作之前为旧的分支提示提交创建一个新的分支名称来保存原始提交集:
git checkout xyzzy
git branch xyzzy.0
git rebase main
当您完成 rebase 后,您将拥有 xyzzy.0(您之前出现的原始提交)和 xyzzy(您的新的和改进的提交副本)。如果在 rebase 期间出现问题,现在返回并查看您的原始提交相对容易。
无论哪种方式,您现在都可以使用:
git push -f origin branch
要将新提交发送到您的 GitHub 分支并使您的 GitHub 分支 Git 存储库使用名称 branch 来识别来自 rebase 的新提交和改进提交。是否也在你的 fork 上创建名称 branch.0 由你决定,以保持对原始提交的访问。
【讨论】:
如果来源仍然相同,您可以重命名本地分支以继续使用 Github 上的版本。
master 分支中git checkout master
git branch -m main
然后您将能够像以前一样继续使用 main 分支而不是 master
【讨论】: