协慌网

登录 贡献 社区

如何将修订后的提交推送到远程 Git 存储库?

当我处理完源代码后,我做了通常的事情提交,然后将其推送到远程存储库。但是后来我发现我忘记了在源代码中组织导入。因此,我执行了 amend 命令来替换先前的提交:

> git commit --amend

不幸的是,无法将提交推回存储库。像这样被拒绝:

> git push origin
To //my.remote.repo.com/stuff.git/
 ! [rejected]        master -> master (non-fast forward)
error: failed to push some refs to '//my.remote.repo.com/stuff.git/'

我应该怎么办? (我可以访问远程存储库。)

答案

实际上,我曾经使用--force.git存储库进行推送,并被 Linus BIG TIME责骂。总的来说,这会给其他人带来很多问题。一个简单的答案是 “不要这样做”。

我看到其他人仍然给出了这样做的诀窍,因此在此不再赘述。但是,在您使用 --force(或 + master)推出修订后的提交之后,这里有一个技巧可以使您从这种情况中恢复过来。

  1. 使用git reflog查找您修改过的旧提交(将其命名为old new调用您创建的新提交)。
  2. 创建之间的合并oldnew ,记录的树new ,喜欢git checkout new && git merge -s ours old
  3. git merge master到您的 master
  4. git push . HEAD:master更新结果。 git push . HEAD:master
  5. 将结果推出。

然后,那些不幸地将工作基于已通过修改和强制推送而抹去的提交的人,将会看到最终的合并,将会看到您偏爱new不是old 。他们后来合并将不会看到之间的矛盾oldnew起因于您的修正,所以他们没有受到影响。

您正在看到 Git 安全功能。 Git 拒绝使用您的分支更新远程分支,因为分支的 head 提交不是您要推送到的分支的当前 head 提交的直接后代。

如果不是这种情况,那么两个人几乎同时推送到同一个存储库,就不会知道同时有一个新的提交,而最后推送的人将丢失前一个推送器的工作而没有任何一个他们意识到这一点。

如果您知道自己是唯一推送的人,并且想要推送修订的提交或推送回退分支的提交,则可以使用-f开关 “强制” Git 更新远程分支。

git push -f origin master

甚至这可能也不起作用,因为 Git 允许远程存储库通过使用配置变量receive.denynonfastforwards拒绝远端的非快进推送。如果是这种情况,拒绝原因将如下所示(请注意 “远程拒绝” 部分):

! [remote rejected] master -> master (non-fast forward)

为了解决这个问题,您需要更改远程存储库的配置,或者作为肮脏的黑客,您可以删除并重新创建分支,从而:

git push origin :master
git push origin master

git push的最后一个参数使用格式<local_ref>:<remote_ref> ,其中local_ref是本地存储库remote_ref是远程存储库上分支的名称。该命令对使用两个速记。 :master具有一个空的 local_ref,这意味着将一个空分支推送到远程master ,即删除远程分支。分支名称为 no :表示将具有给定名称的本地分支推送到具有相同名称的远程分支。 master在这种情况下是短期的master:master

快速说明:没有人在此处发布简单答案这一事实表明,Git CLI 表现出了极度的用户敌意。

无论如何,假设您没有尝试强制推动,“明显” 的方法就是先拉。这会拉出您修改(因此不再拥有)的更改,以便您再次拥有它。

解决所有冲突后,您可以再次推送。

所以:

git pull

如果在拉取过程中遇到错误,则可能是本地存储库配置有问题(我在. git / config 分支节中的引用有误)。

之后

git push

也许您会获得与主题有关 “临时合并” 的额外承诺。