在预生产和生产两个分支中保持线性历史

Keep linear history in two branches preprod and production

我在 github preprodproduction 中有两个分支,它们都受到保护并执行 线性历史 这意味着对分支需要由“rebase/merge”或“squash/merge”完成。

添加到 preprod 分支的每个新功能都是由功能分支创建的。

a          <-- production
 \
  b        <-- preprod
   \
    c -- d <-- featureA

当我将 featureA 与 squash/merge、'c' 和 'd' 合并到 preprod 时,在 preprod 中创建一个新提交。

a           <-- production
 \
  b -- e    <-- preprod
   \    ^
    \    \
     c -- d <-- featureA
       

在添加了几个新功能后,我使用相同的方法 squash/merge 将 preprod 合并到 production。这最终看起来像这样。

a ------------ h     <-- production
 \              ^
  \              \
   b -- e -- f -- g  <-- preprod

preprodproduction 的几次合并后,分支具有相同的代码但提交历史记录不同,因为 squash/merge 在 production 分支中创建提交不在 preprod 中,这会在我每次执行新的拉取请求时造成太多冲突,因为我试图合并提交 'b'、'e'、[=64 中的所有更改=]、'g'、'i' 和 'j'。看起来像这样。

a ------------ h ------- k     <-- production
 \              ^         ^
  \              \         \
   b -- e -- f -- g -- i -- j  <-- preprod

更新: 正如@matt 正确提到的那样,这是真实的图表

a ------------ h ------- k     <-- production
 \                       
  \                      
   b -- e -- f -- g -- i -- j  <-- preprod

随着时间的推移,情况变得越来越糟,我需要一种方法将 preprod 分支与 production 同步,因此在新合并中,拉取请求仅查找已合并一次的新提交。

在这个阶段无法做到 rebase/merge 因为冲突所以我不知道该怎么做。上次,为了合并从 preprodproduction 的更改,由于冲突,我被 github 阻止了,我在 this guide

之后解决了它
# in case branchA is not our current branch
git checkout branchA

# make merge commit but without conflicts!!
# the contents of 'ours' will be discarded later
git merge -s ours branchB    

# make temporary branch to merged commit
git branch branchTEMP         

# get contents of working tree and index to the one of branchB
git reset --hard branchB

# reset to our merged commit but 
# keep contents of working tree and index
git reset --soft branchTEMP

# change the contents of the merged commit
# with the contents of branchB
git commit --amend

# get rid off our temporary branch
git branch -D branchTEMP

# verify that the merge commit contains only contents of branchB
git diff HEAD branchB

这解决了冲突,因为我可以只使用 preprod 上的版本而忽略冲突。

我想让这个长期存在的分支同步并受到保护,因为我有一些 github 操作 运行 构建和测试,我认为这两个分支都需要受到保护并具有线性历史,因为在构建和测试通过后,两者都会自动部署到其相应的服务器。保持线性历史让我可以轻松地看到部署之间的变化,但是从 preprod 合并到 production 正在成为一个瓶颈。

知道如何解决这个问题吗?

根据我对您的流程的了解,我会:

  • 在将 preprod 合并到 prod 时不会挤压,这仍然会给你一个线性历史假设没有直接在 prod 分支上发生提交?
  • 定期删除 preprod 分支并从 prod 重新创建它
  • 或者有选择地定期将 preprod 变基到 prod 上,但这会稍微复杂一点,好处不大

强烈倾向于第一个选项,但这值得商榷。

this is creating too many conflicts each time I do a new pull request, because is trying to merge all the changes

是的,长寿命分支和压缩合并是对立的,正是出于这个原因。你选错了路。真正的合并存在是有原因的:它们 移动合并基础 以供将来合并。你没有利用这个事实。

您的图表有误,可能会误导您。例如:

a ------------ h ------- k     <-- production
 \              ^         ^
  \              \         \
   b -- e -- f -- g -- i -- j  <-- preprod

没有。 gh 之间的界线,jk 之间的界线是假的。实际情况是:

a ------------ h ------- k     <-- production
 \          
  \           
   b -- e -- f -- g -- i -- j  <-- preprod

gh 之间,或 jk。相反,hk 是突然神秘地创建的。但它们仍然是使用 merge logic 形成的。用于该合并逻辑的合并基数永远不会移动:它将始终为 a。因此,随着生活的继续,如果 preprod 还活着,而你一次又一次地尝试这样做,它将变得越来越难,这反映在不断增加的冲突中。

总而言之:您所做的并不是rebase/squash“合并”的设计目的。这些不是合并。在我看来,您应该放弃“线性历史”的目标——它根本不是历史,这就是全部问题。您应该拥抱 true 合并。