有人将变基或重置推送到已发布的分支后,如何恢复/重新同步?
我们都听说过,永远不应该对已发表的作品进行变基,这是危险的,等等。但是,我还没有看到任何发布的方法来说明如何处理变基发布的情况。
现在,请注意,只有当存储库仅由已知的(最好是一小群)人克隆时,这才是真正可行的,这样无论谁推动变基或重置都可以通知其他人,他们下次需要注意拿来(!)。
如果您在 foo 上没有本地提交并且它会被重新设置,我见过的一个明显的解决方案将起作用:
git fetch
git checkout foo
git reset --hard origin/foo
这将简单地丢弃 foo 的本地状态,以支持其根据远程存储库的历史记录。
但是,如果一个人对该分支进行了重大的本地更改,该如何处理这种情况呢?
We have all heard that one should never rebase published work, that it’s dangerous, etc. However, I have not seen any recipes posted for how to deal with the situation in case a rebase is published.
Now, do note that this is only really feasible if the repository is only cloned by a known (and preferably small) group of people, so that whoever pushes the rebase or reset can notify everyone else that they will need to pay attention next time they fetch(!).
One obvious solution that I have seen will work if you have no local commits on foo
and it gets rebased:
git fetch
git checkout foo
git reset --hard origin/foo
This will simply throw away the local state of foo
in favour of its history as per the remote repository.
But how does one deal with the situation if one has committed substantial local changes on that branch?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在大多数情况下,在推送变基后恢复同步实际上并不那么复杂。
IE。首先,您为远程分支最初所在的位置设置一个书签,然后使用它来重播从该点开始的本地提交到重新定位的远程分支。
变基就像暴力:如果它不能解决你的问题,你只需要更多。 ☺
当然,如果您查找预变基
origin/foo
提交 ID 并使用它,您当然可以在没有书签的情况下执行此操作。这也是您处理在获取之前忘记创建书签的情况的方法。不会丢失任何内容 - 您只需要检查远程分支的引用日志:
这将打印
origin/foo
在最近一次更改其历史记录的提取之前指向的提交 ID。然后你可以简单地
Getting back in synch after a pushed rebase is really not that complicated in most cases.
Ie. first you set up a bookmark for where the remote branch originally was, then you use that to replay your local commits from that point onward onto rebased remote branch.
Rebasing is like violence: if it doesn’t solve your problem, you just need more of it. ☺
You can do this without the bookmark of course, if you look up the pre-rebase
origin/foo
commit ID, and use that.This is also how you deal with the situation where you forgot to make a bookmark before fetching. Nothing is lost – you just need to check the reflog for the remote branch:
This will print the commit ID that
origin/foo
pointed to before the most recent fetch that changed its history.You can then simply
我想说 git-rebase 手册页的 从上游 rebase 恢复 部分几乎涵盖了所有这些。
这实际上与从您自己的变基恢复没有什么不同 - 您移动一个分支,并将历史记录中包含该分支的所有分支变基到新位置。
I'd say the recovering from upstream rebase section of the git-rebase man page covers pretty much all of this.
It's really no different from recovering from your own rebase - you move one branch, and rebase all branches which had it in their history onto its new position.
从 git 1.9/2.0 Q1 2014 开始,在重写的上游分支上重新建立基础之前,您不必标记以前的分支源,如 亚里士多德 Pagaltzis 的答案:
请参阅 提交 07d406b 和 提交 d96855f :
这就是为什么
git merge-base
命令有一个新选项:例如,如果历史记录如下所示:
Git 2.1(2014 年第 3 季度)将添加使此功能更加强大的功能:请参阅 commit 1e0dacd 通过 John Keeping (
johnkeeping
)正确处理我们具有以下拓扑的场景:
其中:
B'
是B
的修复版本,与B
补丁不同;C*
和D*
分别与C
和D
补丁相同,如果应用于顺序错误;E
在文本上依赖于D
。git rebase master dev
的正确结果是B
被识别为dev
和master
的分叉点,因此C
、D
、E
是需要重播到master
上的提交;但C
和D
与C*
和D*
补丁相同,因此可以删除,这样最终结果是:如果未识别分叉点,则将
B
选取到包含B'
的分支上会导致冲突,并且如果补丁相同的提交不存在正确识别,然后将C
选择到包含D
(或等效的D*
)的分支上会导致冲突。“
git rebase
”的“--fork-point
”模式在 2.20 时代用 C 重写命令时出现了退化,已在 Git 2.27(Q2)中得到纠正。 2020)。请参阅 提交 f08132f(2019 年 12 月 9 日),作者:Junio C Hamano (
gitster
)。(由 Junio C Hamano --
gitster
-- 合并于 提交fb4175b,2020年3月27日)对于 Git 2.31(2021 年第一季度),“< code>git rebase --[no-]fork-point"(man)" 获得了一个配置变量
rebase.forkPoint
,这样用户就不必继续指定非默认设置,请参阅 commit 2803d80(2021 年 2 月 23 日)< a href="https://github.com/alexhenrie" rel="nofollow noreferrer">亚历克斯·亨利 (
alexhenrie
)。(由 Junio C Hamano --
gitster
-- 合并于 提交 682bbad,2021 年 2 月 25 日)git config
现在包含在其 手册页:Starting with git 1.9/2.0 Q1 2014, you won't have to mark your previous branch origin before rebasing it on the rewritten upstream branch, as described in Aristotle Pagaltzis's answer:
See commit 07d406b and commit d96855f :
That is why the
git merge-base
command has a new option:For example, if the history looked like where:
Git 2.1 (Q3 2014) will add make this feature more robust to this: see commit 1e0dacd by John Keeping (
johnkeeping
)correctly handle the scenario where we have the following topology:
where:
B'
is a fixed-up version ofB
that is not patch-identical withB
;C*
andD*
are patch-identical toC
andD
respectively, and conflict textually, if applied in the wrong order;E
depends textually onD
.The correct result of
git rebase master dev
is thatB
is identified as the fork-point ofdev
andmaster
, so thatC
,D
,E
are the commits that need to be replayed ontomaster
; butC
andD
are patch-identical withC*
andD*
and so can be dropped, so that the end result is:If the fork-point is not identified, then picking
B
onto a branch containingB'
results in a conflict and if the patch-identical commits are not correctly identified, then pickingC
onto a branch containingD
(or equivalentlyD*
) results in a conflict.The "
--fork-point
" mode of "git rebase
" regressed when the command was rewritten in C back in 2.20 era, which has been corrected with Git 2.27 (Q2 2020).See commit f08132f (09 Dec 2019) by Junio C Hamano (
gitster
).(Merged by Junio C Hamano --
gitster
-- in commit fb4175b, 27 Mar 2020)With Git 2.31 (Q1 2021), "
git rebase --[no-]fork-point
"(man)" gained a configuration variablerebase.forkPoint
so that users do not have to keep specifying a non-default setting.See commit 2803d80 (23 Feb 2021) by Alex Henrie (
alexhenrie
).(Merged by Junio C Hamano --
gitster
-- in commit 682bbad, 25 Feb 2021)git config
now includes in its man page: