在执行git commit --amend之后再执行git push的情况下,如何解决“Your branch and 'origin/master' have diverged”这个问题?

编程语言 2026-07-09

我做了一些修改,导致产生了若干提交。然后我已经把它推送到了裸仓库。

edit 1
git commit -a
edit 2
git commit -a
git push

随后,我对已经推送到裸仓库的最近一次提交进行了修订。然后又做了一些改动并提交。

edit 3
git commit --amend
edit 4
git commit -a
edit 5
git commit -a

我知道不应该修改已经推送的提交,但我确实这么做了。

Git的状态现在显示分支已经分叉

git status

On branch master
Your branch and 'origin/master' have diverged,
and have 6 and 1 different commits each, respectively.
  (use "git pull" if you want to integrate the remote branch with yours)

nothing to commit, working tree clean

我该如何解决这种情况?

解决方案

Fix is to either: be forced (to roll-back) or to force it.

  1. If, and only if you have not yet pruned the repo, (can be automatic by git's garbage collection, e.g., git gc and manual via a git prune, etc.), then you may be able to roll back the commit. Otherwise skip to option 2.

从提交历史中选择一个之前的点(例如,在查找已amend的提交时的线索:使用类似 git log --topo-order --graph --all --reflog 之类的更详细描述,找到最近的一个有效提交)

例如如果远端(origin/master)仍处于编辑的第3 次状态(+1差异),它可能看起来像这样(为便于说明而简化):

console $ git log --topo-order --graph --all # log abriviated for space * commit 12345678 edit 5 (HEAD -> master) | | * commit 23456789 edit 4 |/ | * commit 56783948 other-work (origin/master, origin/HEAD) | * commit 2345678A edit 3 |/ | * commit 2345678B edit 2 |/ | * commit 2345678C edit 1 |/ * commit root (probably need to add --boundary to see this kind of root)

你可以回滚到编辑的第3 次(你之前的版本):

bash # from edit 5 # first backup your changes (-M to force move the local diverged copy to some other name can work too if you are on a different branch from master already) git branch my-edit-5 # force off of the diverged branch git checkout --force my-edit-5 # remove the local diverged branch (unless -M was used already) git branch -D master # now re-checkout "master" (by default this will select the origin/master and create a new ./master setup to track the origin master, otherwise you must manually do all that) git checkout master || git checkout -B master origin/master # check that it is rolled back git status # should say you are behind by 1 and can use git pull, so let's pull git pull # done: you are no longer diverged on your master branch # # OPTIONAL: now you can try to merge in from the other branch (locally, as it still probably tracks origin/master) git merge --no-ff -- my-edit-5 master # if all goes well it will merge as normal, otherwise # don't bother merging git merge --abort 2. Here is my recommendation from your specific example (adjust branch names as needed):

下面给出基于你这个 具体 示例的建议(根据需要调整分支名):

bash #setup git fetch --all --no-prune git branch temp-name-that-is-unique-and-unused git checkout --force temp-name-that-is-unique-and-unused # backup old git git branch -M master old-master-5 # throw out any untracked mess git --unset-upstream old-master-5 # jump to upstream git checkout --force -B master origin/master # clean up git branch -D temp-name-that-is-unique-and-unused git fetch --all --no-prune # check everything is ok git log --branches --tags --topo-order --stat --notes --graph --show-signature --all --reflog 3. What if you need those changes on old-master-5?

(This being why you should not have used git commit --amend.)

警告:我通常会给我的git服务器设置保护(例如,即使GitHub的仓库也可以配置来防止这种情况,但默认并非如此),以阻止我接下来要解释的做法;这本来就非常危险。

There is a --force option to git push you can use to force your local copy to the server. But if you force it, there will be no undo afterwards.

有一个 --force 选项,可以用来强制把本地副本推送到服务器到 git push。但如果你强制执行,之后就没有撤销的机会。

You could also try using git push --atomic --force and the amended commit will be forced to the remote (and --atomic is critical to prevent causing harder to fix issues here).

你也可以尝试使用 git push --atomic --force,修改后的提交将被强制推送到远端(而 --atomic 对防止在这里引发更难以修复的问题至关重要)。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章