代码之家  ›  专栏  ›  技术社区  ›  robertpostill

Git Reset--硬盘和远程存储库

git
  •  178
  • robertpostill  · 技术社区  · 15 年前

    我有一个存储库,其中有一些错误的提交(本例中是D、E和F)。

    A-B-C-D-E-F主机和源站/主机

    我特别修改了本地存储库 git reset --hard . 重置前我做了一个分支,所以现在我有一个回购,看起来像:

    A-B-C master  
         \ D-E-F old_master
    
    A-B-C-D-E-F origin/master
    

    现在,我需要这些糟糕的提交中的一些部分,所以我挑选了我需要的部分,并做出了一些新的提交,所以现在我在本地有了以下内容:

    A-B-C-G-H master
         \ D-E-F old_master
    

    现在我想把这种情况推到远程回购上。但是,当我尝试 git push 吉特礼貌地拒绝了我:

    $ 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 git@git.example.com:myrepo.git  
    ! [remote rejected] master -> master (non-fast forward)  
    error: failed to push some refs to 'git@git.example.com:myrepo.git'  
    

    如何让远程回购获得本地回购的当前状态?

    4 回复  |  直到 7 年前
        1
  •  261
  •   Henrik    13 年前

    如果强制推不起作用(“ git push --force origin “或” git push --force origin master “应该足够了”),这可能意味着远程服务器拒绝通过 接收.denynonfastforwards 配置变量(请参见 git config 或通过更新/预接收挂钩。

    使用较旧的Git,您可以通过删除来绕过该限制。” git push origin :master (请参阅分支名称前的“:”,然后重新创建) git push origin master “给定分支。

    如果你不能改变这一点,那么唯一的解决办法就是将历史重写为 创建提交 reverting D-E-F的变化 :

    A-B-C-D-E-F-[(D-E-F)^-1]   master
    
    A-B-C-D-E-F                             origin/master
    
        2
  •  24
  •   Jealie    11 年前

    为了补充Jakub的答案,如果您可以在ssh中访问远程git服务器,则可以进入git远程目录并设置:

    user@remote$ git config receive.denyNonFastforwards false
    

    然后回到您的本地回购,再次尝试执行您的承诺 --force :

    user@local$ git push origin +master:master --force
    

    最后将服务器的设置恢复为原始保护状态:

    user@remote$ git config receive.denyNonFastforwards true
    
        3
  •  1
  •   Community CDub    8 年前

    与修复“主”分支不同,通过重命名分支,可以更容易地将其与“所需的主”进行交换。见 https://stackoverflow.com/a/2862606/2321594 .这样,您甚至不会留下多个还原日志的任何跟踪。

        4
  •  0
  •   Wolfgang Fahl    8 年前

    对我来说,整个Git重置业务看起来要复杂得多。

    所以我做了一些事情,把我的SRC文件夹放在几天前提交的状态中。

    # 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目录被它之前提交过的状态替换。