使用Git Stash作为工作流是否是反模式?


25

最近,我一直在研究我和我的团队如何使用Git以及我们的工作流程如何工作。我们目前使用的功能分支工作流程似乎运行良好。

我还看到我们团队中的某些人使用基于git stash的工作流。工作流程如下所示:

  • 在主分支上工作(如master
  • 随手提交
  • 如果需要更改或切换分支,请将未提交的更改推送到存储中
  • 更新完成后,将更改从隐藏项中弹出。

我应该提到,此工作流代替了功能分支工作流。在这里,开发人员只需要在一个分支上工作,而不是采用分支机构就可以按照自己的意愿推送/弹出堆栈。

实际上,我认为这不是一个很好的工作流程,因此分支比以这种方式使用git stash更合适。我可以将git stash的值视为紧急操作,但不能用于日常的常规工作流程中。

定期使用git stash是否会被视为反模式?如果是这样,可能会出现哪些具体问题?如果没有,有什么好处?


2
您可以尝试询问您的同事他们的工作流程是否有任何问题。如果他们没有,那么我不会认为这有害。
AlexFoxGill 2014年

@AlexG这是一个正确的观点。我在这里问这个问题,看看是否有人发现了“陷阱”。
joshin4colours 2014年

3
如果我理解正确的话...... If you need to get changes or switch branches, push your uncommitted changes onto the stash-这就是究竟藏匿是什么。

3
@MichaelT我的本地分支允许所有操作。无条件的。
maaartinus 2014年

2
我的模式是:->不要使用git stash->使用功能分支->使用“ wip”提交消息保存进行中的工作。->在分支上进行交互式重新构建,以将Wip压缩为一个有意义的提交,但仅适用于本地的,未按下的更改。->推送到远程->根据您的git工作流程合并到主服务器(并推送)。
Michael Durrant 2014年

Answers:


31

Git SCM书中

通常,当您从事项目的一部分时,事情处于混乱状态,您想切换分支以进行其他工作。问题是,您不想做一次半完成的工作,只是想稍后再回到这一点。这个问题的答案是git stash命令。

暂存会占用工作目录的脏状态(即,已修改的跟踪文件和暂存的更改),并将其保存在未完成的更改堆栈中,您可以随时重新应用它们。

鉴于此描述,我会说这是一种反模式。对Git Stash的过于简化的解释是,它是源代码控制的“剪切和粘贴”。您将一堆更改过的文件,保存在Git正常分支工作流程之外的一支握笔中,然后在以后将这些更改重新应用于其他分支。

再往前走一点,致力于掌握是这里的反模式。使用分支。那就是他们的目的。

真正归结为:

您可以将螺丝钉在墙上,这样可以固定图片,但是应该使用螺丝刀。当螺丝刀正坐在您旁边时,请勿使用锤子。

关于提交“破损”代码

虽然以下是意见,但我是根据经验得出的。

提早提交,并经常提交。提交任意数量的损坏代码。在您入侵某些内容时,将您的本地提交历史记录视为“保存点”。完成逻辑工作后,进行提交。当然,它可能会破坏所有内容,但是,只要您不推动这些提交,那都没有关系。推送之前,请重新整理和压缩您的提交。

  1. 建立新分支
  2. 哈克哈克哈克
  3. 提交破损的代码
  4. 完善代码并使其起作用
  5. 提交工作代码
  6. 变基和压扁
  7. 测试
  8. 测试通过时推送

对于OP来说,这个Linux内核消息线程可能是令人感兴趣的,因为听起来好像OP团队的某些成员正在以类似的方式使用Git。

@RibaldEddie在下面的评论中说:

首先,存储不是在“分支工作流”之外,因为在内部,存储只是另一个分支。

(冒着引起许多人愤怒的危险)

莱纳斯说:

使用“ git stash”,您也可以具有多个不同的隐藏对象,但是它们不会彼此排队-它们只是随机存储的独立补丁,因为它们在某些时候不方便而被隐藏了。

我认为@RibaldEddie想要说的是,您可以git stash在功能分支工作流程中使用它-这是事实。这不是git stash问题所在。它是提交到master和using的组合git stash这是一种反模式。

澄清 git rebase

来自@RibaldEddie的评论:

变基更像是粘贴复制,甚至更糟地修改已提交的历史记录。

(强调我的)

修改提交历史记录不是什么坏事,只要它是本地提交历史记录即可。如果您将已经推送的提交作为基准,那么实质上您将使用分支孤立其他任何人。这不好。

现在,假设您在一天内进行了几次提交。一些提交是好的。有些...不太好。该git rebase命令与压缩提交一起是清除本地提交历史记录的好方法。合并到公共分支的一次提交很不错,因为它可以保持团队共享分支的提交历史记录整洁。重新基准化后,您将需要再次测试,但是如果测试通过,则可以推送一个干净的提交,而不是多个脏提交。

关于干净提交历史记录,还有另一个有趣的Linux Kernel线程。

再次,从莱纳斯:

我想要干净的历史记录,但这确实意味着(a)干净和(b)历史记录。

人们可以(也许应该)为自己的私有树(他们自己的工作)建立基础。那是清理工作。但是从来没有其他人编写代码。那是“毁灭的历史”

因此历史部分相当简单。只有一个主要规则,还有一个次要说明:

  • 您绝对不能破坏他人的历史。您不得重新基准其他人所做的提交。基本上,如果没有您的批准,那就超出了限制:您无法将其作为基准,因为它不是您的。

    请注意,这确实是关于其他人的历史,而不是关于其他人的代码。如果他们以电子邮件补丁程序的形式向您发送了东西,并且您使用“ git am -s”应用了它,那么这就是他们的代码,但这是 您的历史记录。

    因此,即使您未编写代码,只要提交本身是您的私有代码,您就可以对其进行“ git rebase”操作。

  • 对该规则的次要说明:在某些公共站点上发布历史后,其他人可能会使用它,因此现在显然不再是您的私人历史了。

    因此,次要澄清的事实是,这不仅涉及“您的提交”,还涉及它对您的树是私有的,并且您尚未将其推出并宣布。

...

现在,“干净”部分更加微妙,尽管第一个规则非常明显且容易:

  • 保持历史记录可读

    有些人通过首先解决问题,而不犯错误来做到这一点。但这非常罕见,对于我们其他人,在解决问题时,我们使用“ git rebase”等。

    因此,“ git rebase”没有错。但这是对的,只有它是您自己的私人git树。

  • 不要暴露你的废话。

    这意味着:如果您仍处于“ git rebase”阶段,则不要将其推出。如果尚未准备好,您可以发送补丁,或使用私人git树(仅作为“补丁系列替代品”),而您不会将其告知公众。

(强调我的)

结论

最后,OP让一些开发人员执行此操作:

git checkout master
(edit files)
git commit -am "..."
(edit files)
git stash
git pull
git stash (pop|apply)

这里有两个问题:

  1. 开发人员致力于掌握。立即将其锁定。真的,这是最大的问题。
  2. 开发人员在应该使用功能分支时会不断使用git stashgit pull掌握。

使用git stash-尤其是在拉动之前- 并没有错,但是git stash当Git中有更好的工作流程时,以这种方式使用是一种反模式。

他们使用git stash红鲱鱼。这不是问题。致力于掌握是问题所在。


4
哇,这是不对的。首先,存储不是在“分支工作流”之外,因为在内部,存储只是另一个分支。将其视为复制粘贴工作流的想法毫无意义。变基更像是粘贴复制,甚至更糟地修改已提交的历史记录。最后,一旦您需要与同事共享进行中的工作,您的工作流程将完全无用,因为一旦您进行更改,工作流程就会崩溃。这是如何获得六票赞成的。
RibaldEddie

8
@RibaldEddie:重定基础和重写提交历史记录没有任何问题,只要它是本地提交历史记录即可。推送这些提交后,您的评论将是正确的,但请重新阅读我的回答。它说:“在推送之前,重新设置和压缩提交。” 那是本地提交历史记录,完全由您控制。
Greg Burghardt 2014年

1
@RibaldEddie:我已经澄清了答案。它确实需要一些清理。
Greg Burghardt 2014年

我将在自己的回答中提供更多背景信息。
RibaldEddie 2014年

请参阅下面的答案-致力于掌握是一种反模式,但这不是真正的问题。
RibaldEddie 2014年

7

我个人仅使用stash短暂的意外中断,例如有人问一个问题,需要更改为其他分支。之所以这样做,是因为我之前忘记了藏匿处,所以它们不会干净地使用。对功能分支的常规提交更难忘记,并且更易于合并,所以现在我倾向于只进行一个损坏的提交,git reset HEAD~1如果以后不想再保留它,则进行a 或rebase。

但是,关于分布式版本控制的好处是,只要共享存储库符合标准,人们就可以在自己的存储库中使用其首选的工作流。我要确保人们不仅仅stash因为没有足够的培训或对替代方案的意识而使用工作流,但是如果他们仍然选择您认为次优的工作流,我会保留。


1

我认为您的问题的一部分是反模式,是使用单个共享的master分支。但是,如果你要包括开发,除了主分支的分支,然后使用储物箱来处理你自己的上下文中发展的分支交换机,这不会是一个反模式,它非常密切反映了一些工作流程由Etsy和Facebook等组织描述。

话虽如此,@ Greg Burghardt的上述回答对所谓的git-flow或feature-branch工作流程来说有点太有利了。我曾经提倡类似的策略,但是在意识到它增加了不必要的复杂性并产生了错误的安全感之后,我不再这样做了。这也是Subversion之类的非分散版本控制系统时代的延续。

首先,由于Git是不同于Subversion的分散式版本控制系统,因此开发人员的本地存储库实质上是代码本身的巨大分支。除非在共享存储库中将损坏的或错误的代码推送到任何共享分支,否则单个开发人员在本地执行的操作不会也不会影响其他团队成员。

但是,当其中一个重播提交中存在合并冲突时,rebase命令可能会损坏分支的历史记录。从http://ryantablada.com/post/the-dangers-of-rebasing-a-branch

其余的基础工作进展顺利,测试似乎都通过了。进行PR。

然后编写更多代码,这些代码依赖于commentsForAllPosts属性,并且一切都坏了。但是我们去找谁寻求帮助?git blame显示代码行仅由服务器端工程师编写,他举起了手。

现在您的前端工程师正在休假,请病假或其他人知道。没有人能弄清楚该代码应该是什么样子!

Rebase破坏了团队查看历史记录以查找出问题所在的能力,因为子分支上的任何合并冲突都将被杀死,并且原始代码将永远丢失。

如果出现相同的合并冲突并使用了合并,则应归咎于该行代码在合并过程,父分支上的提交和子分支上的提交已被触摸。一些人在玩弄这三个排列,您可以将原始意图重新带入代码库中,而无需花费很多头挠指责即可工作。而您真正拥有的只是另一次提交

此外,多重分支模型假定没有两个分支可以包含相互依赖的代码更改。当不可避免地发生这种情况时,开发人员现在必须处理更多的分支才能有效地工作。

我看到的基本反模式与分支与存储无关,而是与一些非常聪明的人已经讨论了一段时间的问题有关:您是否对使用代码有信心?单元测试和好的架构?您是否能够对代码进行增量更改,以使您的开发人员可以轻松地对更改进行推理并了解更改将做什么?您的开发人员是否还会运行一次新代码以查看其是否真正起作用?(是的,我以前见过)。

如果对这些问题的回答是否定的,那么您拥有多少分支实际上并不重要-开发人员会说,代码确实可以使用,可以正常工作并且适合生产,并且分支数量不会无论如何,当该代码投入生产时可以为您提供帮助。


2
您关于重新合并遇到合并解析问题的评论不正确。rebase与实际合并属于同一类型的合并。Git只是在后台合并提交。调整和解决合并冲突不会损坏提交历史记录。重新设置基础和不正确地解决合并冲突会损害事物,这与正常的合并一样。我确实同意功能分支增加了复杂性,但是如果开发人员必须处理多个不相关的更改,那么这可能是必要的复杂性。
格雷格·伯格哈特

那么,您是说合并会破坏历史吗?听起来这只是避免过多分支的更多理由!
RibaldEddie 2014年

1
合并不能破坏历史。我认为您可能会误解了基础和合并的工作原理。当合并冲突被触发时,由人来解决。如果人类没有正确解决它,您就不能怪Git(或SVN,CVS或{在此处插入源代码控制)。
Greg Burghardt 2014年

现在,您所说的与您之前所说的有些冲突。您读过我引用的文章吗?您了解变基会丢失历史记录的情况吗?
RibaldEddie 2014年

1
我读了这篇文章。“在Keen,我们几乎在每次提交后都尝试推送我们的代码。” 对我来说这听起来很疯狂。他们要么提交过多的内容,要么推出尚未准备好的代码。如果立即将所有提交公开,那么重新部署将导致问题。这是“医生,医生,我这样做会很痛”的原则。
Kyralessa 2014年

1

git stash是一个工具。它本身不是模式,也不是反模式。它是一种工具,就像锤子是工具一样。使用锤子打钉是一种模式,而使用锤子打钉是一种反模式。同样,在工作流程和环境中git stash使用正确的工具,在工作流程和环境中使用错误的工具。

在没有高风险更改的情况下,“每个人都提交并推送到主线”工作流是相当合理的工作。它经常在svn环境中使用,那里有一个拥有代码的权威中央服务器。

但是,Git决定取消一台中央服务器。把所有的开发商在做commitpull(或者rebase,如果你进入的是),push所有的时间可以有很大的混乱。

最大的问题出在您正在解决的问题上,您需要处理优先级错误。这意味着您需要将工作搁置一旁,获取最新的工作,无需进行先前的工作,而导致您尝试执行的构建出现问题。

为此,git stash将是适当的工具。

但是,此工作流程的核心存在一个更大的问题。是版本控制分支的所有角色都在一个分支上。主线,开发,维护,累积和包装都在Master上。 是一个问题。(有关此分支方法的更多信息,请参见高级SCM分支策略

是的,您确实指出这不是一个很好的工作流程,并且存在问题。但是,问题不在于该工具git stash。问题在于缺少角色或不兼容策略的明显分支。

git stash但是,这是我在有些情况下已经使用过的东西,处于一种粘滞状态,我不确定这是否是正确的情况时使用的...所以我藏了我的更改然后探讨了解决该问题的另一种方法。如果可行,那就太好了,把东西扔掉,继续。如果其他探索变得更加棘手,则重置为之前的更改,然后重新应用存储以进行处理。另一种选择是提交,签出,分支,然后继续在这个新分支上执行,或者返回并重置它。问题是,当我只是想探索一点东西时,是否真的值得将其纳入历史?

git stash不是反模式。git stash在每个人都向Master提交时使用分支来替代分支是一种反模式-但这不是因为git stash

如果尚未实现,请等到构建出现问题时,某人需要对许多文件进行重大的体系结构更改(以及合并冲突)或一些未经测试的进行中代码,从而为此泄漏到生产环境中。反模式赶上您。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.