如何将修改后的提交推送到远程 Git 存储库?
当我对源代码进行一些处理后,我做了我通常做的事情提交,然后推送到远程存储库。 但后来我注意到我忘记在源代码中组织我的导入。 因此,我执行修改命令来替换以前的提交:
> 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/'
我该怎么办? (我可以访问远程存储库。)
When I've worked a bit with my source code, I did my usual thing commit and then I pushed to a remote repository. But then I noticed I forgot to organize my imports in the source code. So I do the amend command to replace the previous commit:
> git commit --amend
Unfortunately the commit can't be pushed back to the repository. It is rejected like this:
> 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/'
What should I do? (I can access the remote repository.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(21)
实际上,我曾经使用
--force
和.git
存储库进行推送,并被 Linus 责骂了BIG TIME。 一般来说,这会给其他人带来很多问题。 一个简单的答案是“不要这样做”。我看到其他人给出了这样做的秘诀,所以我不会在这里重复。 但这里有一个提示,可以帮助您在使用 --force (或 +master)推出修改后的提交后从这种情况中恢复。
git reflog
查找您修改的旧提交(将其称为old
,我们将调用您通过修改new
创建的新提交)。old
和new
之间创建一个合并,记录new
的树,就像git checkout new && git merge -s 我们的旧的
。git merge master
将其合并到您的 master 使用git push 使用结果更新您的 master。 HEAD:master
然后,那些不幸将他们的工作建立在您通过修改和强制推送而删除的提交上的人将看到最终的合并,他们将看到您更喜欢
new
而不是old
。 他们以后的合并不会看到由于您的修改而导致的old
和new
之间的冲突,因此他们不必遭受损失。I actually once pushed with
--force
and.git
repository and got scolded by Linus BIG TIME. In general this will create a lot of problems for other people. A simple answer is "Don't do it".I see others gave the recipe for doing so anyway, so I won't repeat them here. But here is a tip to recover from the situation after you have pushed out the amended commit with --force (or +master).
git reflog
to find the old commit that you amended (call itold
, and we'll call the new commit you created by amendingnew
).old
andnew
, recording the tree ofnew
, likegit checkout new && git merge -s ours old
.git merge master
git push . HEAD:master
Then people who were unfortunate enough to have based their work on the commit you obliterated by amending and forcing a push will see the resulting merge will see that you favor
new
overold
. Their later merges will not see the conflicts betweenold
andnew
that resulted from your amending, so they do not have to suffer.您正在看到 Git 安全功能。 Git 拒绝用您的分支更新远程分支,因为您的分支的头提交不是您要推送到的分支的当前头提交的直接后代。
如果不是这种情况,那么大约在同一时间推送到同一个存储库的两个人将不知道同时有一个新的提交进入,并且最后推送的人将失去前一个推送者的工作,而无需执行任何操作。他们意识到了这一点。
如果您知道自己是唯一一个推送的人,并且想要推送修改后的提交或推送回滚分支的提交,则可以使用
-f
开关。即使这样也可能不起作用,因为 Git 允许远程存储库通过使用配置变量 receive.denynonfastforwards 拒绝远端的非快进推送。 如果是这种情况,拒绝原因将如下所示(请注意“远程拒绝”部分):
要解决此问题,您要么需要更改远程存储库的配置,要么作为肮脏的黑客,您可以删除并重新创建分支,如下所示:
一般来说,
git push
的最后一个参数使用格式:
,其中local_ref
是分支的名称在本地存储库上,remote_ref
是远程存储库上分支的名称。 该命令对使用两个简写。:master
有一个 null local_ref,这意味着将一个 null 分支推送到远程端master
,即删除远程分支。 没有:
的分支名称表示将具有给定名称的本地分支推送到具有相同名称的远程分支。 在这种情况下,master
是master:master
的缩写。You are seeing a Git safety feature. Git refuses to update the remote branch with your branch, because your branch's head commit is not a direct descendent of the current head commit of the branch that you are pushing to.
If this were not the case, then two people pushing to the same repository at about the same time would not know that there was a new commit coming in at the same time and whoever pushed last would lose the work of the previous pusher without either of them realising this.
If you know that you are the only person pushing and you want to push an amended commit or push a commit that winds back the branch, you can 'force' Git to update the remote branch by using the
-f
switch.Even this may not work as Git allows remote repositories to refuse non-fastforward pushes at the far end by using the configuration variable
receive.denynonfastforwards
. If this is the case the rejection reason will look like this (note the 'remote rejected' part):To get around this, you either need to change the remote repository's configuration or as a dirty hack you can delete and recreate the branch thus:
In general the last parameter to
git push
uses the format<local_ref>:<remote_ref>
, wherelocal_ref
is the name of the branch on the local repository andremote_ref
is the name of the branch on the remote repository. This command pair uses two shorthands.:master
has a null local_ref which means push a null branch to the remote sidemaster
, i.e. delete the remote branch. A branch name with no:
means push the local branch with the given name to the remote branch with the same name.master
in this situation is short formaster:master
.快速咆哮:没有人在这里发布简单的答案这一事实表明了 Git CLI 所表现出的绝望的用户敌意。
无论如何,假设您没有尝试强制推动,“明显”的方法就是先拉动。 这会拉出您修改过的更改(因此不再有),以便您再次拥有它。
解决所有冲突后,您可以再次推送。
所以:
如果你在拉取时遇到错误,可能是你的本地存储库配置出了问题(我在 .git/config 分支部分有一个错误的引用)。
也许
你会得到一个额外的提交,主题是关于“琐碎的合并”。
Quick rant: The fact that no one has posted the simple answer here demonstrates the desperate user-hostility exhibited by the Git CLI.
Anyway, the "obvious" way to do this, assuming you haven't tried to force the push, is to pull first. This pulls the change that you amended (and so no longer have) so that you have it again.
Once you have resolved any conflicts, you can push again.
So:
If you get errors in pull, maybe something is wrong in your local repository configuration (I had a wrong ref in the .git/config branch section).
And after
Maybe you will get an extra commit with the subject telling about a "Trivial merge".
简短的回答:不要将修改后的提交推送到公共仓库。
长答案:一些 Git 命令,例如 git commit --amend 和 git rebase,实际上重写了历史图。 只要您还没有发布您的更改,这就没问题,但是一旦您发布了,您真的不应该乱搞历史记录,因为如果有人已经得到了您的更改,那么当他们再次尝试拉取时,可能会失败。 您不应该修改提交,而应该使用更改进行新的提交。
但是,如果您真的非常想推送修改后的提交,您可以这样做:
前导
+
符号将强制推送发生,即使它不会导致“快速” -转发”提交。 (当您推送的更改是公共存储库中已有更改的直接后代时,就会发生快进提交。)Short answer: Don't push amended commits to a public repo.
Long answer: A few Git commands, like
git commit --amend
andgit rebase
, actually rewrite the history graph. This is fine as long as you haven't published your changes, but once you do, you really shouldn't be mucking around with the history, because if someone already got your changes, then when they try to pull again, it might fail. Instead of amending a commit, you should just make a new commit with the changes.However, if you really, really want to push an amended commit, you can do so like this:
The leading
+
sign will force the push to occur, even if it doesn't result in a "fast-forward" commit. (A fast-forward commit occurs when the changes you are pushing are a direct descendant of the changes already in the public repo.)这是在进行
commit --amend
后推送更改的一种非常简单且干净的方法:它执行以下操作:
如果将此应用到不同的分支或远程,请记住更改
origin
和master
。Here is a very simple and clean way to push your changes after you have already made a
commit --amend
:Which does the following:
Remember to change
origin
andmaster
if applying this to a different branch or remote.我通过放弃本地修改的提交并在顶部添加新的更改来解决这个问题:
I have solved it by discarding my local amended commit and adding the new changes on top:
如果要更改的消息是针对存储库的最新提交,则将执行以下命令:
注意:不建议使用 --force ,除非您完全确定没有其他人有在最新提交后克隆您的存储库。
更安全的替代方法是使用:
与
--force
不同,--force
会破坏其他人推送到分支的任何更改,--force-with-lease
将中止,如果存在是对存储库的上游更改。If the message to be changed is for the latest commit to the repository, then the following commands are to be executed:
Note: using --force is not recommended unless you are absolutely sure that no one else has cloned your repository after the latest commit.
A safer alternative is to use:
Unlike
--force
, which will destroy any changes someone else has pushed to the branch,--force-with-lease
will abort if there was an upstream change to the repository.我有同样的问题。
。作为一个 Git 新手,我认为它已经完成了 FUBAR。
解决方案:有点像@bara建议+创建了一个本地备份分支
也许这不是一个快速干净的解决方案,我丢失了我的历史记录(1次提交而不是5次),但它节省了一天的工作。
I had the same problem.
As a Git-newbie, I thought it was complete FUBAR.
Solution: Somewhat like @bara suggested + created a local backup branch
Maybe it's not a fast and clean solution, and I lost my history (1 commit instead of 5), but it saved a day's work.
如果您尚未将代码推送到远程分支 (GitHub/Bitbucket),您可以在命令行上更改提交消息,如下所示。
如果您正在处理特定分支,请执行以下操作:
如果您已经推送了带有错误消息的代码,那么在更改消息时需要小心。 即,在更改提交消息并尝试再次推送后,您最终会遇到问题。 为了使其顺利,请按照以下步骤操作。
请在执行此操作之前阅读整个答案
重要说明:当您直接使用强制推送时,您可能会遇到其他开发人员在同一分支上工作的代码问题。 因此,为了避免这些冲突,您需要在强制推送之前从分支中提取代码:
这是更改提交消息(如果已推送)的最佳实践。
If you have not pushed the code to your remote branch (GitHub/Bitbucket) you can change the commit message on the command line as below.
If you're working on a specific branch, do this:
If you've already pushed the code with a wrong message then you need to be careful when changing the message. i.e after you change the commit message and try pushing it again you end up with having issues. To make it smooth follow the following steps.
Please read the entire answer before doing it
Important note: When you use the force push directly you might end up with code issues that other developers are working on the same branch. So to avoid those conflicts you need to pull the code from your branch before making the force push:
This is the best practice when changing the commit message, if it was already pushed.
您可以通过以下方式以简单且安全的方式完成此操作:
git commit --amend
修改您的最后一次提交,以及添加git pull
来同步本地的 任何选项存储库与您的远程存储库。git push
现在您的本地和远程存储库已更新,无需更改存储库历史记录。
You can do it in a simple and safe way by doing:
git commit --amend
and whatever options you need to addgit pull
to sync your local repo with your remote repo.git push
Now your local and remote repo are updated with no need to change your repo history.
如果您使用 Visual Studio Code,可以尝试此扩展以使其更轻松。
https://marketplace.visualstudio.com/items?itemName =cimdalli.git-commit-amend-push-force
从名字上就可以理解,它是连续执行命令的
git commit --amend
git push --force
If you are using Visual Studio Code, you can try this extension to make it easier.
https://marketplace.visualstudio.com/items?itemName=cimdalli.git-commit-amend-push-force
As you can understand from its name, it executes commands consecutively
git commit --amend
git push --force
如果您知道没有人拉取您未修改的提交,请使用
git push
的--force-with-lease
选项。在 TortoiseGit 中,您可以在“推送...”选项“强制:可能丢弃”下执行相同的操作并检查“已知更改”。
If you know nobody has pulled your un-amended commit, use the
--force-with-lease
option ofgit push
.In TortoiseGit, you can do the same thing under "Push..." options "Force: May discard" and checking "known changes".
在这种情况下,你应该--force。
基于:
如果是个人项目,我会这样做:
git push origin <分支名称>; -f
如果您正在与您的团队合作,或者其他同行正在审查和使用您的代码,则不建议使用
force
标志。 主要是因为你总是想要一个干净的 git 历史记录。我会做什么?
git commit --amend
,然后git push -f ...
并让人们知道他们需要 git pull --rebase 才能看到您的更改。squash
来清理历史记录。In this case, you should --force.
Based on:
If it is an individual project, I would do this:
git push origin <branch-name> -f
If you are working with your team, or other peers are reviewing and using your code the
force
flag is not recommended. Mainly because you always want a clean git history.What I would do?
git commit --amend
, thengit push -f ...
and let people know that they need togit pull --rebase
to be able to see your changes.squash
to clean up history.您收到此错误是因为 Git 远程已有这些提交文件。 您必须强制推送分支才能使其工作:
还要确保从远程提取代码,因为团队中的其他人可能已推送到同一分支。
这是我们必须强制将提交推送到远程的情况之一。
You are getting this error because the Git remote already has these commit files. You have to force push the branch for this to work:
Also make sure you pull the code from remote as someone else on your team might have pushed to the same branch.
This is one of the cases where we have to force push the commit to remote.
在您已经进行了
git add "your files"
和git commit --amend
后,这是一种非常简单且干净的方法来推送更改:或者:
Here is a very simple and clean way to push your changes after you have already made a
git add "your files"
andgit commit --amend
:or:
我必须通过从远程存储库中拉取来解决这个问题,并处理出现的合并冲突,提交然后推送。 但我觉得有更好的方法。
I had to fix this problem with pulling from the remote repo and deal with the merge conflicts that arose, commit and then push. But I feel like there is a better way.
我只是继续做 Git 告诉我做的事情。 所以:
“合并”)并推送它。
注意:修改后的提交是最新的。
I just kept doing what Git told me to do. So:
"merge") and push it.
Note: The amended commit was the latest one.
在更改提交的作者和提交者时,以下内容对我有用。
git push -f origin master
Git 足够聪明,能够发现这些是相同增量的提交,仅在元信息部分有所不同。
本地和远程负责人都指出了有问题的提交。
The following worked for me when changing Author and Committer of a commit.
git push -f origin master
Git was smart enough to figure out that these were commits of identical deltas which only differed in the meta information section.
Both the local and remote heads pointed to the commits in question.
在这里,我如何修复先前提交中的编辑:
保存到目前为止的工作。
如果进行了更改,请暂时隐藏:
git stash
现在,您的工作副本在上次提交的状态下是干净的。进行编辑和修复。
以“amend”模式提交更改:
git commit --all --amend
您的编辑器将询问日志消息(默认情况下,旧的日志消息)。 当您对编辑器感到满意时,保存并退出编辑器。
新的更改将添加到旧的提交中。 使用
git log
和git diff HEAD^
亲自查看
重新应用隐藏的更改(如果已进行):
git stash apply
Here, How I fixed an edit in a previous commit:
Save your work so far.
Stash your changes away for now if made:
git stash
Now your working copy is clean at the state of your last commit.Make the edits and fixes.
Commit the changes in "amend" mode:
git commit --all --amend
Your editor will come up asking for a log message (by default, the old log message). Save and quit the editor when you're happy with it.
The new changes are added on to the old commit. See for yourself with
git log
andgit diff HEAD^
Re-apply your stashed changes, if made:
git stash apply
为了避免强制推送,请在远程裸存储库中使用以下命令删除最后一次提交(要修改的提交):
然后推送修改后的提交而不发生冲突。
注意:这假设在此期间没有人拉取错误的提交。 如果他们这样做了,他们将不得不类似地倒回并再次拉动,可能会合并他们自己的更改。
To avoid forced push, in the remote bare repository remove the last commit (the one to be amended) using:
then push the amended commit with no conflict.
Note: This assumes no one has pulled the wrong commit in the meantime. If they have, they will have to similarly rewind and pull again, possibly merging their own changes.
只需删除远程分支
,然后推送修改后的分支即可。
Just delete the remote branch
and then push your amended branch.