Mat*_*att 120 git merge rebase git-merge git-rebase
我们使用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
Run Code Online (Sandbox Code Playgroud)
所以听起来这会破坏工作流程:
在myNewFeature上工作的developer1处理他的NewFeature的developer2都使用master作为主分支
developer2将myNewFeature合并到他的NewFeature中
developer1 rebases,解决冲突,然后强制推送到myNewFeature的远程分支
几天后,developer2再次将myNewFeature合并到他的NewFeature中
这会导致其他开发人员讨厌developer1吗?
Tre*_*ris 86
首先,您和您正在与之合作的人需要同意主题/开发分支是用于共享开发还是仅用于您自己的开发.其他开发人员知道不要在我的开发分支上合并,因为他们将随时进行重新定位.通常工作流程如下:
o-----o-----o-----o-----o-----o master
\
o-----o-----o devel0
\
o-----o-----o devel1
Run Code Online (Sandbox Code Playgroud)
然后,为了与遥控器保持同步,我将执行以下操作:
git fetch origin
git checkout master
git merge --ff origin/master
Run Code Online (Sandbox Code Playgroud)
我这样做有两个原因.首先是因为它允许我查看是否有远程更改而无需从我的devel分支切换.其次,它是一种安全机制,以确保我不会覆盖任何未存储/已提交的更改.此外,如果我不能快速合并到主分支,这意味着有人已经重新设置远程主机(他们需要严重鞭打)或我不小心承诺掌握并需要清理我的结束.
然后,当远程更改并且我已快速转发到最新的I'll rebase:
git checkout devel0
git rebase master
git push -f origin devel0
Run Code Online (Sandbox Code Playgroud)
然后其他开发人员知道他们需要从我的最新产品中重新开发他们的开发分支:
git fetch <remote>
git checkout devel1
git rebase <remote>/devel0
Run Code Online (Sandbox Code Playgroud)
这导致更清晰的历史:
o-----o master
\
o-----o-----o devel0
\
o-----o-----o devel1
Run Code Online (Sandbox Code Playgroud)
不要随心所欲地来回合并提交.它不仅会创建重复提交并使历史无法遵循,从特定更改中找到回归几乎不可能(这就是为什么您首先使用版本控制,对吧?).你遇到的问题是这样做的结果.
此外,它听起来像其他开发人员可能正在向您的开发分支提交.你能证实这一点吗?
合并的唯一时间是您的主题分支已准备好被接受master
.
在旁注.如果多个开发人员提交到同一个存储库,那么您应该考虑使用命名分支来区分开发人员开发分支.例如:
git branch 'my-name/devel-branch'
Run Code Online (Sandbox Code Playgroud)
因此所有开发人员主题分支都驻留在他们自己的嵌套集中.
Lea*_*th2 47
您需要强制推送,因为您已将提交进一步向下移动,git期望您将提交添加到分支的顶端.git push -f origin myNewFeature
将解决您的问题.
提示:以上是推力的合法用法.永远不要在公共可访问的存储库中重写历史记录,否则许多人会讨厌你.
Mat*_*ers 31
这里要记住的主要事情是拉动和底板在幕后做什么.
拉动基本上会做两件事:获取和合并.当您包含--rebase时,它将执行rebase而不是合并.
自从您分支,快速转发您的分支到目标上的最新提交,并按顺序取消您的更改时,rebase非常类似于隐藏所有本地更改.
(这解释了为什么在执行rebase时可能会获得多个冲突解决提示与您可能通过合并获得的一个冲突解决方案.您有机会解决正在重新生成的EACH提交中的冲突,以便以其他方式保留您的提交. )
您永远不希望将重新定位的更改推送到远程分支,因为这会重写历史记录.由于几乎总是有例外,因此有点强大.例如,您需要维护本地存储库的远程版本以在特定环境中工作.
这将要求您使用force强制推送重新定义的更改:
git push -f origin newfeature
Run Code Online (Sandbox Code Playgroud)
或者在某些情况下,您的管理员可能已取消强制执行的功能,因此您必须删除并重新创建:
git push origin :newfeature
git push origin newfeature
Run Code Online (Sandbox Code Playgroud)
在任何一种情况下,如果其他人在您的远程分支上与您合作,您必须绝对确定自己知道自己在做什么.这可能意味着您最初与合并一起工作,并在掌握和删除工作分支之前将它们重新绑定为更易于管理的提交格式.
请记住,您几乎可以通过以下方式使用git的GC:
git reflog
Run Code Online (Sandbox Code Playgroud)
这是一个巨大的生命保护程序,因为如果您在所有的rebase /冲突管理中迷失,您可以重置回更稳定的状态.