Git 非快进拒绝

我觉得这个问题已经被问过很多次了,但是解决方案通常是“我删除了目录,然后用一个新的签出重新做了我的工作。”我进行了提交和推送,但发现在提交消息中引用了错误的票证号码。因此,我期待着一个快速的 解决方案,并最终在终端输入以下内容:

$ git reset --soft HEAD^
$ git commit -m "... correct message ..."

唯一的问题是我收到了以下错误消息:

To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again.  See the 'Note about
fast-forwards' section of 'git push --help' for details.

我正在使用 git-flow 模型,并在开发分支上工作。我怎样才能把事情合并回来,让 git 再次快乐起来呢?

101400 次浏览

You might have to do a git pull, which MAY auto merge stuff for you. Then you can commit again. If you have conflicts, it'll prompt you to resolve them.

Keep in mind, you have to specify which branch to pull from if you haven't updated your gitconfig to specify...

For example:

git pull origin develop:develop

Force git push:

git push origin +develop

If you push a commit to the server, and then rewrite that commit locally (with git reset, git rebase, git filter-branch, or any other history manipulation), and then pushed that rewritten commit back up to the server, you will screw up anyone else who had pulled. Here's an example; say you have committed A, and pushed it to the server.

-*-*-A <-- master


-*-*-A <-- origin/master

Now you decide to rewrite A, in the way you mentioned, resetting and re-committing. Note that this leaves a dangling commit, A, which will eventually be garbage collected as it is not reachable.

-*-*-A
\
A' <-- master


-*-*-A  <-- origin/master

If someone else, let's say Fred, pulls down master from the server while you're doing this, they will have a reference to A, which they might start working from:

-*-*-A' <-- master


-*-*-A  <-- origin/master


-*-*-A-B <-- fred/master

Now if you were able to push your A' to origin/master, which would create a non-fast-forward, it wouldn't have A in its history. So if Fred tried to pull again, he'd suddenly have to merge, and would re-introduce the A commit:

-*-*-A' <-- master


-*-*-A  <-- origin/master


-*-*-A-B-\
\     * <-- fred/master
A'--/

If Fred happens to notice this, then he could do a rebase, which would prevent commit A from reappearing again. But he'd have to notice this, and remember to do this; and if you have more than one person who pulled A down, they would all have to rebase in order to avoid getting the extra A commit in the tree.

So, it's generally not a good idea to change history on a repo that other people pull from. If, however, you happen to know that no one else is pulling from that repo (for instance, it's your own private repo, or you only have one other developer working on the project who you can coordinate with easily), then you can forcibly update by running:

git push -f

or

git push origin +master

These will both ignore the check for a non-fast-forward push, and update what's on the server to your new A' revision, abandoning the A revision so it will eventually be garbage collected.

It's possible that force pushes are entirely disabled with the receive.denyNonFastForwards config option. This option is enabled by default on shared repositories. In that case, if you really, really want to force a push, the best option is to delete the branch and re-create it, with git push origin :master; git push origin master:master. However, the denyNonFastForwards option is enabled for a reason, which is described above; on a shared repository, it means that now everyone who uses it needs to ensure that they rebase onto the new history.

On a shared repository, it is generally better to just push new commits on top that fix whatever problem you have; you can use git revert to generate commits that will undo the changes of previous commits.

I was using EGit and I faced this issue also. Just tried to rebase the current branch and It worked.