问题描述
执行 push --force
总是很冒险的,这是一个示例,它可能会产生一些问题,例如远程丢失修订版.
Doing push --force
is always kinda risky and here is an example of how it could produce some problems like loosing revisions remotely.
假设某人鲍勃已将远程 master
分支从 B
更新为 C
.还有另一个人 Mike 尚未获取此更新,并且他的 master
的 HEAD
仍然是 B
.然后 Mike
做 push --force
并突然将远程 master
重新回滚到 B
:
Suppose, there is some person Bob that has updated remote master
branch from B
to C
. And there is another person Mike that doesn't fetch this update yet and HEAD
of his master
is still B
. Then Mike
do push --force
and suddenly roll back remote master
to B
again:
mike@laptop $> git push --force origin
Counting objects: 19, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (12/12), 2.27 KiB, done.
Total 12 (delta 8), reused 0 (delta 0)
remote: => Syncing... [OK]
To git@gitserver.com:path/to/project.git
C..B master -> master (forced update)
换句话说,在迈克做到这一点之前,远程主机就像 A --- B --- C
一样,他将其更改为 A---B
.
In other words, before Mike did that, remote master was like A---B---C
and he changed it to A---B
.
如您所见,这里的 C
修订版仅是远程的-它存在于git-server和 Bob 的笔记本电脑上,因为他将其推送到了远程 master
.这意味着迈克的笔记本电脑上没有这样的本地参考 C
.
As you can see, C
revision here is remote only - it exists on git-server and on the Bob's laptop, because he pushed it to the remote master
. It means that there is no such local ref C
on the Mike's laptop.
问题1 :迈克如何将远程 master
设置回 C
?
Question 1: how can Mike set remote master
back to C
?
Mike 尝试再次使用 push --force
解决该问题,例如提供类似问题的答案,但是它没有用,因为没有本地引用:
Mike has tried to solve that problem with push --force
again like the answer for similar question offers, but it doesn't work because there is no suck local ref:
mike@laptop $> git push --force origin C:master
error: src refspec C does not match any.
error: failed to push some refs to 'git@gitserver.com:path/to/project.git'
问题2 : Mike 如何从git服务器获取 C
版本?如果他不能做到这一点-为什么git会那样设计?在极少数情况下与安全有关吗?它到底能防止什么问题?
Question 2: how can Mike fetch C
revision from the git server? And if he can't do that - why git designed like that? Is it about safety in some rare cases? What problems it exactly prevents?
通常 fetch
仅检索分支和标签,但是 C
不属于任何分支(这意味着 C
是父提交或 HEAD
).
Usually fetch
retrieves branches and tags only, but C
doesn't belong to any branch (which means that there is no any remote branch that C
is parent commit or HEAD
of).
PS:假设 Mike 对git服务器没有ssh访问权限,这意味着无法从服务器端调用git.
PS: let's assume that Mike has no ssh access to git server, it means that there is no way to call git from the server side.
PPS:迈克不希望 Bob 知道该事故,因此回答使 Bob 再次推动该提交"是不是这个问题是关于什么的.
PPS: Mike doesn't want Bob to know about that accident, so answer "Make Bob to push this commit again" is not what this question is about.
推荐答案
任何在本地提交了 C
的人都可以使用 git branch some-name C
来提供C
一个名称,然后 git push origin some-name:master
到(尝试)将 C
附加回原点上的master.
Anyone who has commit C
locally can use git branch some-name C
to give C
a name, then git push origin some-name:master
to (try to) append C
back to master on origin.
没有 C
的任何人根本无法恢复 C
(即使它位于原始对象存储库中).
Anyone who doesn't have C
can't recover C
at all (even if it's in origin's object store).
迈克 无法解决此问题,除了使用包含提交 C
(可能是共享的,可能是 Bob ,可能是在 C
在主服务器上时克隆的其他一些回购).
Mike cannot fix the problem except using a repo that contains commit C
(possibly the shared one, possibly Bob's, possibly some other repo that was cloned when C
was on master).
您不能推送本地没有的提交. git-push
的本地一半必须能够遍历历史记录以找出要上传的对象,如果没有可用的历史记录,则无法做到这一点.
You can't push commits you don't have locally. The local half of git-push
has to be able to walk history to figure out what objects to upload, and it can't do that if it doesn't have that history available.
您无法获取引用无法访问的提交,因为实际上每个git安全层都基于逐个引用而不是逐个对象进行安全性,并且因为没有真正的远程引用松散对象的原因.Git的远程处理层完全围绕复制引用而构建.
You can't fetch commits that aren't reachable from refs, because literally every git security layer out there does security on a ref-by-ref basis, not an object-by-object basis, and because there's no real reason to reference loose objects remotely. Git's remoting layer is entirely built around copying refs around.
但是,如果服务器已启用该功能,则可以使用git-archive获取任意提交的内容.大多数都没有,即使您有,也没有足够的信息来重构提交对象.
But you can fetch arbitrary commits' contents using git-archive, if the server has that feature turned on. Most don't, and even if yours does, it's not enough information to reconstruct the commit object.
(c)irc://freenode/#git,ojacobson
(c) irc://freenode/#git, ojacobson
这篇关于在push --force之后检索孤立的提交对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!