如何将修改后的提交推送到远程Git存储库?

时间:2008-10-31 10:23:14

标签: git git-commit amend

当我使用我的源代码工作时,我做了我惯常的事情提交,然后我推送到远程存储库。但后来我注意到我忘了在源代码中组织我的导入。所以我做了修改命令来替换先前的提交:

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

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

15 个答案:

答案 0 :(得分:456)

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

我看到别人给出了这样做的秘诀,所以我不会在这里重复。但是这里有一个提示,可以在之后恢复你用--force(或+ master)推出修改后的提交。

  1. 使用git reflog查找您修改的旧提交(称之为old,我们将通过修改new来调用您创建的新提交。)
  2. oldnew之间创建合并,记录new的树,如git checkout new && git merge -s ours old
  3. 使用git merge master
  4. 将其合并到您的主人
  5. 使用git push . HEAD:master
  6. 的结果更新您的主人
  7. 推出结果。
  8. 然后,那些不幸的人将你的工作建立在你通过修改和强制推动而被删除的提交上的工作将会看到所产生的合并将会使你new超过old。他们以后的合并将不会发现您修改后oldnew之间的冲突,因此他们不必受到影响。

答案 1 :(得分:253)

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

如果情况并非如此,那么两个人几乎同时推到同一个存储库就不会知道同时有新的提交进入,推送最后一个会丢失前一个推送器的工作没有他们意识到这一点。

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

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的最后一个参数使用格式<local_ref>:<remote_ref>,其中local_ref是本地存储库中分支的名称,remote_ref是远程存储库上的分支。此命令对使用两个shorthands。 :master具有null local_ref,这意味着将空分支推送到远程端master,即删除远程分支。没有:的分支名称意味着将具有给定名称的本地分支推送到具有相同名称的远程分支。在这种情况下,mastermaster:master的缩写。

答案 2 :(得分:201)

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

无论如何,假设你没有试图强行推动,“明显”做到这一点的方法就是先拉。这会拉动您修改的更改(因此不再具有),以便您再次使用它。

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

所以:

git pull

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

之后

git push

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

答案 3 :(得分:97)

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

答案很长:一些Git命令,如git commit --amendgit rebase,实际上会重写历史图表。只要你没有公布你的更改,这很好,但是一旦你做了,你真的不应该在历史记录中徘徊,因为如果有人已经得到你的改变,那么当他们试图再次拉动时,它可能会失败。您应该只使用更改进行新的提交,而不是修改提交。

但是,如果你真的想要推送修改后的提交,你可以这样做:

$ git push origin +master:master

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

答案 4 :(得分:43)

在您创建commit --amend后,这是一种非常简单明了的推送方法:

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

以下是:

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

记得要改变&#34;起源&#34;和#34;主人&#34;如果将此应用于其他分支或远程。

答案 5 :(得分:21)

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

# 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

答案 6 :(得分:7)

我遇到了同样的问题。

  • 意外修改了已经推送的最后一次提交
  • 在本地完成了很多更改,提交了五次
  • 试图推送,得到错误,惊慌失措,合并远程,得到了很多非我的文件,推送,失败等等。

作为Git-newbie,我认为它是完整的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次),但它节省了一天的工作。

答案 7 :(得分:5)

如果您还没有将代码推送到远程分支(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

这是更改提交消息的最佳做法,如果它已被推送。

答案 8 :(得分:5)

如果您知道没有人撤消未经修改的提交,请使用--force-with-lease的{​​{1}}选项。

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

  

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

答案 9 :(得分:3)

您收到此错误,因为Git远程已有这些提交文件。你必须强行推动分支才能发挥作用:

git push -f origin branch_name

另外请确保您从远程提取代码,因为您团队中的其他人可能已将其推送到同一分支。

git pull origin branch_name

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

答案 10 :(得分:3)

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

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

您可以从其名称中了解到,它可以连续执行命令

  • git commit --amend
  • git push --force

答案 11 :(得分:2)

在您完成git add "your files"git commit --amend后,这是一种非常简单明了的推送方式:

git push origin master -f

或:

git push origin master --force

答案 12 :(得分:1)

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

答案 13 :(得分:1)

我一直在做Git告诉我要做的事情。所以:

  • 因修改提交而无法推送。
  • 我按照建议拉。
  • 合并失败。所以我手动修复它。
  • 创建新提交(标记为 &#34;合并&#34;)并推送它。
  • 好像有效!

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

答案 14 :(得分:1)

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

git push -f origin master

Git很聪明,可以弄清楚这些是相同增量的提交,只是在元信息部分有所不同。

本地和远程负责人都指出了相关的提交。