重新基础后不能推向分支

我们使用 git,并且有一个主分支和开发人员分支。我需要添加一个新特性,然后将提交重新设置为 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 开发者2正在开发他的新功能 都是以师父为主干的

Developer2将 myNewFeature 合并到他的 NewFeature 中

Developer1重新建立基础,解决冲突,然后强制推送到 myNewFeature 的远程分支

几天后,developer2再次将 myNewFeature 合并到他的 NewFeature 中

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

111222 次浏览

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

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

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

小贴士: 以上是使用推力的合法用法。永远不要在公开可访问的存储库上重写历史,否则很多人会讨厌你。

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

一个 pull 基本上会做两件事: 提取和合并。当您包含—— rebase 时,它将执行 rebase 而不是 merge。

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

(这解释了为什么在执行 rebase 时可能会得到多个冲突解决提示,而在合并时可能只有一个冲突解决提示。您有机会解决每个提交上的冲突,这个冲突正在被重新定位,以便在其他情况下保存您的提交。)

您永远不会希望将重新基础的更改推送到远程分支,因为这将重写历史记录。粗糙,从来不是有点强,因为几乎总是有例外。例如,需要维护本地存储库的远程版本才能在特定环境中工作。

这将需要您有时使用强制方式推送重新基础的更改:

git push -f origin newfeature

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

git push origin :newfeature
git push origin newfeature

在这两种情况下,如果有人在您的远程分支上与您协作,那么您必须完全确信您知道自己在做什么。这可能意味着,在开始掌握并删除工作分支之前,您需要先使用 merge 并将它们重新设置为更易于管理的提交格式。

请记住,您几乎总是可以利用 git 的 GC:

git reflog

这是一个巨大的生命拯救器,因为如果您在所有的 rebase/冲突管理中迷失了方向,那么您可以重新设置到一个更稳定的状态。

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

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 分支切换。其次,它是一种安全机制,确保不会覆盖任何未隐藏/提交的更改。此外,如果我不能快进合并到主分支,这意味着要么有人已经重新基于远程主服务器(为此他们需要受到严厉的鞭打) ,或者我不小心提交到主服务器,需要清理我的结束。

然后,当 Remote 发生更改并快进到最新版本时,我将重新定位:

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

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

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

这导致了更清洁的历史:

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

不要随心所欲地来回提交合并。它不仅创建了重复的提交,使历史无法遵循,从特定的更改中寻找回归变得几乎不可能(这就是为什么您首先使用版本控制,对吗?).你现在的问题就是这么做的结果。

另外,听起来好像其他开发人员可能正在向您的 devel 分支提交。您能证实这一点吗?

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

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

git branch 'my-name/devel-branch'

因此,所有开发人员的主题分支都驻留在自己的嵌套集中。

已经给出的一般答案——在推动重新基础的变更时使用 git push -f origin myNewFeature——是一个很好的起点。我写这个答案,以解决编辑是否会打破你的工作流程。

如果我们假设您将使用 git pull --rebase ...(或其他变体) ,然后对远程分支进行强制推送,那么在您的示例中打破工作流的事情是 developer2正在将 myNewFeature合并到 hisNewFeature。只要没有其他人在处理您自己的特性分支,就可以重新定义您自己的特性分支,这是有意义的,因此您需要规则来划分分支领域。

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

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

我同意 丘洛先生,也许 Trevor Norris可以考虑更新它的 答得好来取代

git push -f origin devel0

git push --force-with-lease origin devel0

因为这个线程是 这个谷歌搜索的唯一结果,我只是这个命令是其中之一,任何人疯狂滚动通过:

git reset --soft HEAD~1

取消提交您的更改,您的文件将不会被修改,如果您运行 git status,它们将回到看起来好像它们被编辑过一样