[我们都听说过,切勿为已发布的工作重新定级,这很危险,等等。但是,如果重新发布is,我还没有看到有关如何处理这种情况的任何方法。
现在,请注意,仅当存储库仅由已知的(最好是少数)人员克隆时,这才真正可行,因此,推动重新设置或重置的人员可以通知其他所有人,接下来他们将需要注意他们提取(!)的时间。
如果您在foo
上没有本地提交,并且得到重新设置,我见过的一个显而易见的解决方案将起作用:
git fetch
git checkout foo
git reset --hard origin/foo
这将根据远程存储库简单地丢弃foo
的本地状态,以支持其历史记录。
但是,如果有人对该分支机构进行了实质性的本地变更,该人如何处理?
在大多数情况下,重推基础之后恢复同步实际上并不那么复杂。
git checkout foo
git branch old-foo origin/foo # BEFORE fetching!!
git fetch
git rebase --onto origin/foo old-foo foo
git branch -D old-foo
即首先,您要为远程分支的原始位置设置一个书签,然后使用该书签将您从该点开始的本地提交重播到重新建立基础的远程分支上。
重装就像暴力:如果不能解决您的问题,您只需要更多。 ☺
当然,如果您查找重新基准化前的origin/foo
提交ID,并使用它,当然也可以不使用书签。
这也是您处理忘记制作书签[[之前的情况。没有任何损失–您只需要检查远程分支的引用日志:
git reflog show origin/foo | awk '
PRINT_NEXT==1 { print $1; exit }
/fetch: forced-update/ { PRINT_NEXT=1 }'
这将在最近一次更改其历史记录的获取之前打印origin/foo
指向的提交ID。您可以然后简单地
git rebase --onto origin/foo $commit foo
与从自己的基准库中恢复实际上没有什么不同-您移动一个分支,并将其历史记录中的所有分支基准都重新建立到新位置。
[使用topic
创建的git checkout -b topic origin/master
分支后,可能已经重绕并重建了远程跟踪分支origin/master
的历史,从而导致了这种形状的历史:
o---B1
/
---o---o---B2--o---o---o---B (origin/master)
\
B3
\
Derived (topic)
其中origin/master
过去指向提交B3
,B2
,B1
,现在它指向B
,并且当topic
处于以下位置时,您的origin/master
分支从其顶部开始B3
。此模式使用
origin/master
的引用日志找到B3
作为分支点,因此topic
可以在更新的origin/master
之上重新建立基础:]$ fork_point=$(git merge-base --fork-point origin/master topic) $ git rebase --onto origin/master $fork_point topic
这就是git merge-base
命令具有新选项的原因:
git merge-base
找到分支(或导致--fork-point::
的任何历史记录)从另一个分支(或任何参考)<commit>
分叉的点。这不仅查找两个提交的共同祖先,而且还考虑了
<ref>
的引用日志,以查看导致<ref>
的历史是否是从分支<commit>
的早期版本中派生的。 。“ [<ref>
”命令使用该分支工作所基于的“git pull --rebase
”分支(通常是远程跟踪分支)的reflog条目来计算要重新建立分支的分支点。撤消并重建“基础”分支的情况。例如,如果历史记录看起来像在哪里:
“
base
”分支的当前尖端位于base
,但较早的提取发现它的尖端曾经是B
,然后是B3
,然后是B2
在进入当前提交之前,然后基于最新“基础”重新分支的分支基于提交 B1
,它尝试通过遍历“ B3
”(即B3
,git rev-list --reflog base
,B
,B1
)的输出来查找B2
,直到找到作为当前祖先的提交为止提示“B3
”。内部,
Derived (topic)
可以一次计算。我们想要get_merge_bases_many()
与虚拟合并提交之间的合并基础,该合并提交将合并所有[Derived
]的历史提示。当存在这样的提交时,我们应该得到一个单一的结果,该结果与“base (origin/master)
”的引用条目之一完全匹配。
Git 2.1(2014年第3季度)将对此功能进行增强:请参见base
by commit 1e0dacd正确处理具有以下拓扑的方案:
其中:[
johnkeeping
是C --- D --- E <- dev / B <- master@{1} / o --- B' --- C* --- D* <- master
的固定版本,与B'
补丁不相同;- [
B
和B
分别与C*
和D*
修补相同,并且冲突如果以错误的顺序应用,则按文本;
C
从文字上取决于D
。E
的正确结果是D
被标识为git rebase master dev
和B
的分叉点,因此dev
,master
,C
是需要提交的提交回放到D
上;但是E
和master
与C
和D
的补丁相同,因此可以将其删除,因此最终结果是:C*
[如果未识别出分叉点,则将D*
拾取到包含o --- B' --- C* --- D* --- E <- dev
的分支上会导致冲突,如果未正确识别补丁相同的提交,则将B
拾取到包含B'
的分支上(或等价C
)会导致冲突。
当在2.20年代用C重写命令时,“ [D
”的“D*
”模式已退回,并已通过Git 2.27(2020年第二季度)更正。”>请参阅
--fork-point
的git rebase
(2019年12月9日)。[(由commit f08132f在Junio C Hamano (
gitster
)中合并,2020年3月27日)>[gitster
:Junio C Hamano --gitster
--回归修复
签名人:Alex Torok[jc:修改了补丁,并使用了Alex的测试]签字人:Junio C Hamano
“gitster
”过去工作正常,因为它内部称为“ commit fb4175b”,它知道如何处理短refname,并在调用基础的rebase
函数之前将其变为完整的refname。用C重写命令后,这不再是正确的,因为直接对rebase
的内部调用不会忽略短引用。
将在“ git merge-base”中使用的“ dwim refname参数移到完整的refname”逻辑到基础的--fork-point
函数,以便在执行“ git rebase”时该函数的另一个调用者能够正常工作修复此回归的方法相同。