Git reset --hard and a remote repository
我有一个存储库,其中有一些错误的提交(本例中是D、E和F)。
A-B-C-D-E-F master and origin/master
号
我专门用
1 2 3 4 | A-B-C master \ D-E-F old_master A-B-C-D-E-F origin/master |
现在,我需要这些糟糕的提交中的一些部分,所以我挑选了我需要的部分,并做出了一些新的提交,所以现在我在本地有了以下内容:
1 2 | A-B-C-G-H master \ D-E-F old_master |
号
现在我想把这种情况推到远程回购上。然而,当我试图做一个
1 2 3 4 5 6 | $ git push origin +master:master --force Total 0 (delta 0), reused 0 (delta 0) error: denying non-fast forward refs/heads/master (you should pull first) To [email protected]:myrepo.git ! [remote rejected] master -> master (non-fast forward) error: failed to push some refs to '[email protected]:myrepo.git' |
如何让远程回购获得本地回购的当前状态?
如果强制推不起作用("
使用较旧的Git,您可以通过删除"
如果您无法更改此项,那么唯一的解决方案将是重写历史记录以在D-E-F中创建一个提交恢复更改:
1 2 3 | A-B-C-D-E-F-[(D-E-F)^-1] master A-B-C-D-E-F origin/master |
为了补充Jakub的答案,如果您可以在ssh中访问远程git服务器,则可以进入git远程目录并设置:
1 | user@remote$ git config receive.denyNonFastforwards false |
号
然后回到您的本地回购,再次尝试执行您与
1 | user@local$ git push origin +master:master --force |
最后将服务器的设置恢复为原始保护状态:
1 | user@remote$ git config receive.denyNonFastforwards true |
。
与修复"主"分支不同,通过重命名分支,可以更容易地将其与"所需的主"进行交换。请参阅https://stackoverflow.com/a/2862606/2321594。这样,您甚至不会留下多个还原日志的任何跟踪。
对我来说,整个Git重置业务看起来要复杂得多。
所以我做了一些事情,让我的SRC文件夹处于几天前提交的状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # reset the local state git reset <somecommit> --hard # copy the relevant part e.g. src (exclude is only needed if you specify .) tar cvfz /tmp/current.tgz --exclude .git src # get the current state of git git pull # remove what you don't like anymore rm -rf src # restore from the tar file tar xvfz /tmp/current.tgz # commit everything back to git git commit -a # now you can properly push git push |
这样,SRC中的状态保存在tar文件中,并且Git被迫接受这个状态,而不需要太多的修改——基本上,SRC目录被它之前提交过的状态所替换。