Git 使用分叉远程进行变基
Git rebase with forked remote
有一个主要的 git 回购;主要回购;主分支 - 我的远程。
我将其分叉到我的个人资料中:main-repo;主分支 - 起源
在分叉后添加了对远程的提交。
分叉后添加了对 origin 的提交。所以现在这是前一提交和后一提交。
目标:将 my-remote 重新设置为 origin。以这种方式,origin 应该首先从 my-remote 提交,然后再从 origin 提交。我知道这将创建新的提交 (SHA)。
我正在从我的个人资料中克隆。
git clone url2
。 - 起源
将远程仓库添加为另一个远程仓库。
git remote add my-remote gitRepoToRemote
我在我的本地 master 分支上,它正在跟踪来源。
正在尝试变基。
git fetch --all
.
git rebase my-remote/master
.
有冲突。
手动解决。
然后 git add file-with-conflict
.
继续变基 git rebase --continue
.
git push origin HEAD:master
.
获取错误。为什么在推送前解决冲突时会出现此错误?
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'gitRepoToOrigin'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details
正如评论中暗示(但未说明)的那样,您将需要某种强制推动。原因并没有那么复杂,但是画出原因,与其说说而已,还是很有帮助的。这里的问题,用一种有趣的方式来说,是你有三个不同的存储库,都命名为 Bruce,一个新的提交命名为 Bruce,一个重写的新提交命名为 Bruce。您现在需要告诉 Bruce 忘记 Bruce,因为 Bruce 有了新的 Bruce 并且 Bruce 需要与 Bruce 匹配。
(以上有点矫枉过正,但也请参见had had had had had句。)
而不是称每个人和所有事物为“Bruce”,或者尝试给出每个提交的确切哈希 ID——这会导致类似(尽管不同)的问题,因为 人类 不擅长哈希 ID,将每个 ID 转换为他们头脑中类似“Bruce”的哔哔声——让我们将每个存储库绘制为一系列提交,其中提交由单个大写字母指定。我们首先从您所谓的“main-repo”开始,然后在您使用 git remote add
:
后调用 my-remote
my-remote:
...--F--G--H <-- master
名称 master
存在于此存储库中。该名称存储提交的哈希 ID H
(一些丑陋的大哈希 ID)。右侧的提交 H
是最新的。它包含:
- 每个文件的完整快照,以及
- 包含早期提交的哈希 ID 的元数据
G
所以提交 H
向后链接到更早的提交 G
。较早的提交 G
有每个文件的快照(来自较早的),当然,加上 still-earlier 提交 F
的哈希 ID。这一直重复到时间的开始:这就是 Git 存储提交的方式。
然后您使用 GitHub 的 fork 按钮制作了此存储库的 copy,我们将其称为 origin
。此副本有自己的 b运行ch 名称,但与原始存储库共享实际提交。1 在任何情况下,在 GitHub 上的这个副本中,name master
拥有相同的哈希 ID:
origin:
...--F--G--H <-- master
然后您将 GitHub 分支克隆到您自己的计算机(我们将其称为“膝上型计算机”,即使它是台式机或桌边计算机,只是为了给它一个好记但独特的名称)。这复制了提交,但副本与原件相同——它们必须是;任何提交的任何部分在提交后都不能更改——然后将它们的 b运行ch 名称复制到 remote-tracking 名称,所以你有:
laptop:
...--F--G--H <-- origin/master
你的 git clone
命令然后根据你的 -b master
参数,或者你缺少任何 -b
参数加上来自 GitHub 的建议,即您的 Git 在此处使用名称 master
:
laptop:
...--F--G--H <-- master, origin/master
最后,在你的笔记本电脑上,你的 Git 运行 git checkout master
填充工作树(和 Git 的 index 虽然我们不会在这里讨论这个)从提交 H
,使 master
成为 当前 b运行ch 并提交 H
当前提交,在laptop
:
laptop:
...--F--G--H <-- master (HEAD), origin/master
1他们是否共享原始底层提交或复制它们与我们并不真正相关。事实是提交是 100%,bit-for-bit 相同。这意味着只要 my-remote
和 origin
都存储在同一台 物理机 上,它们就可以共享底层提交。如果它们存储在具有独立永久内存系统(旋转磁盘、闪存等)的独立物理机器上,他们将需要使用原始提交字节的副本,而不是真正共享底层存储,但我们不关心关于那个。
到目前为止的总结
截至此时(过去某个时间),所有三个存储库的内容看起来非常相似。您的笔记本电脑存储库中主要且可观察到的区别在于您拥有 origin/master
和提交的工作副本 H
。除了这些差异(对于完成工作很重要,但在其他方面无关紧要),这三者看起来都是这样的:
...--F--G--H <-- master
事情会随着时间而改变
接下来,您在笔记本电脑上进行了新的提交。我们将此提交称为 I
,H
之后的下一个字母。所以在 laptop 上我们现在有:
laptop:
...--F--G--H <-- origin/master
\
I <-- master (HEAD)
与此同时,有人在 GitHub 上为 my-remote
存储库向 master
发送了新提交。通常我会称这个提交为J
,但没有明显的原因,我会在这里称它为K
。所以 他们 有这个,我也会无缘无故地画得很奇怪:
my-remote:
K <-- master
/
...--F--G--H
请注意名为 origin
的存储库还没有发生任何变化。
此时,您 运行 git push
在您的笔记本电脑上。无需过多担心您将 传递给 git push
(如果有)的确切参数,这最终会发送一个提交,您的 lapto有,origin
没有,要origin
。所以现在,在 origin
,你有:
origin:
...--F--G--H
\
I <-- master
此推送成功后,您的笔记本电脑将更新其 origin/master
。那是因为你的 git push
有你的笔记本电脑 呼叫 GitHub,通过互联网,要求 GitHub 连接到存储库 origin
(哪个有效)。你的笔记本Git发送组成commitI
的数据,然后询问GitHub设置他们的 master
, 他们说可以, 所以你的笔记本电脑 Git 知道 origin
Git 的 master
指向提交 I
。所以现在 laptop
你有:
laptop:
...--F--G--H
\
I <-- master (HEAD), origin/master
我们在这里绘制的图表中不需要所有这些小问题,但我是故意使用它们的。请注意,origin
和 laptop
都不知道有关提交 K
的任何信息!同样,my-remote
从未听说过 commit I
.
乐趣 (?) 开始
此时你开始做一些花哨的事情:
Added remote repo as another remote.
git remote add my-remote gitRepoToRemote
您的 laptop
Git 现在知道另一个 Git,名为 my-remote
, 存在 。它尚未连接到它。
git fetch --all
大多数人误用了--all
,但在这里您已经正确地使用了它(恭喜!)。 --all
选项将您的 Git 指向 运行 git fetch
而不是 每个遥控器 .
这有点矫枉过正,因为这让你的 Git 调用了 origin
和 my-remote
,看看是什么新的,如果有的话,在这两个存储库中。 origin
中没有任何新内容, 也不可能 有任何内容,因为您将是唯一更新它的人。但没关系!但是,当您的 Git 调用名为 my-remote
的 Git 时,有些东西 是 新的:他们提交了 K
,而您没有't.
你的 Git 因此 获得 提交 K
来自 my-remote
,并将其插入你的存储库。然后你的 Git 创建了一个 remote-tracking 名字,my-remote/origin
,因为这是 与 my-remote
的第一次联系。所以现在 laptop
有:
laptop:
K <-- my-remote/master
/
...--F--G--H
\
I <-- master (HEAD), origin/master
(现在你可以明白为什么我在绘图中保留扭结了)。
你可以告诉你的Git告诉origin
Git关于提交K
(发送K
到 origin
在过程中2laptop 上的图可以看出,origin
会出现问题:名称 master
只能指向 一个 提交。您可以选择 提交 I
或 提交 K
,但不能同时选择两者。要指向两个提交——以便您可以找到 I
和 K
——您至少需要 两个 名称。
您在 laptop
上的存储库 具有 必要的名称:my-remote/master
指向 K
,master
指向至 I
。 origin/master
也指向 I
,所以你现在可以自由地让你的 master
指向 任何地方 :找到提交 K
你可以使用名称 my-remote/master
,要查找 I
,您可以使用名称 origin/master
.
2因为origin
是my-remote
的一个分支,origin
理论上能够见 更直接地提交K
。理论上,GitHub 可以 ar运行为此。他们是否、如何以及何时这样做取决于他们:您的 Git 不需要知道任何相关信息。如果、如何以及何时 GitHub 添加 web 机制,而不是这种有点迂回的 fetch-and-push-again 方法,引入 将 K
提交到 origin
,同样取决于 GitHub。不过,从今天开始,您必须使用迂回方法。
变基
rebase 命令可以这样总结:我有一些我最喜欢的提交,但是这些提交有一些我不 喜欢。我知道我不能 更改 任何现有提交的任何内容,所以我不想这样做,而是 copy 现有提交 new-and-improved个,把不喜欢的改了,喜欢的留了
让我们再看看此时 laptop
上的内容:
laptop:
K <-- my-remote/master
/
...--F--G--H
\
I <-- master (HEAD), origin/master
我们不喜欢提交I
的地方有两点:
- 它没有来自提交
K
和 的更新
- 它在提交
H
之后出现,而不是在提交 K
之后出现。
我们做喜欢它的是这些东西:
- 它与提交
H
和 相比有一些变化
- 它有一个精心制作的、令人愉快的详细提交消息解释为什么它有这些变化。
我们希望在进行 新 提交时保留这两件事,以修复我们 不 喜欢的两件事。我们用 git rebase
来做到这一点(在内部,它由 cherry-picking 我们想要复制的每个提交组成;只有一个,这就是为什么我们只是获得一个新的提交)。
无需过多担心 that 的进展情况——它有时会变得混乱:
Got conflicts. Resolved manually. then git add file-with-conflict.
continue with rebase git rebase --continue
.
但看起来你做的所有这些都是正确的——最终结果是一个新的提交:
laptop:
J <-- master (HEAD)
/
K <-- my-remote/master
/
...--F--G--H
\
I <-- origin/master
此 新 提交,J
,出现在现有提交 K
之后,并进行了正确的更改——根据 [=469] 的需要进行了修改=] 冲突——并带有正确的提交消息文本。所以 new commit J
就是我们想要的。它 完全废弃 旧提交 I
。
我们如何知道 J
取代了 I
,而 I
不再有用? 这里唯一的答案是我们知道它是因为我们做到了。 Git不知道也不关心。只有 我们 知道并关心。我们的 Git,在 laptop
,我们的 master
现在指向提交 J
。提交 I
已被放弃,除了我们的 origin/master
仍然可以找到它。
我们现在要告诉 origin
做同样的事情
我们现在可以运行:
git push origin master
或:
git push origin HEAD:master
让我们的 Git 调用 GitHub,让他们连接到 origin
存储库,并向他们发送新的提交 J
。这部分有效——但随后我们要求他们将他们的master
设置为指向提交J
,他们拒绝.他们特别说不,错误说 如果我这样做,我将放弃一些现有的提交:
! [rejected] master -> master (non-fast-forward)
此 non-fast-forward
消息意味着 我将丢失我的 master
.
的一些提交
在这种情况下,他们将丢失的提交是提交 I
。提交 I
被 提交 J
废弃。但是他们不知道。我们必须迫使他们放弃提交 I
.
我们这样做的方法是使用各种强制选项之一(非常适合星球大战日):
git push --force origin master
或:
git push --force-with-lease origin master
它们之间是有区别的,但是 在这种特殊情况下(origin
是“你的”分叉,由你控制,而不是 pushed-to由其他人)这并不重要。它们都像常规 git push
一样工作,除了最后,不是发送礼貌的请求:请,如果没问题并且没有丢失任何东西,请将您的 master
更新为记住现在提交 J
,这种推送以 command 形式结束 update your master
to point to commit J
! Git 在 GitHub 将服从这个命令并在 origin
存储库中留下这个:
origin:
J <-- master
/
K
/
...--F--G--H
\
I ???
位于 GitHub 的 Git 最终会——这可能需要一天、一周或更长时间——运行 git gc
和 删除 提交 I
,我们现在应该开始将其存储库绘制为:
origin:
...--F--G--H--K--J <-- master
简化它。我们也可以开始用你的笔记本电脑这样做,除了我们需要 my-remote/master
指向 K
,所以我们得到:
laptop:
J <-- master (HEAD), origin/master
/
...--F--G--H--K <-- my-remote/master
你的笔记本电脑 Git 实际上会挂起提交 I
相当长一段时间——默认情况下至少 30 天——然后才扔掉它,但由于它 不可见(在 git log
输出中)此时我们不必费心绘制它。
有一个主要的 git 回购;主要回购;主分支 - 我的远程。
我将其分叉到我的个人资料中:main-repo;主分支 - 起源
在分叉后添加了对远程的提交。
分叉后添加了对 origin 的提交。所以现在这是前一提交和后一提交。
目标:将 my-remote 重新设置为 origin。以这种方式,origin 应该首先从 my-remote 提交,然后再从 origin 提交。我知道这将创建新的提交 (SHA)。
我正在从我的个人资料中克隆。
git clone url2
。 - 起源
将远程仓库添加为另一个远程仓库。
git remote add my-remote gitRepoToRemote
我在我的本地 master 分支上,它正在跟踪来源。
正在尝试变基。
git fetch --all
.
git rebase my-remote/master
.
有冲突。
手动解决。
然后 git add file-with-conflict
.
继续变基 git rebase --continue
.
git push origin HEAD:master
.
获取错误。为什么在推送前解决冲突时会出现此错误?
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'gitRepoToOrigin'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details
正如评论中暗示(但未说明)的那样,您将需要某种强制推动。原因并没有那么复杂,但是画出原因,与其说说而已,还是很有帮助的。这里的问题,用一种有趣的方式来说,是你有三个不同的存储库,都命名为 Bruce,一个新的提交命名为 Bruce,一个重写的新提交命名为 Bruce。您现在需要告诉 Bruce 忘记 Bruce,因为 Bruce 有了新的 Bruce 并且 Bruce 需要与 Bruce 匹配。
(以上有点矫枉过正,但也请参见had had had had had句。)
而不是称每个人和所有事物为“Bruce”,或者尝试给出每个提交的确切哈希 ID——这会导致类似(尽管不同)的问题,因为 人类 不擅长哈希 ID,将每个 ID 转换为他们头脑中类似“Bruce”的哔哔声——让我们将每个存储库绘制为一系列提交,其中提交由单个大写字母指定。我们首先从您所谓的“main-repo”开始,然后在您使用 git remote add
:
my-remote
my-remote:
...--F--G--H <-- master
名称 master
存在于此存储库中。该名称存储提交的哈希 ID H
(一些丑陋的大哈希 ID)。右侧的提交 H
是最新的。它包含:
- 每个文件的完整快照,以及
- 包含早期提交的哈希 ID 的元数据
G
所以提交 H
向后链接到更早的提交 G
。较早的提交 G
有每个文件的快照(来自较早的),当然,加上 still-earlier 提交 F
的哈希 ID。这一直重复到时间的开始:这就是 Git 存储提交的方式。
然后您使用 GitHub 的 fork 按钮制作了此存储库的 copy,我们将其称为 origin
。此副本有自己的 b运行ch 名称,但与原始存储库共享实际提交。1 在任何情况下,在 GitHub 上的这个副本中,name master
拥有相同的哈希 ID:
origin:
...--F--G--H <-- master
然后您将 GitHub 分支克隆到您自己的计算机(我们将其称为“膝上型计算机”,即使它是台式机或桌边计算机,只是为了给它一个好记但独特的名称)。这复制了提交,但副本与原件相同——它们必须是;任何提交的任何部分在提交后都不能更改——然后将它们的 b运行ch 名称复制到 remote-tracking 名称,所以你有:
laptop:
...--F--G--H <-- origin/master
你的 git clone
命令然后根据你的 -b master
参数,或者你缺少任何 -b
参数加上来自 GitHub 的建议,即您的 Git 在此处使用名称 master
:
laptop:
...--F--G--H <-- master, origin/master
最后,在你的笔记本电脑上,你的 Git 运行 git checkout master
填充工作树(和 Git 的 index 虽然我们不会在这里讨论这个)从提交 H
,使 master
成为 当前 b运行ch 并提交 H
当前提交,在laptop
:
laptop:
...--F--G--H <-- master (HEAD), origin/master
1他们是否共享原始底层提交或复制它们与我们并不真正相关。事实是提交是 100%,bit-for-bit 相同。这意味着只要 my-remote
和 origin
都存储在同一台 物理机 上,它们就可以共享底层提交。如果它们存储在具有独立永久内存系统(旋转磁盘、闪存等)的独立物理机器上,他们将需要使用原始提交字节的副本,而不是真正共享底层存储,但我们不关心关于那个。
到目前为止的总结
截至此时(过去某个时间),所有三个存储库的内容看起来非常相似。您的笔记本电脑存储库中主要且可观察到的区别在于您拥有 origin/master
和提交的工作副本 H
。除了这些差异(对于完成工作很重要,但在其他方面无关紧要),这三者看起来都是这样的:
...--F--G--H <-- master
事情会随着时间而改变
接下来,您在笔记本电脑上进行了新的提交。我们将此提交称为 I
,H
之后的下一个字母。所以在 laptop 上我们现在有:
laptop:
...--F--G--H <-- origin/master
\
I <-- master (HEAD)
与此同时,有人在 GitHub 上为 my-remote
存储库向 master
发送了新提交。通常我会称这个提交为J
,但没有明显的原因,我会在这里称它为K
。所以 他们 有这个,我也会无缘无故地画得很奇怪:
my-remote:
K <-- master
/
...--F--G--H
请注意名为 origin
的存储库还没有发生任何变化。
此时,您 运行 git push
在您的笔记本电脑上。无需过多担心您将 传递给 git push
(如果有)的确切参数,这最终会发送一个提交,您的 lapto有,origin
没有,要origin
。所以现在,在 origin
,你有:
origin:
...--F--G--H
\
I <-- master
此推送成功后,您的笔记本电脑将更新其 origin/master
。那是因为你的 git push
有你的笔记本电脑 呼叫 GitHub,通过互联网,要求 GitHub 连接到存储库 origin
(哪个有效)。你的笔记本Git发送组成commitI
的数据,然后询问GitHub设置他们的 master
, 他们说可以, 所以你的笔记本电脑 Git 知道 origin
Git 的 master
指向提交 I
。所以现在 laptop
你有:
laptop:
...--F--G--H
\
I <-- master (HEAD), origin/master
我们在这里绘制的图表中不需要所有这些小问题,但我是故意使用它们的。请注意,origin
和 laptop
都不知道有关提交 K
的任何信息!同样,my-remote
从未听说过 commit I
.
乐趣 (?) 开始
此时你开始做一些花哨的事情:
Added remote repo as another remote. git remote add my-remote gitRepoToRemote
您的 laptop
Git 现在知道另一个 Git,名为 my-remote
, 存在 。它尚未连接到它。
git fetch --all
大多数人误用了--all
,但在这里您已经正确地使用了它(恭喜!)。 --all
选项将您的 Git 指向 运行 git fetch
而不是 每个遥控器 .
这有点矫枉过正,因为这让你的 Git 调用了 origin
和 my-remote
,看看是什么新的,如果有的话,在这两个存储库中。 origin
中没有任何新内容, 也不可能 有任何内容,因为您将是唯一更新它的人。但没关系!但是,当您的 Git 调用名为 my-remote
的 Git 时,有些东西 是 新的:他们提交了 K
,而您没有't.
你的 Git 因此 获得 提交 K
来自 my-remote
,并将其插入你的存储库。然后你的 Git 创建了一个 remote-tracking 名字,my-remote/origin
,因为这是 与 my-remote
的第一次联系。所以现在 laptop
有:
laptop:
K <-- my-remote/master
/
...--F--G--H
\
I <-- master (HEAD), origin/master
(现在你可以明白为什么我在绘图中保留扭结了)。
你可以告诉你的Git告诉origin
Git关于提交K
(发送K
到 origin
在过程中2laptop 上的图可以看出,origin
会出现问题:名称 master
只能指向 一个 提交。您可以选择 提交 I
或 提交 K
,但不能同时选择两者。要指向两个提交——以便您可以找到 I
和 K
——您至少需要 两个 名称。
您在 laptop
上的存储库 具有 必要的名称:my-remote/master
指向 K
,master
指向至 I
。 origin/master
也指向 I
,所以你现在可以自由地让你的 master
指向 任何地方 :找到提交 K
你可以使用名称 my-remote/master
,要查找 I
,您可以使用名称 origin/master
.
2因为origin
是my-remote
的一个分支,origin
理论上能够见 更直接地提交K
。理论上,GitHub 可以 ar运行为此。他们是否、如何以及何时这样做取决于他们:您的 Git 不需要知道任何相关信息。如果、如何以及何时 GitHub 添加 web 机制,而不是这种有点迂回的 fetch-and-push-again 方法,引入 将 K
提交到 origin
,同样取决于 GitHub。不过,从今天开始,您必须使用迂回方法。
变基
rebase 命令可以这样总结:我有一些我最喜欢的提交,但是这些提交有一些我不 喜欢。我知道我不能 更改 任何现有提交的任何内容,所以我不想这样做,而是 copy 现有提交 new-and-improved个,把不喜欢的改了,喜欢的留了
让我们再看看此时 laptop
上的内容:
laptop:
K <-- my-remote/master
/
...--F--G--H
\
I <-- master (HEAD), origin/master
我们不喜欢提交I
的地方有两点:
- 它没有来自提交
K
和 的更新
- 它在提交
H
之后出现,而不是在提交K
之后出现。
我们做喜欢它的是这些东西:
- 它与提交
H
和 相比有一些变化
- 它有一个精心制作的、令人愉快的详细提交消息解释为什么它有这些变化。
我们希望在进行 新 提交时保留这两件事,以修复我们 不 喜欢的两件事。我们用 git rebase
来做到这一点(在内部,它由 cherry-picking 我们想要复制的每个提交组成;只有一个,这就是为什么我们只是获得一个新的提交)。
无需过多担心 that 的进展情况——它有时会变得混乱:
Got conflicts. Resolved manually. then git add file-with-conflict. continue with rebase
git rebase --continue
.
但看起来你做的所有这些都是正确的——最终结果是一个新的提交:
laptop:
J <-- master (HEAD)
/
K <-- my-remote/master
/
...--F--G--H
\
I <-- origin/master
此 新 提交,J
,出现在现有提交 K
之后,并进行了正确的更改——根据 [=469] 的需要进行了修改=] 冲突——并带有正确的提交消息文本。所以 new commit J
就是我们想要的。它 完全废弃 旧提交 I
。
我们如何知道 J
取代了 I
,而 I
不再有用? 这里唯一的答案是我们知道它是因为我们做到了。 Git不知道也不关心。只有 我们 知道并关心。我们的 Git,在 laptop
,我们的 master
现在指向提交 J
。提交 I
已被放弃,除了我们的 origin/master
仍然可以找到它。
我们现在要告诉 origin
做同样的事情
我们现在可以运行:
git push origin master
或:
git push origin HEAD:master
让我们的 Git 调用 GitHub,让他们连接到 origin
存储库,并向他们发送新的提交 J
。这部分有效——但随后我们要求他们将他们的master
设置为指向提交J
,他们拒绝.他们特别说不,错误说 如果我这样做,我将放弃一些现有的提交:
! [rejected] master -> master (non-fast-forward)
此 non-fast-forward
消息意味着 我将丢失我的 master
.
在这种情况下,他们将丢失的提交是提交 I
。提交 I
被 提交 J
废弃。但是他们不知道。我们必须迫使他们放弃提交 I
.
我们这样做的方法是使用各种强制选项之一(非常适合星球大战日):
git push --force origin master
或:
git push --force-with-lease origin master
它们之间是有区别的,但是 在这种特殊情况下(origin
是“你的”分叉,由你控制,而不是 pushed-to由其他人)这并不重要。它们都像常规 git push
一样工作,除了最后,不是发送礼貌的请求:请,如果没问题并且没有丢失任何东西,请将您的 master
更新为记住现在提交 J
,这种推送以 command 形式结束 update your master
to point to commit J
! Git 在 GitHub 将服从这个命令并在 origin
存储库中留下这个:
origin:
J <-- master
/
K
/
...--F--G--H
\
I ???
位于 GitHub 的 Git 最终会——这可能需要一天、一周或更长时间——运行 git gc
和 删除 提交 I
,我们现在应该开始将其存储库绘制为:
origin:
...--F--G--H--K--J <-- master
简化它。我们也可以开始用你的笔记本电脑这样做,除了我们需要 my-remote/master
指向 K
,所以我们得到:
laptop:
J <-- master (HEAD), origin/master
/
...--F--G--H--K <-- my-remote/master
你的笔记本电脑 Git 实际上会挂起提交 I
相当长一段时间——默认情况下至少 30 天——然后才扔掉它,但由于它 不可见(在 git log
输出中)此时我们不必费心绘制它。