ChatGPT解决这个技术问题 Extra ChatGPT

变基后无法推送到分支

我们使用 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

编辑

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

developer1 在 myNewFeature 上工作 developer2 在 hisNewFeature 上工作都使用 master 作为主分支

developer2 将 myNewFeature 合并到 hisNewFeature

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

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

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

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

T
Trevor Norris

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

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 历史不匹配)时,您必须强制 push 用从 git rebase 生成的新历史覆盖以前的历史。
L
Learath2

您需要强制推送,因为您已将提交进一步移到 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 做什么?
M
Matthew Sanders

这里要记住的主要事情是 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

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


上面的删除和重新创建选项对我来说效果很好。我的回购不允许强制!
T
ThiefMaster

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

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


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

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

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

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

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


S
Sylvain Lesage

我同意 MrCholo,也许 Trevor Norris 可以考虑更新其 good answer 以替换

git push -f origin devel0

git push --force-with-lease origin devel0

g
gordy

因为这个线程是 this google search 的唯一结果,所以对于任何疯狂滚动的人来说,我只是将这个命令放在其他命令中:

git reset --soft HEAD~1

取消提交您的更改,您的文件将不会被修改,如果您运行 git status,它们将恢复为已编辑的状态