变基后无法推送到分支

Posted

技术标签:

【中文标题】变基后无法推送到分支【英文标题】:can't push to branch after rebase 【发布时间】:2013-02-15 02:05:22 【问题描述】:

我们使用 git 并有一个 master 分支和 developer 分支。我需要添加一个新功能,然后将提交变基到 master,然后将 master 推送到 CI 服务器。

问题是,如果我在 rebase 期间发生冲突,我无法在 rebase 完成后推送到我的远程开发人员分支(在 Github 上),直到我拉出我的远程分支。这会导致重复提交。当没有冲突时,按预期工作。

问题:在 rebase 和冲突解决之后,如何在不创建重复提交的情况下同步本地和远程开发人员分支

设置:

// master branch is the main branch
git checkout master
git checkout -b myNewFeature

// I will work on this at work and at home
git push origin myNewFeature

// work work work on myNewFeature
// master branch has been updated and will conflict with myNewFeature
git pull --rebase origin master

// we have conflicts
// solve conflict
git rebase --continue

//repeat until rebase is complete
git push origin myNewFeature

//ERROR
error: failed to push some refs to 'git@github.com:ariklevy/dropLocker.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

// do what git says and pull
git pull origin myNewFeature

git push origin myNewFeature

// Now I have duplicate commits on the remote branch myNewFeature

编辑

所以听起来这会破坏工作流程:

开发者 1 正在开发 myNewFeature developer2 正在开发 hisNewFeature 都使用master作为主分支

developer2 将 myNewFeature 合并到 hisNewFeature 中

developer1 变基,解决冲突,然后为 myNewFeature 强制推送到远程分支

几天后,developer2 再次将 myNewFeature 合并到 hisNewFeature 中

这会不会导致其他开发者讨厌 developer1?

【问题讨论】:

不是一个解决方案,只是一个想法。谁是we?你的团队不仅仅是你吗? they 说(比我了解更多的人)如果你分享你的代码,那么你不应该使用 rebase。你为什么不直接做git pullgit merge 对不起,我们 = 开发团队 所以是的,当你共享代码时可能不应该变基。这可能会导致您必须执行下面列出的操作(force 推送) 哦,对不起,当他们说rewriting history时,那是rebase 正如他所说,这是他自己的开发分支,因此除非有人将其合并,否则这应该不是问题。 【参考方案1】:

我同意MrCholo,也许Trevor Norris 可以考虑更新它的good answer 来代替

git push -f origin devel0

git push --force-with-lease origin devel0

【讨论】:

【参考方案2】:

这里要记住的主要事情是 pull 和 rebase 在幕后做了什么。

拉取基本上会做两件事:获取和合并。当您包含 --rebase 时,它​​将执行变基而不是合并。

rebase 非常类似于存储分支后的所有本地更改,将分支快速转发到目标上的最新提交,然后按顺序取消存储更改。

(这解释了为什么在执行 rebase 时可能会收到多个冲突解决提示,而不是在合并时可能会收到一个冲突解决提示。您有机会解决正在 rebase 的每个提交的冲突,以便以其他方式保留你的提交。)

您永远不想将重新设置的更改推送到远程分支,因为这是重写历史。 Ofcoarse, never is a bit strong 因为几乎总是有例外。例如,您需要维护本地存储库的远程版本以在特定环境中工作的情况。

这将要求您有时使用强制推送重新设置的更改:

git push -f origin newfeature

或者在某些情况下,您的管理员可能已移除强制功能,因此您必须删除并重新创建:

git push origin :newfeature
git push origin newfeature

在任何一种情况下,如果其他人在您的远程分支上与您合作,您必须绝对确定您知道自己在做什么。这可能意味着您最初与合并一起工作,并将它们重新设置为更易于管理的提交格式,然后再去掌握和删除您的工作分支。

请记住,您几乎总是可以通过以下方式回退到 git 的 GC:

git reflog

这是一个巨大的救命稻草,因为如果您在所有变基/冲突管理中迷失方向,您可以重置回更稳定的状态。

【讨论】:

上面的删除和重新创建选项对我来说效果很好。我的回购不允许强制!【参考方案3】:

已经给出的一般答案——在推送重新设置的更改时使用git push -f origin myNewFeature——是一个很好的起点。我写这个答案是为了解决关于它是否会破坏你的工作流程的编辑。

如果我们假设您将使用 git pull --rebase ...(或其他一些变体)然后强制推送到远程分支,那么在您的示例中破坏工作流的事情是 developer2 正在合并 @ 987654323@ 转为hisNewFeature。只要没有其他人在该分支上工作,就能够重新定位您自己的功能分支是有意义的,因此您需要规则来划分分支领域。

您可以通过以下方式解决此问题:a) 建立一个仅从 master 合并的规则,或 b) 创建一个集体 develop 分支,并以此为基础建立您自己的 myNewFeature 分支,并建立一个规则你只从develop合并。然后master 将仅保留用于里程碑或发布(或者您想要设置的其他内容),develop 将是您在准备好集成到其他功能分支时推送每个功能的地方。

我相信这可以被视为 Gitflow 工作流程的简化版本。

【讨论】:

【参考方案4】:

首先,您和您的合作伙伴需要就主题/开发分支是用于共享开发还是仅用于您自己的开发达成一致。其他开发人员知道不要合并到我的开发分支上,因为它们随时会被重新定位。通常工作流程如下:

o-----o-----o-----o-----o-----o       master
 \
   o-----o-----o                      devel0
                \
                  o-----o-----o       devel1

然后,为了与遥控器保持同步,我将执行以下操作:

 git fetch origin
 git checkout master
 git merge --ff origin/master

我这样做有两个原因。首先是因为它允许我查看是否有远程更改,而无需从我的 devel 分支切换。其次,这是一种安全机制,可确保我不会覆盖任何未隐藏/提交的更改。另外,如果我不能快进合并到 master 分支,这意味着要么有人重新设置了远程 master 的基础(为此他们需要被严厉地鞭打),或者我不小心提交给 master 并需要清理我的结束。

然后当远程发生变化并且我已经快速转发到最新的时,我将重新设置:

git checkout devel0
git rebase master
git push -f origin devel0

然后其他开发人员知道他们需要从我的最新版本中重新定位他们的开发分支:

git fetch <remote>
git checkout devel1
git rebase <remote>/devel0

这会导致更清晰的历史记录:

o-----o                                 master
       \
         o-----o-----o                  devel0
                      \
                        o-----o-----o   devel1

不要随心所欲地来回合并提交。它不仅会创建重复提交并使历史无法跟踪,而且几乎不可能从特定更改中找到回归(这就是您首先使用版本控制的原因,对吗?)。您遇到的问题就是这样做的结果。

另外,听起来其他开发人员可能正在对您的开发分支进行提交。你能确认一下吗?

合并的唯一时间是当您的主题分支准备好被master接受时。

附带说明。如果多个开发人员提交到同一个存储库,您都应该考虑使用命名分支来区分开发人员的开发分支。例如:

git branch 'my-name/devel-branch'

因此,所有开发人员的主题分支都位于他们自己的嵌套集中。

【讨论】:

“另外,听起来其他开发人员可能正在对您的开发分支进行提交。您能确认一下吗?”是的,他们是…… 你还让我注意到另一个问题。在办公室和家之间工作。我在这两个地方进行合并,并在一天结束时推动,以便我可以从我离开的地方继续。然后,当需要 rebase 时,所有这些提交都会造成混乱。我需要将我的分支视为一个分支并变基 @Matt 是的,这两个问题真的会搞砸你的工作流程。首先,我会与其他开发人员沟通,只有所有者才能提交到命名分支(例如“matt/devel”)。恕我直言,无论如何,没有两个开发人员应该提交到同一个分支。只会造成混乱。对于后者,变基和强制推送应该使两个位置保持最新。 很好的答案。我有一个附带问题,为什么你在使用git push -f origin devel0 时使用--force 标志? @Nobita 当git push 无法快进(即sha 历史不匹配)时,您必须强制推送以用git rebase 生成的新历史覆盖以前的历史。 【参考方案5】:

您需要强制推送,因为您已将提交进一步移到 git 期望您将提交添加到分支的尖端。 git push -f origin myNewFeature 会解决你的问题。

提示:以上是强制使用的合法用法。永远不要在可公开访问的存储库上重写历史记录,否则很多人会讨厌你。

【讨论】:

我发现这是维护工作流程的最佳方式。 谢谢伙计。我使用此命令强制我重新定位的本地分支到同一个远程分支。 使用git push --force-with-lease比使用git push --force安全得多 git push --force-with-lease origin HEAD - 假设您的目标分支已经签出 @LucaciSergiu --force-with-lease 做什么?【参考方案6】:

你需要执行强制推送,即git push -f origin myNewFeature

哦,你最好确保人们不会基于你的 dev 分支做任何事情——通常你不应该发布你正在重写历史的分支(或者更确切地说,一旦发布就不要重写历史)。一种方法是使用像 wip/myNewFeature 这样的分支名称,然后提到 wip 分支将不时重新设置为 master。

【讨论】:

使用git push --force-with-lease比使用git push --force安全得多 @MrCholo 人们不会开始使用它,直到 git 为其添加一个简短的选项,例如 -f 用于正常强制推送:) 哈哈,是的,我在自动脚本中使用了它

以上是关于变基后无法推送到分支的主要内容,如果未能解决你的问题,请参考以下文章

功能分支变基后 Git 推送被拒绝

删除坏变基后引入的重复提交

无法将 git 分支重命名为“master”,以错误的名称推送到远程

将不同的分支推送到 Heroku

git - 将某个分支推送到远程的某个分支

如何将文件从主分支推送到另一个分支?