在push --force之后检索孤立的提交对象

时间:2013-09-18 17:20:34

标签: git

执行push --force总是有点风险,这里有一个例子说明它如何产生一些问题,比如远程修改版本。

假设有一些人 Bob 已更新从masterB的远程C分支。还有另一个人 Mike 尚未获取此更新,而HEAD的{​​{1}}仍为master。然后B执行Mike并突然将远程push --force再次回滚到master

B

换句话说,在 Mike 之前,远程母版就像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修订只是远程的 - 它存在于git-server和 Bob 的笔记本电脑上,因为他将其推送到远程{{1 }}。这意味着 Mike 的笔记本电脑上没有此类本地参考C

问题1 Mike 如何将远程master设置回C

Mike 已尝试再次使用master解决C问题,但它不起作用,因为没有糟糕的本地参考:

push --force

问题2 Mike 如何从git服务器获取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' 修订版?如果他不能那样做 - 为什么git这样设计?在一些罕见的情况下是否涉及安全?它究竟阻止了什么问题?

通常C仅检索分支和标记,但fetch不属于任何分支(这意味着没有任何远程分支C是父提交或{{ 1}} of of。

PS:我们假设 Mike 没有对git服务器的ssh访问权限,这意味着无法从服务器端调用git。

PPS: Mike 不希望 Bob 知道该事故,因此请回答“让 Bob 再次推送此提交”是不是这个问题是什么。

4 个答案:

答案 0 :(得分:9)

任何在本地提交C的人都可以使用git branch some-name CC提供一个名称,然后git push origin some-name:masterC添加回主人C原产地。

任何没有C的人根本无法恢复C(即使它位于原始对象商店中)。

迈克 无法解决问题,除非使用包含提交C的可用内容(可能是共享内容,可能是 Bob ' s,可能是git-push在主人身上时克隆的其他一些仓库。

您无法推送本地没有的提交。 {{1}}的本地一半必须能够遍历历史记录以确定要上传的对象,如果没有该历史记录,则无法执行此操作。

你无法获取无法从refs访问的提交,因为字面上每个git安全层都在ref-by-ref的基础上进行安全性,而不是逐个对象,并且因为没有真正的有理由远程引用松散的物体。 Git的远程处理层完全围绕复制refs构建。

但是如果服务器启用了该功能,您可以使用git-archive获取任意提交的内容。大多数都没有,即使你的,也没有足够的信息来重建提交对象。

(c)irc:// freenode /#git,ojacobson

答案 1 :(得分:9)

如果您使用的是GitHub,则可以按照this post中的步骤在孤立后在提交C上创建分支。

答案 2 :(得分:2)

无法访问服务器,这是......非常困难,充其量。 (我说“硬得多”,因为它可能会编写一个上传无包装的程序,然后发送一个转换更新,按编号提到C。我不知道这是否会起作用;它威力。)

但是,一般情况下,服务器将从某个客户端获取修订版C(大多数推送服务器为--bare,这意味着服务器上没有实际执行任何工作)。那个客户端缺少提交,并且很容易恢复提交(在reflog中找到,添加一个新的分支或标记,推送)。

如果您具有对服务器的ssh访问权限,请登录并使用git fsck查找已删除的提交(或者如果您使用缩写的SHA-1只使用该提交),则使用git branch或{ {1}}创建对它的引用。

编辑,每个问题编辑:Mike 实际上可能提交 git tag 。他可以尝试,例如,C,看看他是否拥有它。但是git rev-parse C失败已经告诉我们他没有它。他为什么不能得到它?因为当他连接到服务器时,他说(实际上)“这是我的分支机构,你的是什么?”并且服务器说(实际上)“哦,我的是这些,你想要其中的一些吗?”。这就是协议中的所有内容 - 客户端不能通过ID请求特定的提交,至少不是通过这些接口。某些Web服务器访问方法 do 允许您通过原始SHA-1值发送并请求相应的对象;您必须查明服务器是否正在运行任何此类服务。

至于“迈克不希望鲍勃知道这起事故”......好吧,有时你只需承认。 : - )

答案 3 :(得分:0)

这些 git 命令解决了这个问题。 仅当您拥有完整的哈希值时才有效。

# Fetch the remote commit and create a reference for it
git fetch origin C:refs/remotes/origin/foo-commit

# Checkout the remote branch we just created
git checkout foo-commit

# Force push foo-commit branch to master
git push -f origin master

一个很好的额外之处是它不接触本地主分支。