重新设定基准后无法推送至分支


131

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

问题是,如果我在重定基期间遇到冲突,则在重定基完成后,我无法推送到我的远程开发人员分支(在Github上),直到我拉开我的远程分支为止。这将导致重复提交。没有冲突时,按预期方式工作。

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

建立:

// 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合并到他的NewFeature中

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

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

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


不是解决方案,而是一种想法。谁的we?您是一个不只是您的团队吗?they说(那些比我了解更多的人),如果您共享代码,则不应该使用rebase。为什么你不只是在做git pullgit merge
AdamT

抱歉,我们=开发团队
Matt

1
所以,是的,共享代码时可能不应该变基础。可能会导致您不得不执行以下操作(force推送)
AdamT

哦,对不起,当他们说时rewriting history,这是rebase
AdamT

正如他所说的其自己这样一个发展分支,除非有人预计合并这不应该是一个问题英寸
Learath2

Answers:


93

首先,您和您与之共事的人需要同意主题/开发分支是用于共享开发还是您自己的。其他开发人员知道不合并在我的开发分支上,因为它们会随时重新设置基础。通常的工作流程如下:

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

然后其他开发人员知道他们将需要根据我的最新消息重新建立其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'

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


1
“而且听起来其他开发人员可能正在对您的devel分支进行提交。您能确认这一点吗?” 是的,他们是……
Matt

您还引起我注意另一个问题。在办公室和家庭之间工作。我在两个地方进行合并,并在一天结束时进行合并,这样我就可以从上次中断的地方接起。然后,当需要重新设定基准时,所有这些提交都会造成混乱。我需要将我的分支视为一个分支并重新设置
Matt

@Matt是的,这两个问题确实会困扰您的工作流程。首先,我要与其他开发人员沟通,只有所有者可以提交到命名分支(例如,“ matt / devel”)。恕我直言,无论如何,任何两个开发人员都不应致力于同一分支。只会造成混乱。对于以后,重新设置基准点和强制推入应该使两个位置保持最新。
Trevor Norris

好答案。我有一个附带的问题,为什么--force这样做时要使用标志git push -f origin devel0
大雄2015年

2
@Nobita如果git push无法快速前进(即,sha历史记录不匹配),则必须强制按下以使用从生成的新历史记录覆盖以前的历史记录git rebase
Trevor Norris

50

您需要在将提交进一步向下移动到行中时强制推送git期望您将提交添加到分支的尖端。git push -f origin myNewFeature将解决您的问题。

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


1
我发现这是维护工作流的最佳方法。
Syed Priom

1
谢了哥们。我使用此命令将重新建立基础的本地分支强制到同一远程分支。

11
使用git push --force-with-lease比使用安全得多git push --force

git push --force-with-lease origin HEAD-假设您的目标分支已经结帐了
Lucaci Sergiu

31

这里要记住的主要事情是pull和rebase在后台进行的操作。

拉取基本上将完成两件事:提取和合并。当包含--rebase时,它将进行重新设置而不是合并。

重新建立基础就像存储自分支以来的所有本地更改,将分支快速转发到目标上的最新提交,并按顺序取消存储更改。

(这说明了为什么在进行基准调整时可能会收到多个冲突解决提示,而在进行合并时可能会得到一个冲突解决。您有机会解决正在重新建立基础的EACH提交上的冲突,以免保留您的提交。 )

您再也不想将重新设置的更改推送到远程分支,因为这是在重写历史记录。简而言之,永远都不会强大,因为几乎总是有例外。例如,您需要维护本地存储库的远程版本以在特定环境下工作。

这将要求您有时使用强制推送重新进行基础的更改:

git push -f origin newfeature

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

git push origin :newfeature
git push origin newfeature

无论哪种情况,如果您的远程分支上有其他人与您合作,您都必须绝对确定自己知道自己在做什么。这可能意味着您首先要进行合并,然后在掌握和删除工作分支之前将合并重新设置为更易于管理的提交格式。

请记住,您几乎可以始终利用以下优势回退到git的GC:

git reflog

这是一个巨大的生命保护程序,如果您在所有变基/冲突管理中迷失了方向,可以将其重置为更稳定的状态。


上面的delete&recreate选项对我来说很好。我的仓库中不允许强行使用!
西蒙·福尔摩斯

2

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

哦,您最好确保人们不会在您的dev分支上建立任何东西-通常,您根本不应该在要重写历史的位置发布分支(或者一旦发布就不要重写历史)。一种方法是使用类似的分支名称wip/myNewFeature,然后提及wip分支将不时地重新建立为母版。


使用git push --force-with-lease比使用安全得多git push --force

@MrCholo人们将不会开始使用它,直到git为它像-f普通的强制推动一样添加了一个简短的选项:)
ThiefMaster 18-10-9

哈,是的,我在自动脚本中使用了它

2

已经给出的一般答案(git push -f origin myNewFeature在推动基于基础的更改时使用)是一个很好的起点。我正在写此答案,以解决有关是否破坏您的工作流程的修改。

如果我们假设你要使用git pull --rebase ...(或某些变化),然后通过力推动该远程分支,然后打破你的榜样工作流程developer2被合并的事情myNewFeaturehisNewFeature。只要没有其他人在该分支上工作,便能够重新建立自己的要素分支是有意义的,因此您需要使用规则来划分分支区域。

您可以通过以下方法解决此问题:a)建立您只能从中合并的规则master,或b)创建develop您自己的myNewFeature分支所基于的集体分支,并建立您仅可以从中合并的规则developmaster然后将仅保留用于里程碑或版本(或者您要对其进行设置),并且develop将在准备将其集成到其他功能分支时将其推入该位置。

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.