770

当我对我的源代码做了一些工作后,我做了我通常的事情提交,然后我推送到一个远程存储库。但后来我注意到我忘记在源代码中组织我的导入。所以我执行了修改命令来替换之前的提交:

> git commit --amend

不幸的是,提交不能被推回存储库。它被这样拒绝:

> git push origin
To //my.remote.repo.com/stuff.git/
 ! [rejected]        master -> master (non-fast forward)
error: failed to push some refs to '//my.remote.repo.com/stuff.git/'

我该怎么办?(我可以访问远程存储库。)

4

17 回答 17

576

实际上,我曾经推送--force.git存储库并被 Linus BIG TIME责骂。一般来说,这会给其他人带来很多问题。一个简单的答案是“不要这样做”。

无论如何,我看到其他人给出了这样做的秘诀,所以我不会在这里重复。但是,在您使用--force(或+master)推出修改后的提交,这里有一个提示可以从这种情况中恢复过来。

  1. 用于git reflog查找您修改的旧提交(调用它old,我们将调用您通过 amending 创建的新提交new)。
  2. old在和之间创建一个合并new,记录 的树new,就像git checkout new && git merge -s ours old
  3. 将它与你的主人合并git merge master
  4. 用结果更新你的主人git push . HEAD:master
  5. 将结果推出。

然后那些不幸的人将他们的工作建立在你通过修改和强制推送而抹杀的提交上,他们会看到结果合并会看到你更new喜欢old. 他们后来的合并不会看到你的修改导致的old和之间的冲突new,所以他们不必受苦。

于 2009-01-11T07:36:32.787 回答
305

您正在看到 Git 安全功能。Git 拒绝使用您的分支更新远程分支,因为您的分支的头部提交不是您要推送到的分支的当前头部提交的直接后代。

如果不是这种情况,那么两个人几乎同时推送到同一个存储库将不知道有一个新的提交同时进入,最后推送的人将失去前一个推送者的工作,而没有任何一个他们意识到这一点。

如果您知道您是唯一推送的人,并且您想要推送修改后的提交或推送回滚分支的提交,您可以使用-f开关“强制”Git 更新远程分支。

git push -f origin master

即使这也可能不起作用,因为 Git 允许远程存储库通过使用配置变量在远端拒绝非快进推送receive.denynonfastforwards。如果是这种情况,拒绝原因将如下所示(注意“远程拒绝”部分):

 ! [remote rejected] master -> master (non-fast forward)

为了解决这个问题,您要么需要更改远程存储库的配置,要么作为一个肮脏的黑客,您可以删除并重新创建分支:

git push origin :master
git push origin master

通常,最后一个参数git push使用 format <local_ref>:<remote_ref>,其中local_ref是本地存储库上remote_ref的分支名称,是远程存储库上的分支名称。此命令对使用两个速记。:master有一个空的local_ref,这意味着将一个空分支推送到远程端master,即删除远程分支。没有的分支名称:意味着将具有给定名称的本地分支推送到具有相同名称的远程分支。master在这种情况下是master:master.

于 2008-10-31T21:58:00.533 回答
234

快速咆哮:没有人在这里发布简单的答案这一事实表明 Git CLI 表现出绝望的用户敌意。

无论如何,假设您没有尝试强制推动,那么执行此操作的“明显”方法是先拉动。这会拉动您修改(因此不再拥有)的更改,以便您再次拥有它。

解决任何冲突后,您可以再次推送。

所以:

git pull

如果您在拉取时遇到错误,则可能是您的本地存储库配置有问题(我在 .git/config 分支部分有错误的引用)。

之后

git push

也许你会得到一个额外的提交,主题是关于“琐碎合并”。

于 2009-09-22T10:46:04.907 回答
121

简短的回答:不要将修改后的提交推送到公共回购。

长答案:一些 Git 命令,比如git commit --amendand git rebase,实际上重写了历史图。只要你没有发布你的更改就可以了,但是一旦你这样做了,你真的不应该在历史上乱七八糟,因为如果有人已经得到了你的更改,那么当他们再次尝试拉取时,它可能会失败. 而不是修改提交,您应该只对更改进行新的提交。

然而,如果你真的,真的想要推送一个修改过的提交,你可以这样做:

$ git push origin +master:master

前导+符号将强制推送发生,即使它不会导致“快进”提交。(当您推送的更改是公共存储库中已有更改的直接后代时,就会发生快进提交。)

于 2008-10-31T14:35:12.097 回答
67

这是一种非常简单且干净的方法来在您已经做出更改后推送您的更改commit --amend

git reset --soft HEAD^
git stash
git push -f origin master
git stash pop
git commit -a
git push origin master

执行以下操作:

  • 将分支头重置为父提交。
  • 存储最后一次提交。
  • 强制推送到远程。遥控器现在没有最后一次提交。
  • 弹出你的藏匿处。
  • 干净地提交。
  • 推送到远程。

记住要更改originmaster如果将其应用于不同的分支或远程。

于 2015-06-21T14:41:57.227 回答
33

我已经通过丢弃我的本地修改提交并在顶部添加新更改来解决它:

# Rewind to commit before conflicting
git reset --soft HEAD~1

# Pull the remote version
git pull

# Add the new commit on top
git add ...
git commit
git push
于 2012-09-24T15:46:14.803 回答
11

我有同样的问题。

  • 不小心修改了已经推送的最后一次提交
  • 在本地做了很多更改,提交了大约五次
  • 尝试推送、出错、恐慌、合并远程、获取大量非我的文件、推送、失败等。

作为一个 Git 新手,我认为它是完整的FUBAR

解决方案:有点像@bara 建议的 + 创建了一个本地备份分支

# Rewind to commit just before the pushed-and-amended one.
# Replace <hash> with the needed hash.
# --soft means: leave all the changes there, so nothing is lost.
git reset --soft <hash>

# Create new branch, just for a backup, still having all changes in it.
# The branch was feature/1234, new one - feature/1234-gone-bad
git checkout -b feature/1234-gone-bad

# Commit all the changes (all the mess) not to lose it & not to carry around
git commit -a -m "feature/1234 backup"

# Switch back to the original branch
git checkout feature/1234

# Pull the from remote (named 'origin'), thus 'repairing' our main problem
git pull origin/feature/1234

# Now you have a clean-and-non-diverged branch and a backup of the local changes.
# Check the needed files from the backup branch
git checkout feature/1234-gone-bad -- the/path/to/file.php

也许这不是一个快速而干净的解决方案,而且我丢失了我的历史记录(1 次提交而不是 5 次),但它节省了一天的工作。

于 2014-02-20T10:24:49.413 回答
9

如果您还没有将代码推送到远程分支(GitHub/Bitbucket),您可以在命令行上更改提交消息,如下所示。

 git commit --amend -m "Your new message"

如果您正在处理特定分支,请执行以下操作:

git commit --amend -m "BRANCH-NAME: new message"

如果您已经推送了带有错误消息的代码,那么您在更改消息时需要小心。即,在您更改提交消息并尝试再次推送它之后,您最终会遇到问题。为了使其顺利,请按照以下步骤操作。

请在做之前阅读整个答案

git commit --amend -m "BRANCH-NAME : your new message"

git push -f origin BRANCH-NAME                # Not a best practice. Read below why?

重要提示:当您直接使用强制推送时,您可能会遇到其他开发人员在同一分支上工作的代码问题。因此,为避免这些冲突,您需要在强制推送之前从分支中提取代码:

 git commit --amend -m "BRANCH-NAME : your new message"
 git pull origin BRANCH-NAME
 git push -f origin BRANCH-NAME

如果已推送,这是更改提交消息时的最佳实践。

于 2015-01-13T07:20:05.867 回答
6

您收到此错误是因为 Git 远程已经有这些提交文件。您必须强制推送分支才能使其正常工作:

git push -f origin branch_name

还要确保您从远程提取代码,因为您团队中的其他人可能已经推送到同一个分支。

git pull origin branch_name

这是我们必须强制将提交推送到远程的情况之一。

于 2016-01-21T06:35:29.630 回答
6

如果您使用的是 Visual Studio Code,您可以尝试使用此扩展程序以使其更容易。

https://marketplace.visualstudio.com/items?itemName=cimdalli.git-commit-amend-push-force

从它的名字就可以理解,它是连续执行命令的

  • git commit --amend
  • git push --force
于 2020-03-06T09:12:36.220 回答
5

如果您知道没有人取消您未修改的提交,请--force-with-lease使用git push.

在 TortoiseGit 中,您可以在“推送...”选项“强制:可能丢弃”并检查“已知更改”下执行相同的操作。

强制(可能丢弃已知更改)允许远程存储库接受更安全的非快进推送。这可能会导致远程存储库丢失提交;小心使用它。这可以防止丢失遥控器上其他人的未知更改。它检查服务器分支是否指向与远程跟踪分支相同的提交(已知更改)。如果是,将执行强制推送。否则会被拒绝。由于 git 没有远程跟踪标签,因此无法使用此选项覆盖标签。

于 2016-06-07T00:03:57.953 回答
2

这是一个非常简单和干净的方法来在你已经做了一个git add "your files"and之后推送你的更改git commit --amend

git push origin master -f

或者:

git push origin master --force
于 2016-01-18T08:29:59.733 回答
1

我必须通过从远程仓库中提取并处理出现的合并冲突、提交然后推送来解决这个问题。但我觉得有更好的方法。

于 2008-10-31T11:39:28.587 回答
1

我只是继续做 Git 让我做的事情。所以:

  • 由于修改了提交,无法推送。
  • 我按照建议进行拉动。
  • 合并失败。所以我手动修复它。
  • 创建一个新的提交(标记为“合并”)并推送它。
  • 它似乎工作!

注意:修改后的提交是最新的。

于 2016-12-02T16:29:18.070 回答
1

在更改提交的作者和提交者时,以下内容对我有用。

git push -f origin master

Git 足够聪明,可以确定这些是相同增量的提交,仅在元信息部分有所不同。

本地和远程负责人都指向有问题的提交。

于 2020-02-03T03:36:44.593 回答
0

在这里,我如何修复先前提交中的编辑:

  1. 保存到目前为止的工作。

  2. 如果进行了更改,请暂时隐藏您的更改:git stash现在您的工作副本在您上次提交的状态下是干净的。

  3. 进行编辑和修复。

  4. 在“修改”模式下提交更改:git commit --all --amend

  5. 您的编辑器会出现询问日志消息(默认情况下,旧日志消息)。满意后保存并退出编辑器。

    新的更改被添加到旧的提交中。自己看git loggit diff HEAD^

  6. 重新应用您隐藏的更改(如果进行了):git stash apply

于 2019-03-13T06:34:12.030 回答
0

为避免强制推送,请在远程裸存储库中使用以下命令删除最后一次提交(要修改的提交):

git update-ref HEAD HEAD^

然后推送修改后的提交,没有冲突。

注意:这假设在此期间没有人拉过错误的提交。如果他们有,他们将不得不再次倒带并再次拉动,可能会合并他们自己的更改。

于 2022-02-28T00:42:44.640 回答