我已经建立了一个遵循所谓的“ git flow”的存储库,并且必须开发/掌握/工厂分支。从现在开始,我将在叉上引用origin
,在主存储库中引用upstream
。
打开问题并与回购维护者讨论/达成一些协议后,我开始着手研究。我要做的第一件事是创建功能分支跟踪(起源/开发)。
在几次临时提交并带有临时丢弃的临时坏名之后,我创建了一个PR并推送了。我想到的想法最终是将所有提交压缩到一个提交中,然后提供适当的提交名称/描述,以便维护人员能够毫无问题地将所有合并到上游/开发中,我的主要目标是使对于我和上游维护者而言,整个过程都尽可能地顺利,一旦合并,我将很乐意删除我的本地分支,完成工作,轻松自如...:)
我天真的想法会如此顺利!
无论如何我都不是git专家,并且我认为PR会如此平稳地发展是错误的(这可能在您不真正知道所使用的工具时发生)。在某个时候,我停止了几天的PR工作,显然上游/开发工作在不断发展,远远超出了PR,我的PR尚未通过测试,整个PR仍在等待未完成的工作
几天后,我决定返回该PR,并尝试恢复我的工作,在获取上游/开发后,我发现许多上游提交已经离我的PR遥远了,我真的不知道什么是在特定情况下的最佳选择,我不知道,我仍然不知道合并还是重新部署是最佳选择...
在对合并或重新定级的潜在含义了解甚少的情况下,我认为合并不会那么糟糕,最终一切都有可能整理,对吧?好吧,结果是,在合并并推送了更多临时提交之后,我的本地历史变得有些混乱,我真的不知道是否可以在不弄乱上游历史的情况下将其清除。
让我们说历史看起来像是PR = c1-> c2-> c3->上游1->上游2->上游3-> c4-> c5。在该示例中,c1..c6将是我的本地更改,而上游1..upstream3将是从上游提交的。
我想通过询问上游远离您的未完成PR(包含多个临时提交)的最佳方式来总结整个线程。
答案 0 :(得分:4)
在这种情况下,我会告诉我该怎么做。这种方法非常实用,可能不同的人有不同的个人选择。
与您一样,我也努力将PR中的提交压缩为1。
所以说,有一个dev
分支。
当我启动功能分支时,我会做:
>> git checkout dev
>> git pull
>> git checkout -b feature_branch
>> commitA
>> commitB
>> git push -u origin feature_branch // now there is origin/feature_branch available to everyone
>> and create a PR when I'm ready
现在过程如下:
人们查看我的工作并发表评论,然后进行更改并提交。这是一种循环, 结束时,我们所有人都对这些更改感到满意,并准备将事情合并回
>> commitC
>> commitD
所以,现在我准备“将提交压缩为一个”。所以我这样做:
>> // make sure I'm on feature_branch
>> git rebase -i HEAD~4
>> // at this point I have one 'beautiful' commit, lets_call it commit_TO_GO
>> git push -f //forcefully push my commits by overriding the current state of a remote branch in PR, this is not really important, only if I want to "preserve this state for backup or something
只要该分支没有合并,我就不介意这样做,没关系。
让我们假装此过程花费了一些时间,同时,origin/dev
分支中还有其他队友完成了一些新的提交(commitX,commitY和commitZ)。
因此,从理论上讲,我现在可以执行以下操作: 通过应用常规的三向合并进行合并,如果有冲突,我首先必须解决它们。
但是,由于我担心提交的历史(就像您一样),因此请执行以下操作:
>> git fetch --all
>> git rebase origin/dev
>> // at this point The my commit_TO_GO is applied on top of commitX,commitY,commitZ.
>> // technically it has a different sha1 now, but it's not really important, its
>> still my own branch, I do whatever I want there :)
>> git push -f // again forcefully push to origin/feature_branch
在此步骤之后,origin/feature_branch
是origin/dev
的FF,这很酷,因为我可以应用合并,并且它将处于FF模式,甚至不会创建合并提交。 / p>
当然,如果存在冲突,则无法进行重新设置基准,我必须首先解决冲突。我在IDE中执行此操作,然后继续进行变基(git rebase --continue
),但是解决冲突已超出此问题的范围
现在我准备将更改合并回origin/dev
通常,我是在bitbucket / github的UI中完成的。
合并后,origin/dev
中的历史记录看起来很美:
commitX->commitY->commitZ->commit_TO_GO
结果:根本没有合并提交,我的单个提交最后应用
要考虑的一点:
即使在开发过程中(当您在feature_branch上工作时),只要确保它包含最新更改,就没有必要从dev分支重新建立基础。因此,您可以根据需要多次遍历循环:
>> git fetch --all
>> git rebase origin/dev
我了解到,Git可能袖手旁观了更多的“快捷命令”,也许这个解释太详细了。
答案 1 :(得分:2)
就最终结果而言,合并和重新定基是相同的...但是,就产生的历史记录以及“孤立地”进行工作的轻松程度而言,它们是完全不同的。 ..如果您进行工作,然后进行合并,然后进行更多的工作...然后进行合并...然后进行更多的工作,依此类推,很难仅查看构成该功能的所有修订。
所有这些要说的只是重新设定基准。应该怎么办?转到上游/开发的提示,挑选构成功能的实际修订版本(不合并)...这样,您便清理了分支...设置本地功能指向这一点并继续工作...如果在上游/开发上进行了更多工作,请在此基础上重新构建。
答案 2 :(得分:0)
如上所述,我将选择使用git rebase
,如下所示。
topic
是您的请求请求,与此同时master
分支涉及另一个提交。
A---B---C topic
/
D---E---F---G master
rebase
意味着更改以前的基础,这也会修改分支的历史记录。
A'--B'--C' topic
/
D---E---F---G master
因此,您必须强制推送到远程分支。因为以前没有人合并过您的PR,所以可以,不会对您的合作者造成任何影响。
您可以在此处阅读有关变基的更多详细信息: Pro Git v2, Git Branching - Rebasing和git-rebase command。