Git cherry-pick vs stash,switch和pop

时间:2014-03-07 12:13:07

标签: git version-control merge

所以我在一个分支上进行一些更改时遇到了问题,并意识到我对该分支进行了无关的更改。

无关的变化非常小(只有一两行)。所以我提交了相关更改,然后尝试切换到master(我想在其中进行无关的更改)。分支交换机失败,因为会出现合并冲突,所以我转移到我通常用于绕过它的方法,并通过更改隐藏,然后移动到master。我应用了藏匿并发生合并冲突!这让我感到惊讶,因为变化非常简单。

查看合并工具中的合并冲突,我看到了原始功能分支中的各种代码 - git已经为我自动取消选择这些,所以没有将它们拖到我的主分支上的真正危险但它让我思考关于stashes(和diffs)是如何工作的更深入一点 - 我并没有想到一个简单的差异包含了它来自哪里!

无论如何,在咨询了一位同事后,我决定尝试使用git cherry pick将更改移到master上 - 显然这种方式有所不同。因此,我在功能分支上临时提交了更改,然后尝试将这些更改提取到主服务器上。我有完全相同的合并冲突!

所以无论如何我修复了东西并完成了提交。但我想知道解决我遇到的问题的推荐方法是什么(在不同的分支上进行一些更改)?它不是真的git stash的用途吗?但是在我的功能分支上进行提交(然后不得不删除它)似乎有点沉重。

ELI5的奖励积分是stash pop和cherry pick之间的差异(如果有的话)。

1 个答案:

答案 0 :(得分:3)

你问了三个问题:

  1. 在这种情况下发生了什么。
  2. 一般该怎么做。
  3. checkout,stash / checkout / pop和commit / checkout / cherrypick之间有什么区别。
  4. 按相反的顺序:

    问题3:

    为此,在树中进行非分段更改的结帐与stash,checkout,stash pop基本相同。在这两种情况下,你基本上都是预先取得一个差异(你的非分段更改),签出一些其他分支,然后将这个差异(作为补丁)应用到新分支上,为你提供相同的非分段更改,但使用不同的工作树。

    (Stashing还有一些其他功能,例如允许多个stashes,但它们在这里不相关。)

    如果diff(即非分段更改)干净地应用于新工作树的顶部,则此方法可以正常工作。如果没有,那么结账方法将失败,而存储弹出将给你一个合并冲突。由于更改可能是微不足道的(或者您正在做一些更正式的事情,比如进行一些提交),我倾向于手动排序这类事情:在旧分支上使用git diff,然后抛弃这些更改,结帐新的分支并手工应用差异,并充分考虑为什么它首先不干净地应用。存储方法只是让你使用git的合并机制来帮助你。

    我们没有创建过提交。由于提交本质上是一种差异,我们可以为原始分支上的所需更改创建提交。然后我们可以检查所需的目标分支并使用cherry-pick:将提交(即差异)从一个地方复制到另一个地方。但是,差异仍然与checkout和stash / checkout / pop方法相同,因此如果diff不能完全应用,你仍然会遇到合并问题。你不会通过提交魔术那些魔法。

    所以:

    • 结帐:结构最差。肮脏的工作树。基本上是git diff> foo; git checkout new-branch; patch -p1< FOO。没有任何格式记录变更或来自何处。

    • stash:更结构化的方法,因为它将工作树的肮脏记录为临时提交,可能带有消息。您可以稍后应用它,也许已经做了一些其他更改,并且可以轻松使用git的合并机制来解决冲突。

    • cherry-pick:大多数结构化:像stash一样,除了更改是一个完全成熟的提交,而不是在应用stashed更改时被丢弃的临时提交。

    关于挑选樱桃的几点说明:

    • 原始提交(正在被挑选)和最终提交之间没有git关系(从提交到其他分支的提交)。

    • 如果你使用cherry-pick -x,那么git将在结果提交的注释中包含原始的commit ref,这至少为你提供了可追溯性元素。

    问题2:

    我的意见:

    • checkout和stash / pop之间没有真正的区别。个人偏好,除非你想依靠git合并。

    • 取决于所涉及的更改量以及您是否需要能够跟踪从其原始位置(在功能分支上)到其最终位置(在主服务器上)的更改。如果它很简单,那么checkout或stash / pop。如果它涉及更多,和/或提交原始分支是明智的,那么在那里提交并进入主人(或稳定的发布分支),无论你的组织做什么(通常合并或挑选)。

    • 如果您不小心在功能分支上提交了无关的更改,并且您没有推送功能分支,那么您可以通过将更改添加到更多功能上来解决问题。相关分支,然后从您的功能分支中丢弃该提交。这使得git提交树在逻辑上变得合理,以重写历史为代价。 (你是否应该重写历史往往是一个宗教和/或组织问题。)

    问题1:

    您的问题源于这样一个事实:您的无关更改取决于您的功能分支上尚未掌握的某些更改。这意味着更改(表示为普通差异)不会干净地应用于master,因此任何应用该diff的自动化方法(无论是checkout-with-dirty-working-tree,stash / pop还是commit / cherry-pick )将因合并冲突而失败。