Git reset --hard和一个远程存储库

时间:2009-09-04 08:05:22

标签: git

我有一个存储库,它上面有一些不好的提交(本例中为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礼貌地给了我刷掉的东西:

$ 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'  

如何让远程仓库获取本地仓库的当前状态?

5 个答案:

答案 0 :(得分:265)

如果强制推送没有帮助(“git push --force origin”或“git push --force origin master”应该足够了),这可能意味着远程服务器通过 receive.denyNonFastForwards 配置变量(有关说明,请参阅git config联机帮助页),或通过更新/预接收挂钩。

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

如果你无法改变这一点,那么唯一的解决方案就是不要将历史重写为在D-E-F中创建提交reverting

A-B-C-D-E-F-[(D-E-F)^-1]   master

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

答案 1 :(得分:24)

为了补充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

答案 2 :(得分:2)

对于GitHub的用户,这对我有用:

  1. 在您希望进行任何更改的分支保护规则中,请确保已启用允许强行推送
  2. git reset --hard <full_hash_of_commit_to_reset_to>
  3. git push --force

这将“更正”本地计算机和GitHub服务器上的分支历史记录,但是自错误提交以来已将此分支与服务器同步的任何人都将在其本地计算机上拥有历史记录。如果他们有权直接推送到分支,则这些提交将在同步时立即备份。

所有其他人所需要做的就是上面的git reset命令来“更正”其本地计算机上的分支。当然,他们需要警惕在目标散列之后 对该分支所做的任何本地提交。 Cherry选择/备份并在必要时重新应用它们,但是,如果您位于受保护的分支中,则可以直接提交给它的人数可能会受到限制。

答案 3 :(得分:1)

而不是修复你的&#34;主人&#34;分支,它更容易与您的&#34;期望的主人&#34;交换它。通过重命名分支。见https://stackoverflow.com/a/2862606/2321594。这样,您甚至不会留下任何多个还原日志的痕迹。

答案 4 :(得分:0)

整个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目录被替换为它有几次提交之前的状态。