推送分支上的每日 rebase

Everyday rebase on pushed branch

我开始 learn/use rebase 并且有问题:

  1. 我从 master
  2. 创建 feature-1 分支
  3. 我工作了 5 天,每天做出一些承诺,每天结束时我做出 pushfeature-1
  4. 因为其他开发人员对 master 进行了一些更改,所以我在每天开始时都将 rebase(变为 feature-1
  5. 完成后,我创建了从 feature-1master
  6. 的拉取请求

一段时间后,我读到如果我将更改推送到我的分支(我每天结束后都会这样做),我不应该使用变基 - 所以我想知道我是否以正确的方式使用 rebase 还是我应该改变我的方法吗?

Rebase 是一个破坏历史的命令,因此 [根据经验] 不应在其他人签出的分支中使用它,因为强制推送会并且会扰乱工作流程。

也就是说,如果 feature-1 仅由您检查,您描述的工作流程对我来说看起来非常好。它将导致更清晰的合并和更新。

“不要强制推送 public 分支” 经验法则是防止普通用户搞砸的概括。

在您描述的工作流程中,在第 2 步的一天结束时,显然第一次推送您的分支时它是干净的,但随后几天的推送将需要强制推送(除非 master没有改变,那天的 rebase 没有效果。

你的用例完全没问题,我会(并且会)在我的个人分支上做同样的事情。经验法则确实应该是“不要强制推送 shared 分支”,特别是分支策略中的长期分支(例如,mainmaster, develop, 等等)但即便如此,我还是建议保护那些特殊的分支,这样即使你尝试过也不能强制推送,除非 repo 管理员知道他们在做什么。如果你适当地保护某些共享分支,那么允许每个人随时强制推送(他们自己的)分支是很好的。如果开发人员在单个分支上进行协作,那么他们只是让彼此知道他们是否强制推送该分支。 (在工作环境中,如果开发人员开始在未经许可的情况下强制推送 其他 人的分支,那么他们可能需要更多培训或删除他们的访问权限。)

重要的是要注意,即使您在第 2 步中从未在一天结束时推送,一旦您将 PR 创建到 master,您可能仍然希望变基,并随后强制推送。例如,在代码审查期间,有人可能会发现您需要修复的一个字符拼写错误。当然,您 可以 只需在新提交中修复该拼写错误,但是当您可以修复现有提交时,为什么还要用新提交来混淆历史呢?无论您是在分支上修改提示提交还是修复先前的提交(使用 rebase -i),您都需要在之后强制推送,恕我直言,重写该提交应该是默认的,而不是例外。如果直到 PR 完成到 master 之后才发现拼写错误,那么这是一个完全不同的场景,通常需要新的提交和额外的 PR。我的观点是,如果您的工作流程使用 PR 将更改引入共享分支,那么强制推送应该是工作流程的常规部分。相反,一个你永远不想强制推送的例子是基于主干的开发(TBD),例如每个人都在 master 上工作,一旦你推送,你就不会重写任何这些提交.

什么时候真正需要强制推送?

You need to force push anytime you wish to remove commits from a branch that has already been pushed.

您可能觉得自己没有删除 提交,因为从概念上讲,您正在更改 它们。然而,当你变基时,你实际上是在 重新编写 提交,但这样做你也在 从分支中删除 以前版本的提交.任何时候您 重写 一个提交,您都在更改该提交的某些内容。在变基的情况下,您通常至少要更改父提交和提交者日期时间(现在)。当有关提交的任何内容发生变化时,提交 ID(哈希)也会发生变化,因为没有两个不同的输入应该能够生成相同的哈希*。这相当于您在远程分支上“删除”至少一个提交 ID,并添加一个新 ID。因此,如果您对较早的提交使用 rebasecommit --amendreset 之类的命令,在已推送的分支上,您需要再次强制推送。

其他想法和提示:

  1. 除非有理由不这样做,否则在您停止工作时推出您的分支(就像您正在做的那样)。在您的本地计算机丢失或损坏的不太可能发生的情况下,这可以作为一个很好的备份。如果您在多台机器上工作,它还可以确保您不会踩到自己的脚趾。
  2. 定期获取并变基到目标上,例如 origin/master,以便及时了解可能导致与您的分支冲突的更改。当确实发生冲突时,通常更容易立即处理。我通常每天大约 1-5 次变基到 origin/master,并在创建 PR 之前再变一次。
  3. 强制推送时,默认为git push --force-with-lease(甚至可能是)而不是众所周知的--force。这将防止您不小心吹走您尚未看到的远程分支上的新提交(由您从另一台机器或您的分支上的协作者添加)。
  4. 一些 Git SCM 工具可让您在更新分支时跟踪 PR 的历史记录。出于多种原因,这很有用,其中之一是隔离由变基或合并带来的您可能不会注意到的更改。每次你变基并强制推出你的分支时,PR 可以检测到自上一个分支版本以来的变化,它会突出显示差异(可能在没有冲突的情况下静默合并)所以你可以很容易地看到它们是否兼容你的改变。

反驳:

有些人可能会争辩说您甚至不应该强制推送您自己的个人分支,以防万一其他人可能正在使用您正在替换的以前的提交 ID。也许这在有许多合作者的 public 回购中可能是正确的,但是,恕我直言,这只需要由组织或回购所有者定义。实现此目的的一种方法是用您的名字命名分支(例如 user/first.last/description-of-the-change)。这样一来,谁“拥有”它就一目了然了。如果有人想使用我的分支,他们可以,但它可能会在合并到 main 之前被重写多次,如果他们对此有疑问,他们可以寻求我的帮助做一个花哨的 rebase --onto 如果需要的话。我个人看不出有任何理由禁止在私人仓库中强制推送,事实上我更喜欢 BitBucket 的“rebase,merge”或 Azure DevOps 的 ,两者都可能在 PR 时有目的地做另一个 rebase完成。 (同样,我能想到的唯一例外情况是很少使用力推,如果有待定的话。)


*从理论上讲,哈希冲突是可能的,两个不同的输入可以生成相同的哈希。 Git,默认情况下,使用 SHA-1 哈希算法,该算法确实存在已知的冲突,但据我所知,它们 rare enough 从未在 Git 回购中引起问题,而且可能永远不会会.