更新被拒绝,因为您当前分支的提示落后了 - 但为什么呢?
Updates were rejected because the tip of your current branch is behind - but why?
这个问题已经从另一个角度回答了here。但我的问题是首先试图理解为什么会出现这个问题。我在工作中一直 运行 关注这个问题,建议的解决方案并不过分令人满意,因为它并没有真正解决问题本身,并且有丢失提交的危险。
下面是我发现重现错误的最短 git 交互序列:
git clone git@github.com:joyofdata/test3.git
cd test3
echo "1" > m
git add .
git commit -m "m1"
git push origin master
git checkout -b feature
git push -u origin feature
echo "1" > f
git add .
git commit -m "f1"
git rebase master
git push origin feature
git checkout master
echo "2" >> m
git add .
git commit -m "m2"
git push origin master
git checkout feature
echo "2" >> f
git add .
git commit -m "f2"
git rebase master
git push origin feature (error - see next code box)
我只是在 master 中对文件 m 进行版本化,然后在 feature 中对文件 f 进行版本化,然后在 master 中提交更改,然后在 feature 中提交更改。现在,在将我的更改推送到远程功能分支之前,我想将其重新设置为 master。
这是上面列表中最后一个命令的命令和错误消息:
➜ test3 git:(feature) git push origin feature
To github.com:joyofdata/test3.git
! [rejected] feature -> feature (non-fast-forward)
error: failed to push some refs to 'git@github.com:joyofdata/test3.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
现在 - 我尝试通过首先从远程功能中拉取(如消息中所建议的)来解决问题,然后解决冲突,推送到功能:
➜ test3 git:(feature) git pull origin feature
From github.com:joyofdata/test3
* branch feature -> FETCH_HEAD
Auto-merging f
CONFLICT (add/add): Merge conflict in f
Automatic merge failed; fix conflicts and then commit the result.
➜ test3 git:(feature) ✗ vim f
➜ test3 git:(feature) ✗ git add .
➜ test3 git:(feature) git commit -m "deconflicted"
[feature 3fb647e] deconflicted
➜ test3 git:(feature) git push origin
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 565 bytes | 565.00 KiB/s, done.
Total 5 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), done.
To github.com:joyofdata/test3.git
0f31f60..3fb647e feature -> feature
但是 - 从现在开始 - 我将一次又一次地 运行 一次又一次地进入那个错误,每次我在 master 上重新设置功能 - 再次是合并冲突,再次是那个错误。
➜ test3 git:(feature) git rebase master
First, rewinding head to replay your work on top of it...
Applying: f1
Applying: f1
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
No changes -- Patch already applied.
Applying: f2
➜ test3 git:(feature) git push origin
To github.com:joyofdata/test3.git
! [rejected] feature -> feature (non-fast-forward)
error: failed to push some refs to 'git@github.com:joyofdata/test3.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
我不明白!
我的意思是 - 我想做的只是应用以下工作流程:
- 本地功能分支的变化
- 暂存并提交更改
- git 变基大师
- git 推送原始功能
我简单地说 - 在提交远程功能之前,我想在 master 上重新设置功能。如果我将 master 合并到功能中(git pull origin master
或 git merge master
如果本地 master 是最新的)那么我不会 运行 进入那个问题。
我希望这不会太混乱,但我不知道如何说得更简单,这让我很烦。
快速回答是不要对上游分支进行变基,link 解释了问题和解决方案:
https://git-scm.com/docs/git-rebase#_recovering_from_upstream_rebase
一个基本的选择可能是这样的:
从您的示例开始,在错误行之前,分支如下所示:
$ git log --pretty=oneline --graph --all
* b5b045591ec6584e8f896d85399b7ed5b08d8098 (HEAD -> feature) f2
* 5187c95d6d91b550b9b2cc10ad673a52add620f6 f1
* cea62f3fd0349390115ee5e263730656b7a52d2d (origin/master, master) m2
| * f043b50940593c1ded4631f3681420ad57c0b190 (origin/feature) f1
|/
* 4847339d95d8f02c25538da7e51be14cbb30530d m1
执行时
$ git push origin feature
您尝试包含从分支功能到 origin/feature 的更改,这是不可能的,因为它们有不同的提交。
所以可以删除远程分支origin/feature
取消设置上游
$ git checkout feature
$ git branch --unset-upstream
删除远程分支
$ git push origin --delete feature
将您的更改添加到上游
$ git push -u origin feature
支线这样结束
$ git log --pretty=oneline --graph --all
* b5b045591ec6584e8f896d85399b7ed5b08d8098 (HEAD -> feature) f2
* 5187c95d6d91b550b9b2cc10ad673a52add620f6 f1
* cea62f3fd0349390115ee5e263730656b7a52d2d (origin/master, master) m2
* 4847339d95d8f02c25538da7e51be14cbb30530d m1
根据此示例,提交 b5b045 具有提交 f043b50 的更改,因此不会丢失更改,您可以检查
$ git diff f043b50 b5b045
问题的根源在于您正在重新设置 feature
。这是一种草率的表达方式:重要的不是分支名称,而是提交。但是变基通过将一些提交复制到新的和(据说)改进的不同提交来工作。这需要丢弃——或放弃——旧的(现在很糟糕)提交。
git push
命令调用另一个 Git 并向他们发送您新的和改进的 feature
提交,然后请求其他 Git 存储库到 扔掉 它旧的(现在很糟糕)提交。它说:不!如果我问你问,我会失去一些宝贵的提交! 这个投诉以这种形式返回:
! [rejected] feature -> feature (non-fast-forward)
non-fast-forward 错误是另一个 Git 告诉你的方式,如果它遵从你的礼貌请求更改它的名字 feature
来命名您建议它使用的新的和改进的提交,这将丢失旧的(被新的和改进的过时的)提交。
当然,这正是您想要它做的。注意:您是否应该 这样做取决于使用其他 Git 存储库(GitHub 上的那个)的其他人是否事先同意这即将发生。
要让另一个 Git,即 GitHub 上的那个,同意放弃其存储库中的提交,您必须在这个特定的 [=12= 上设置 "force flag" ] 手术。不过,有两种不同的强制标志:
总力:我命令你,其他Git仓库,你的分支名称要这样设置!这个简单有效,弃用不仅是旧的和糟糕的提交,你已经通过 rebase 替换为新的和改进的提交,而且其他任何人添加的提交你没有也 替换为新的和改进的副本。 (这是几个原因中的一个,每个使用此 GitHub 存储库的人都必须同意提前 将发生变基。)
Force-with-lease: 我命令你,其他 Git 存储库,将存储在你的分支名称中的哈希 ID 与我 [=62 的值进行比较=]认为 你有。如果它们相等,那么你应该用我现在提供的新值替换那个值。 这种强制推送的变体更安全:如果你重新设置了一些提交,但其他人从那时起添加了 new 提交您 失败 变基,您的强制租赁操作将失败。另一个 Git,在 GitHub,会说:我存储的哈希 ID 与你说的你认为我拥有的不匹配。所以我终究没有接受你的命令
如果您和此 GitHub 存储库的所有其他用户事先同意可以进行变基,并且您认为有人可能在您不注意的情况下偷偷提交了一些代码,您应该使用--force-with-lease
选项到 git push
以查明是否确实如此。
如果没有其他用户使用 GitHub 存储库(或者 none 他们使用 feature
分支),none 这是必需的,你可以简单地使用 git push --force
。您唯一需要同意的人就是您自己:您是否允许自己强制推送 feature
分支?如果是这样,您可以强制推送 feature
分支。
请注意,如果有 个其他用户,并且您和他们都同意此强制推送变基过程,您和他们必须 全部 注意观察任何强制更新,并对 尚未 复制到新的和改进的提交的任何提交进行自己的变基。这是一个相当复杂的工作流程;确保你和你所有的朋友/同事都准备好了。
这个问题已经从另一个角度回答了here。但我的问题是首先试图理解为什么会出现这个问题。我在工作中一直 运行 关注这个问题,建议的解决方案并不过分令人满意,因为它并没有真正解决问题本身,并且有丢失提交的危险。
下面是我发现重现错误的最短 git 交互序列:
git clone git@github.com:joyofdata/test3.git
cd test3
echo "1" > m
git add .
git commit -m "m1"
git push origin master
git checkout -b feature
git push -u origin feature
echo "1" > f
git add .
git commit -m "f1"
git rebase master
git push origin feature
git checkout master
echo "2" >> m
git add .
git commit -m "m2"
git push origin master
git checkout feature
echo "2" >> f
git add .
git commit -m "f2"
git rebase master
git push origin feature (error - see next code box)
我只是在 master 中对文件 m 进行版本化,然后在 feature 中对文件 f 进行版本化,然后在 master 中提交更改,然后在 feature 中提交更改。现在,在将我的更改推送到远程功能分支之前,我想将其重新设置为 master。
这是上面列表中最后一个命令的命令和错误消息:
➜ test3 git:(feature) git push origin feature
To github.com:joyofdata/test3.git
! [rejected] feature -> feature (non-fast-forward)
error: failed to push some refs to 'git@github.com:joyofdata/test3.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
现在 - 我尝试通过首先从远程功能中拉取(如消息中所建议的)来解决问题,然后解决冲突,推送到功能:
➜ test3 git:(feature) git pull origin feature
From github.com:joyofdata/test3
* branch feature -> FETCH_HEAD
Auto-merging f
CONFLICT (add/add): Merge conflict in f
Automatic merge failed; fix conflicts and then commit the result.
➜ test3 git:(feature) ✗ vim f
➜ test3 git:(feature) ✗ git add .
➜ test3 git:(feature) git commit -m "deconflicted"
[feature 3fb647e] deconflicted
➜ test3 git:(feature) git push origin
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 565 bytes | 565.00 KiB/s, done.
Total 5 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), done.
To github.com:joyofdata/test3.git
0f31f60..3fb647e feature -> feature
但是 - 从现在开始 - 我将一次又一次地 运行 一次又一次地进入那个错误,每次我在 master 上重新设置功能 - 再次是合并冲突,再次是那个错误。
➜ test3 git:(feature) git rebase master
First, rewinding head to replay your work on top of it...
Applying: f1
Applying: f1
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
No changes -- Patch already applied.
Applying: f2
➜ test3 git:(feature) git push origin
To github.com:joyofdata/test3.git
! [rejected] feature -> feature (non-fast-forward)
error: failed to push some refs to 'git@github.com:joyofdata/test3.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
我不明白!
我的意思是 - 我想做的只是应用以下工作流程:
- 本地功能分支的变化
- 暂存并提交更改
- git 变基大师
- git 推送原始功能
我简单地说 - 在提交远程功能之前,我想在 master 上重新设置功能。如果我将 master 合并到功能中(git pull origin master
或 git merge master
如果本地 master 是最新的)那么我不会 运行 进入那个问题。
我希望这不会太混乱,但我不知道如何说得更简单,这让我很烦。
快速回答是不要对上游分支进行变基,link 解释了问题和解决方案: https://git-scm.com/docs/git-rebase#_recovering_from_upstream_rebase
一个基本的选择可能是这样的: 从您的示例开始,在错误行之前,分支如下所示:
$ git log --pretty=oneline --graph --all
* b5b045591ec6584e8f896d85399b7ed5b08d8098 (HEAD -> feature) f2
* 5187c95d6d91b550b9b2cc10ad673a52add620f6 f1
* cea62f3fd0349390115ee5e263730656b7a52d2d (origin/master, master) m2
| * f043b50940593c1ded4631f3681420ad57c0b190 (origin/feature) f1
|/
* 4847339d95d8f02c25538da7e51be14cbb30530d m1
执行时
$ git push origin feature
您尝试包含从分支功能到 origin/feature 的更改,这是不可能的,因为它们有不同的提交。
所以可以删除远程分支origin/feature
取消设置上游
$ git checkout feature $ git branch --unset-upstream
删除远程分支
$ git push origin --delete feature
将您的更改添加到上游
$ git push -u origin feature
支线这样结束
$ git log --pretty=oneline --graph --all
* b5b045591ec6584e8f896d85399b7ed5b08d8098 (HEAD -> feature) f2
* 5187c95d6d91b550b9b2cc10ad673a52add620f6 f1
* cea62f3fd0349390115ee5e263730656b7a52d2d (origin/master, master) m2
* 4847339d95d8f02c25538da7e51be14cbb30530d m1
根据此示例,提交 b5b045 具有提交 f043b50 的更改,因此不会丢失更改,您可以检查
$ git diff f043b50 b5b045
问题的根源在于您正在重新设置 feature
。这是一种草率的表达方式:重要的不是分支名称,而是提交。但是变基通过将一些提交复制到新的和(据说)改进的不同提交来工作。这需要丢弃——或放弃——旧的(现在很糟糕)提交。
git push
命令调用另一个 Git 并向他们发送您新的和改进的 feature
提交,然后请求其他 Git 存储库到 扔掉 它旧的(现在很糟糕)提交。它说:不!如果我问你问,我会失去一些宝贵的提交! 这个投诉以这种形式返回:
! [rejected] feature -> feature (non-fast-forward)
non-fast-forward 错误是另一个 Git 告诉你的方式,如果它遵从你的礼貌请求更改它的名字 feature
来命名您建议它使用的新的和改进的提交,这将丢失旧的(被新的和改进的过时的)提交。
当然,这正是您想要它做的。注意:您是否应该 这样做取决于使用其他 Git 存储库(GitHub 上的那个)的其他人是否事先同意这即将发生。
要让另一个 Git,即 GitHub 上的那个,同意放弃其存储库中的提交,您必须在这个特定的 [=12= 上设置 "force flag" ] 手术。不过,有两种不同的强制标志:
总力:我命令你,其他Git仓库,你的分支名称要这样设置!这个简单有效,弃用不仅是旧的和糟糕的提交,你已经通过 rebase 替换为新的和改进的提交,而且其他任何人添加的提交你没有也 替换为新的和改进的副本。 (这是几个原因中的一个,每个使用此 GitHub 存储库的人都必须同意提前 将发生变基。)
Force-with-lease: 我命令你,其他 Git 存储库,将存储在你的分支名称中的哈希 ID 与我 [=62 的值进行比较=]认为 你有。如果它们相等,那么你应该用我现在提供的新值替换那个值。 这种强制推送的变体更安全:如果你重新设置了一些提交,但其他人从那时起添加了 new 提交您 失败 变基,您的强制租赁操作将失败。另一个 Git,在 GitHub,会说:我存储的哈希 ID 与你说的你认为我拥有的不匹配。所以我终究没有接受你的命令
如果您和此 GitHub 存储库的所有其他用户事先同意可以进行变基,并且您认为有人可能在您不注意的情况下偷偷提交了一些代码,您应该使用--force-with-lease
选项到 git push
以查明是否确实如此。
如果没有其他用户使用 GitHub 存储库(或者 none 他们使用 feature
分支),none 这是必需的,你可以简单地使用 git push --force
。您唯一需要同意的人就是您自己:您是否允许自己强制推送 feature
分支?如果是这样,您可以强制推送 feature
分支。
请注意,如果有 个其他用户,并且您和他们都同意此强制推送变基过程,您和他们必须 全部 注意观察任何强制更新,并对 尚未 复制到新的和改进的提交的任何提交进行自己的变基。这是一个相当复杂的工作流程;确保你和你所有的朋友/同事都准备好了。