git pull --rebase 分叉信息
git pull --rebase fork infomation
我们使用 git pull --rebase
而不是 git pull
。我们在检索服务器上不再显示的分叉信息时遇到问题。
假设只有一个 "master" 分支,人们可以从中推拉。
此外,假设人们修改了不同的文件并且 git.
没有引发冲突
这是拉取前我的本地分支及其上游的图像
A---B---C local
/
D---E---F---G server
如果我们使用 git pull
(标准的)会发生这种情况
A---B---C
/ \
D---E---F---G---M---
但是因为我们使用的是 git pull --rebase
如果我没记错的话会发生这种情况:
D---E---F---G---A'--B'--C'
现在我们知道其中一个测试在 C' 中不再有效。我们确信它在 C 和 G 中都能正常工作。即使没有冲突,如果有两个冗余代码块,并且第一个人删除了一个块,而另一个人删除了另一个块,这也可能发生。
通常要检查的修改是提交 A',B',C,F,G 中的修改,因为分叉发生在 E。但是由于我们使用 git pull --rebase
我们无法知道当分叉发生时,我们无法识别集合 A'、B'、C、F、G。
1) 知道问题现在只出现在 C' 是否有办法识别 E 并因此识别集合 A',B',C,F,G?
2) 如果 1) 的答案是 "no" 那么应该检查哪些提交?
TL;DR:您可以使用 git merge-base
和 reflog 信息找到提交 E
。
你的绘图是正确的,因为 rebase 所做的是 copy 提交(到新的,略有不同的)。
原始提交会在存储库中保留一段时间(一般情况下,默认为 30 天):它们只是被放置在视图之外。有可能(使用 reflogs and/or ORIG_HEAD
找到原始的 C
并从那里,合并基础提交 E
.
如果这种事情经常发生,我建议不要直接使用 git pull
。事实上,我建议永远不要 从 开始 git pull
,即使使用这两个独立的基础步骤需要更多的工作和更多的输入。这里的想法是让 Git 正在做什么变得显而易见,从而更容易插入有用的自动化。 (之后,根据您自己的自动化程度,如果您发现 运行 一个命令比两个命令更方便,您可以返回使用 git pull
,有或没有 --rebase
。)
git pull
所做的是 运行 git fetch
,然后是 git merge
或 git rebase
。虽然 pull
有一些额外的花里胡哨,但这确实是其行动的核心。分别执行这两个操作的好处是,它们让您可以检查 fetch
之后和 merge
-or-rebase
.
之前的状态
(这对于 merge
来说是不必要的,因为 "before merge" 状态很明显:只需剥离合并提交,你就会拥有合并前的状态。它对 [= 更有用31=] 因为 "before merge" 状态允许你在允许 Git 做它疯狂和疯狂的事情之前分别查看分叉开发的两侧,制作提交的副本。)
让我们在这里重现您的 "before" 状态,然后展示 rebase 真正做了什么。这是 "before" 状态,在 运行ning git fetch
之后,但在 运行ning git rebase
:
之前
A---B---C <-- HEAD -> branch
/
D---E---F---G <-- origin/branch
我添加了指向您当前分支的名称 HEAD
,并将分支重新命名为更典型。
在 git rebase
步骤之后,我们有:
A---B---C <-- ORIG_HEAD, branch@{1}
/
D---E---F---G <-- origin/branch
\
A'--B'--C' <-- HEAD -> branch
通常,观看者(git log
、gitk --all
等)会跳过 ORIG_HEAD
、CHERRY_PICK_HEAD
等特殊引用。他们还忽略了 reflogs 的内容 (branch@{1}
)。使用 git reflog
或 git log -g
,或在命令行中添加名称 ORIG_HEAD
,您可以指示这些观众向您展示原件。
如果将这两个步骤分开,可以很容易地保存关于任何特定提交的信息或向其添加标记(例如临时 git tag
s)。比如在git fetch
之后,可以标记commitE
:找到branch
和origin/branch
的1合并基,然后标记它:
$ git tag temp-marker $(git merge-base branch origin/branch)
(假设 sh 或 bash 或类似的;请注意,要概括这一点,您可以只使用 HEAD
和 @{u}
代替 branch
和 origin/branch
).
如果你不想让人们感到困惑 ("why is there a tag named temp-marker
in all our repositories?!"),请确保在完成后删除 temp-marker
标签(或至少避免推送它)。
即使您使用 git pull --rebase
将它们组合在一起,之后您也可以使用 reflog and/or ORIG_HEAD
来做同样的事情。 (这里的主要问题是 reflog 中的数字——上面的 branch@{1}
——和 ORIG_HEAD
本身都会更新。如果你再做一次变基,ORIG_HEAD
现在会跟踪 rebase 而不是你仍然关心的那个。同时,如果你对 branch
进行任何更新,数字 (@{1}
) 递增:现在你需要 branch@{2}
,然后branch@{3}
,等等。(您也可以使用 branch@{yesterday}
,它检查记录到 branch
的每个更改的日期戳,并使用来自 "yesterday"。有关详细信息,请参阅 the git reflog
documentation and its link back to git log
, and also gitrevisions
。)
换句话说,一旦你进入了这个特定的泡菜,检查 branch@{1}
是否是正确的参考(或者 ORIG_HEAD
仍然是好的)。如果不是,请使用 git reflog
或类似的方法找到正确的参考。无论如何,一旦找到它:
git merge-base branch@{1} origin/branch
将找到提交 E
.
1这假设只有一个合并基础提交。对于我们在这里考虑的所有情况,这应该是正确的。只有在存在 "criss-cross merges" 的情况下才能获得多个合并基础(必须手工制作):
...--o--*---o--o <-- branch1
\ /
X
/ \
...--o--*---o--o <-- branch2
在这里,branch1
和 branch2
之间没有单一的合并基础:两个 *
提交都是合适的合并基础。这不会发生在具有单个上游分支的正常工作流中(因为您无法签出 origin/branch
并对其进行提交)。你将不得不做一些你自己的狂野和疯狂的事情(使用一个临时分支、两个显式合并和至少一个推送)来实现它。
我们使用 git pull --rebase
而不是 git pull
。我们在检索服务器上不再显示的分叉信息时遇到问题。
假设只有一个 "master" 分支,人们可以从中推拉。 此外,假设人们修改了不同的文件并且 git.
没有引发冲突这是拉取前我的本地分支及其上游的图像
A---B---C local
/
D---E---F---G server
如果我们使用 git pull
(标准的)会发生这种情况
A---B---C
/ \
D---E---F---G---M---
但是因为我们使用的是 git pull --rebase
如果我没记错的话会发生这种情况:
D---E---F---G---A'--B'--C'
现在我们知道其中一个测试在 C' 中不再有效。我们确信它在 C 和 G 中都能正常工作。即使没有冲突,如果有两个冗余代码块,并且第一个人删除了一个块,而另一个人删除了另一个块,这也可能发生。
通常要检查的修改是提交 A',B',C,F,G 中的修改,因为分叉发生在 E。但是由于我们使用 git pull --rebase
我们无法知道当分叉发生时,我们无法识别集合 A'、B'、C、F、G。
1) 知道问题现在只出现在 C' 是否有办法识别 E 并因此识别集合 A',B',C,F,G?
2) 如果 1) 的答案是 "no" 那么应该检查哪些提交?
TL;DR:您可以使用 git merge-base
和 reflog 信息找到提交 E
。
你的绘图是正确的,因为 rebase 所做的是 copy 提交(到新的,略有不同的)。
原始提交会在存储库中保留一段时间(一般情况下,默认为 30 天):它们只是被放置在视图之外。有可能(使用 reflogs and/or ORIG_HEAD
找到原始的 C
并从那里,合并基础提交 E
.
如果这种事情经常发生,我建议不要直接使用 git pull
。事实上,我建议永远不要 从 开始 git pull
,即使使用这两个独立的基础步骤需要更多的工作和更多的输入。这里的想法是让 Git 正在做什么变得显而易见,从而更容易插入有用的自动化。 (之后,根据您自己的自动化程度,如果您发现 运行 一个命令比两个命令更方便,您可以返回使用 git pull
,有或没有 --rebase
。)
git pull
所做的是 运行 git fetch
,然后是 git merge
或 git rebase
。虽然 pull
有一些额外的花里胡哨,但这确实是其行动的核心。分别执行这两个操作的好处是,它们让您可以检查 fetch
之后和 merge
-or-rebase
.
(这对于 merge
来说是不必要的,因为 "before merge" 状态很明显:只需剥离合并提交,你就会拥有合并前的状态。它对 [= 更有用31=] 因为 "before merge" 状态允许你在允许 Git 做它疯狂和疯狂的事情之前分别查看分叉开发的两侧,制作提交的副本。)
让我们在这里重现您的 "before" 状态,然后展示 rebase 真正做了什么。这是 "before" 状态,在 运行ning git fetch
之后,但在 运行ning git rebase
:
A---B---C <-- HEAD -> branch
/
D---E---F---G <-- origin/branch
我添加了指向您当前分支的名称 HEAD
,并将分支重新命名为更典型。
在 git rebase
步骤之后,我们有:
A---B---C <-- ORIG_HEAD, branch@{1}
/
D---E---F---G <-- origin/branch
\
A'--B'--C' <-- HEAD -> branch
通常,观看者(git log
、gitk --all
等)会跳过 ORIG_HEAD
、CHERRY_PICK_HEAD
等特殊引用。他们还忽略了 reflogs 的内容 (branch@{1}
)。使用 git reflog
或 git log -g
,或在命令行中添加名称 ORIG_HEAD
,您可以指示这些观众向您展示原件。
如果将这两个步骤分开,可以很容易地保存关于任何特定提交的信息或向其添加标记(例如临时 git tag
s)。比如在git fetch
之后,可以标记commitE
:找到branch
和origin/branch
的1合并基,然后标记它:
$ git tag temp-marker $(git merge-base branch origin/branch)
(假设 sh 或 bash 或类似的;请注意,要概括这一点,您可以只使用 HEAD
和 @{u}
代替 branch
和 origin/branch
).
如果你不想让人们感到困惑 ("why is there a tag named temp-marker
in all our repositories?!"),请确保在完成后删除 temp-marker
标签(或至少避免推送它)。
即使您使用 git pull --rebase
将它们组合在一起,之后您也可以使用 reflog and/or ORIG_HEAD
来做同样的事情。 (这里的主要问题是 reflog 中的数字——上面的 branch@{1}
——和 ORIG_HEAD
本身都会更新。如果你再做一次变基,ORIG_HEAD
现在会跟踪 rebase 而不是你仍然关心的那个。同时,如果你对 branch
进行任何更新,数字 (@{1}
) 递增:现在你需要 branch@{2}
,然后branch@{3}
,等等。(您也可以使用 branch@{yesterday}
,它检查记录到 branch
的每个更改的日期戳,并使用来自 "yesterday"。有关详细信息,请参阅 the git reflog
documentation and its link back to git log
, and also gitrevisions
。)
换句话说,一旦你进入了这个特定的泡菜,检查 branch@{1}
是否是正确的参考(或者 ORIG_HEAD
仍然是好的)。如果不是,请使用 git reflog
或类似的方法找到正确的参考。无论如何,一旦找到它:
git merge-base branch@{1} origin/branch
将找到提交 E
.
1这假设只有一个合并基础提交。对于我们在这里考虑的所有情况,这应该是正确的。只有在存在 "criss-cross merges" 的情况下才能获得多个合并基础(必须手工制作):
...--o--*---o--o <-- branch1
\ /
X
/ \
...--o--*---o--o <-- branch2
在这里,branch1
和 branch2
之间没有单一的合并基础:两个 *
提交都是合适的合并基础。这不会发生在具有单个上游分支的正常工作流中(因为您无法签出 origin/branch
并对其进行提交)。你将不得不做一些你自己的狂野和疯狂的事情(使用一个临时分支、两个显式合并和至少一个推送)来实现它。