2014-03-07 67 views
0

所以我在一个分支上做了一些更改时遇到了一个问题,并且意识到我对该分支做了一个无关的更改。Git cherry-pick vs存储,切换和弹出

无关的变化非常小(只有一两行)。所以我做了相关的修改,然后尝试切换到master(我想放置不相关的更改)。分支交换机失败了,因为会有合并冲突,所以我转移到了我通常使用的方法来实现这一点,并通过更改隐藏起来,然后移动到主机。我申请了这个藏匿处,并且遇到了合并冲突!这让我感到惊讶,因为变化非常简单。

看着合并工具中的合并冲突,我看到了我原来的功能分支中的各种代码 - git有自动取消选择这些给我,所以没有真正的危险将它们拖到我的主分支上,但它让我稍微深入地考虑一下存储(和差异)是如何工作的 - 我并不认为简单的差异包含了它的来源!

无论如何,在咨询了一位同事之后,我决定尝试使用git cherry pick来将这些更改转移到master上 - 显然这种工作方式不同。所以我在功能分支上做了一些临时的修改,然后尝试把这些修改放到master上。我有完全相同的合并冲突!

所以我修好了东西,完成了提交。但是我想知道解决我遇到的问题的推荐方法是什么(在不同的分支上提交一些更改)?这不是真正的git存储是为了正确的目的?但是对我的功能分支进行提交(然后不得不删除它)似乎有点沉重。

ELI5的奖励积分藏匿流行和樱桃挑选之间的差异(如果有的话)。

+0

最好提供git命令输出,包括git status,git log -n 2,git checkout等等。 – user3159253

回答

3

你问三个问题:

  1. 在这种情况下发生了什么事。
  2. 一般做什么。
  3. 结帐,存/结帐/流行和提交/结帐/樱桃选择有什么区别。

在相反的顺序:

问题3:

为了这个目的,与树中不分阶段变化的检出是基本上相同藏匿,结账,藏匿弹出。在这两种情况下,你基本上都会预先比较差异(检查未分类的更改),检查其他分支,然后将该差异(作为补丁)应用到新分支,为您提供相同的未分级更改,但使用不同的分区工作的树。

(积攒了一些其他的功能,比如允许多个储物箱,但它们不是与此有关)。

这工作正常,如果差异(即未分级的变化)干净适用于新的工作之上树。如果没有,那么结帐方式将失败,而隐藏弹出会给你一个合并冲突。由于改变可能是微不足道的(否则你会做更正式的事情,比如做一些提交),我倾向于手动对这类事情进行分类:git diff在旧分支上,然后丢弃这些改变,结帐新的分支和手工应用差异,同时适当考虑到为什么它不适用于清洁的原因。隐藏方法只是让你使用git的合并机制来帮助你。

在这些都没有我们创造了一个提交。由于提交本质上是一个差异,所以我们可以在原始分支上为我们所需的更改创建一个提交。然后,我们可以检出所需的目标分支并使用樱桃挑选:即将提交(即差异)从一个地方复制到另一个地方。然而,diff与checkout和stash/checkout/pop方法仍然是相同的差异,所以如果差异不适用,你仍然会遇到合并问题。你不会通过犯下这些魔术。

所以:

  • 结帐:至少结构。肮脏的工作树。基本上git diff> foo; git checkout new-branch; patch -p1 < foo。没有任何格式记录的变化或来自哪里。

  • 隐藏:更加结构化的方法,因为它将工作树的肮脏性记录为临时提交,也许带有消息。您可以稍后再应用它,也许做了一些其他更改,并可以轻松使用git的合并机制来解决冲突。挑选:最具结构化的:像存储,除了这些更改是完全成熟的提交,而不是在应用隐藏更改时被丢弃的临时提交。

一对夫妇约挑肥拣瘦笔记:

  • 有承诺(这是樱桃挑选的),并将所得的commit(从樱桃采摘提交到原来没有任何混帐关系一些其他分支)。

  • 如果你使用cherry-pick -x,那么git会在最终提交的注释中包含原始提交ref,它至少为你提供了一个可追溯性元素。

问题2:

我的看法:

  • 结算和存储/流行之间没有真正的区别。个人偏好,除非你想依靠git合并。

  • 取决于所涉及的变化量以及是否需要能够追踪从其原始位置(特征分支)到其最终位置(主位置)的更改。如果它很简单,那么结帐或存储/弹出。如果涉及更多,并且/或者在原始分支上提交是明智的,那么在那里进行落实并与任何组织所做的事情(通常是合并或樱桃选择)进入主(或稳定的发布分支)。

  • 如果你不小心犯下一个特性分支无关的变化,你有没有推功能分支那么你可以东西出来的樱桃采摘的变化上更相关的分支,然后丢弃排序从您的功能分支提交。这使得git commit树在重写历史记录的代价上是合理的。 (你是否应该重写历史往往是一个宗教和/或组织问题。)

问题1:

你的问题的事实,你改变无关的一些对你的功能分支尚未掌握上的变化取决于茎。这意味着变化(表示为一个普通的差异)并不会干净地应用到master上,所以应用该差异的任何自动化方法(无论是使用dirty-working-tree,stash/pop或commit/cherry-pick )会因合并冲突而失败。

+0

伟大的答案谢谢你。这证实了我原来的直觉,那就是作为一种操作,git存储流行与樱桃挑选相同,然后进行删除(否则有些人告诉我)。我知道他们在提交提交的临时程度方面有所不同(正如您的回答所述),但您的最终状态在两者中都是相同的。 – Sam

+0

一个重要的技术说明:一个提交不*包含差异,它包含一个完整的,完整的文件树。每次有人要求时,动态计算差异。在这些情况下,可观察到的效果是相同的,但是如果你深入到一个提交的内部,它开始变得重要;它也通过例如'git show'显示差异的方式显示出来,这取决于诸如'diff.renamelimit'设置(在git config文件中)。 (为了超级技术,git会在其“包文件”中存储增量,但它们不一定在普通文件之间)。 – torek