Git重设-硬并推送到远程存储库


199

我的存储库上有一些错误的提交(本示例中为D,E和F)。

ABCDEF母版和来源/母版

我已经使用专门修改了本地存储库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 pushGit 时,我会毫不犹豫地给我刷掉:

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

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


2
该是“几乎”复制几个“我怎么推修改历史问题”,例如看便知这里stackoverflow.com/questions/253055/...
CB贝利

2
是的,我在发布之前已经在StackOverflow上搜索了答案。但是,我的搜索仅找到了答案,其中git push --force解决了该问题。感谢您链接到您的帖子:)
robertpostill

2
您很快就会(2013年第4季度git1.8.5)能够做得git push -force更加谨慎
VonC

Answers:


286

如果强制推送无济于事(“ git push --force origin”或“ git push --force origin master”应该足够),则可能意味着远程服务器正在通过receive.denyNonFastForwards配置变量(请参见git config联机帮助页以获取描述)拒绝非快进推送。通过更新/预接收钩子。

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

如果您不能更改此设置,那么唯一的解决方案是代替重写历史记录来创建提交以恢复 DEF中的更改

ABCDEF-[[DEF)^-1]主

ABCDEF起源/母版

2
@JakubNarębski,谢谢。get revert HEAD~N帮助了。N是提交次数。例如,如果我需要上一次提交,我将使用git revert HEAD~1
Maksim Dmitriev

1
并且请注意,这样做会破坏其他所有人。
汤姆·布里托

24

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

user@remote$ git config receive.denyNonFastforwards false

然后返回您的本地仓库,再试一次以执行您的提交--force

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

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

user@remote$ git config receive.denyNonFastforwards true

另请参见pete.akeo.ie/2011/02/denying-non-fast-forward-and.html,以获取sourceforge量身定制的信息。
2014年

有关如何禁用denyNonFastForwards使用的详细说明,请参见此viSO帖子:stackoverflow.com/a/43721579/2073804
ron190


1

整个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目录替换为之前已提交的状态。


0

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

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

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.