jjzjj

git - 当上游从不完整的 PR 中领先时,正确的处理方式是什么?

coder 2023-06-25 原文

简介

我已经 fork 了一个遵循所谓的“git 流程”的存储库,并且必须开发/主/工厂分支。从现在开始,我将在我的分支上引用 origin 并将主存储库引用为 upstream

在打开一个问题并与 repo 维护者讨论/同意一些事情后,我开始着手处理它。我做的第一件事是创建功能分支跟踪(起源/开发)。

在使用临时丢弃的临时错误名称进行几次临时提交后,我创建了一个 PR 并进行了推送。我想到的想法是最终将我所有的提交压缩到一个提交上,然后提供一个正确的提交名称/描述,这样维护者就可以毫无问题地将所有提交 merge 到上游/开发,我的主要目标是使整个过程对我和上游维护者来说都尽可能顺利,一旦 merge ,我会很高兴地删除我的本地分支,工作完成,简单易行...:)

问题

我天真地以为会这么顺利!

我无论如何都不是 git 专家,我错误地认为 PR 会发展得如此顺利(当你不真正了解你正在使用的工具时,这种情况往往会发生)。在某个时候,我已经停止了几天的 PR 工作,显然上游/开发继续发展并远远领先于我的 PR,我的 PR 还没有通过测试,整个 PR 仍在等待未完成的工作.

几天后我决定回到那个 PR 并试图恢复我的工作,在获取上游/开发之后我看到许多上游提交已经远远超过我的 PR 我真的不知道是什么是在那个特定情况下的最佳选择,我不知道,我仍然不知道 merge 或 rebase 是否是最好的选择......

由于对 merge 或 rebase 的可能影响知之甚少,我认为 merge 不会那么糟糕,最终一切都有可能得到整理,对吧?好吧,结果是,在 merge 并推送一些更多的临时提交之后,我的本地历史变得有点困惑,我真的不知道是否可以在不弄乱上游历史的情况下以某种方式清理它。

假设历史看起来像 PR=c1->c2->c3->upstream1->upstream2->upstream3->c4->c5。在该示例中,c1..c6 将是我的本地更改,而 upstream1..upstream3 将从上游提前提交。

问题

  • 当上游距离我未完成的 PR 很远时,我 merge 的决定是不是一个非常糟糕的选择?在这种情况下,最好的处理方法是什么?考虑一下我的目标是最终将单个压缩的提交 merge 到上游
  • 一旦造成伤害并且我在解决冲突后 merge 并创建了更多提交,是否仍然可以提供一个干净的 PR,只需 1 个压缩提交而不重写上游历史记录?

我想可以通过询问当上游远离包含多个临时提交的未完成 PR 时最好的处理方式是什么来总结整个线程。

最佳答案

我会告诉你在这种情况下我会怎么做。这种方法非常实用,可能不同的人有不同的个人选择。

我也和你一样,努力将 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

现在的过程是这样的:

人们审查我的工作并发表评论,我做出更改并做出 promise 。这是一种循环, 它在我们所有人都对这些更改感到满意并准备好 merge 回来的地方结束

>> 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

只要不 merge 这个分支,我不介意这样做,没关系。

假设这个过程花费了一些时间,同时,在 origin/dev 分支中有一些新的提交(commitX、commitY 和 commitZ)是由其他队友完成的。

因此,理论上,我现在可以执行以下操作: 通过应用常规的三向 merge 来 merge ,如果有冲突,我当然必须首先解决它们。

但是,由于我关心提交的历史记录(就像您一样),所以我执行以下操作:

>> 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_branchorigin/dev 的 FF,这很酷,因为我可以应用 merge ,它将处于 FF 模式,甚至不会创建 merge 提交。

当然,如果有冲突,rebase 将无法工作,我必须先解决冲突。我在我的 IDE 中这样做,然后继续 rebase (git rebase --continue),但是解决冲突超出了这个问题的范围

现在我已准备好将我的更改 merge 回 origin/dev

通常,我在 bitbucket/github 的 UI 中进行。

merge 后 origin/dev 中的历史看起来很漂亮:

commitX->commitY->commitZ->commit_TO_GO

结果:根本没有 merge 提交,最后应用了我的单个提交

要考虑的一点:

即使在您的开发过程中(当您正在处理 feature_branch 时)从 dev 分支 rebase 也毫无意义,只是为了确保它包含最新的更改。因此,您可以根据需要多次执行循环:

 >> git fetch --all 
 >> git rebase origin/dev

我知道 Git 可能有更多的“快捷命令”,也许这个解释太详细了。

关于git - 当上游从不完整的 PR 中领先时,正确的处理方式是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52359062/

有关git - 当上游从不完整的 PR 中领先时,正确的处理方式是什么?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  3. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  4. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  5. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  6. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  7. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  8. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  9. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

    它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

  10. ruby - Infinity 和 NaN 的类型是什么? - 2

    我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串

随机推荐