【问题标题】:How do I partially git cherry-pick without ruining a future merge?如何在不破坏未来合并的情况下部分 git cherry-pick?
【发布时间】:2015-07-23 21:20:43
【问题描述】:

我需要将针对develop 分支的一些错误修正带入master。我希望文件 Adevelopmaster 中相同。

通常,我会git cherry-pick 影响A 的提交,但其中一些提交也会影响文件BC,其中B 是存在于master 中的文件,但我不'还不想改变,而Cmaster 中尚不存在的文件。

在未来某个时间发布下一个版本时,develop 将合并到 master。如果我现在git cherry-pick -n 提交我想要的提交,我将不得不取消对B 的更改,并在提交之前解决不存在的C 的冲突。当从developmaster 的真正合并发生时,我想要对BC 进行更改,但实际上我不会得到它们,因为我在cherry-pick 期间已经搞砸了这些更改,对吧?

我应该怎么做?如果我git checkout <latest_commit_hash> A,那以后会不会也造成严重的合并冲突?

【问题讨论】:

  • 我认为你可以从 master 创建 temp 分支,从 develop 创建cherry-peak 提交(或者只是复制你需要的文件),而不是合并 tempmaster。但我不确定。
  • 你也可以考虑创建一个补丁,虽然这是一种更高级的技术。这是一个简短的教程:makandracards.com/makandra/…

标签: git


【解决方案1】:

如果这些分支在未来的任何时间合并,一般避免git cherry-pick

在我看来,如果开发分支是本地的并且不公开可见,git rebase 实际上可能会有所帮助。如果其他人看到了您的更改并且这些提交具有不同的父项,则您无法避免合并。

假设您在开发主线之后有 n 个提交,并且您在 n 中有 m1,m2,m3 个提交并希望与之共享主线。

如果你这样做:

git checkout development # go to development branch
git rebase -i mainline   # reorder all commits in development

您将获得一个编辑器窗口,每行显示一个提交。如果您将 m1,m2,m3 的提交放在该行的顶部并选择 edit(而不是 pickgit 将按照您的要求重新排序您的提交(顶部提交最旧和底部最新的),它将在每次标记为编辑的提交之前停止。

你可以这样做:

git add file1
git commit              # commit only file1
git commit -a           # commit the rest
git rebase --continue   # continue rebasing

然后,您可以重新设置另一个时间,以在您的更改历史记录中进一步移动不需要的提交。如果您对日志感到满意(即:您在主线中需要的所有提交都在主线中的更改之上,仅此而已;因此您可以合并进行快进),您可以从开发分支中选择最远的提交(由 SHA)并合并。

git checkout mainline
git log development   # assume acf123 is the last commit you want
git merge acf123      # fast forward to the right commit

另见:

【讨论】:

    【解决方案2】:

    如果我使用 git checkout develop -- A,那将来会不会导致严重的合并冲突?

    不,它本身不会。合并通过将每个提示与合并基础进行比较,然后比较两组更改来工作。如果两个分支都进行相同的更改,则没有冲突。

    Other 任何一个分支上的更改,或者太接近两个分支上共同更改的行,都可能表现为冲突。阻止这些的方法是通过记录来自公共内容的合并,为 git 提供准确的合并基础。

    # merging master and develop, but there are common changes and 
    # also changes that conflict only with those common changes.
    # supply git's merge with the common changes as part of the base,
    # so it will see that it needs to resolve only those other changes
    
    # check out the current merge base
    git checkout $(git merge-base master develop)
    
    # make the changes you're merging
    git checkout develop -- file_A
    git commit -m "cherrypicking file_A as of develop @ $(git rev-parse develop)"
    
    # (for ensuite)
    base=$(git rev-parse HEAD)
    
    # record that both branches have those changes
    git checkout develop
    git merge -s ours $base -m "recording common content from previous cherry-picks"
    
    git checkout master
    git merge -s ours $base -m "recording common content from previous cherry-picks"
    
    # and now this merge will get an accurate base:
    git merge develop
    

    现在:这些 $base 合并的唯一效果是将公共内容记录为两个分支提示的祖先,从而为从 developmaster 的合并提供一个准确的基础,从而解决其他更改。

    新的提交使历史与广泛使用的successful git branching model 中给出的做法保持一致。


    如果就您的团队如何解释提交而言,最好只将常见内容的来源记录在提交消息的文本中,那么 git 也能做到这一点。除了永久记录祖先,通过上述base 分配后的结帐和合并,您还可以

    echo $(git rev-parse master  master~)  $base > .git/info/grafts
    echo $(git rev-parse develop develop~) $base >>.git/info/grafts
    git checkout master
    git merge develop
    
    # later, whenever you want -- the ancestry above is strictly repo-local
    rm .git/info/grafts
    

    .git/info/grafts 中记录的祖先是 repo-local。您的合并命令会看到它,结果将是正确的。唯一的缺点是因为基地实际上并没有被记录下来,其他人在重复它时也会遇到同样的麻烦——除非你在做 criss-cross merges 或者还挑选其他分支,否则不太可能。

    【讨论】:

      【解决方案3】:

      使用 git-cherry-pick 没有一种好方法可以避免主题发生的合并冲突,其中选择的更改与 master(选择更改的位置)合并。

      我建议您执行cherry-pick 操作,然后在本地进行测试合并,并在担心避免冲突之前发现冲突是否是Git 在没有用户干预的情况下无法管理的。

      我倾向于模仿部分精选的技巧之一是:

      git cherry-pick <commitish>
      git checkout HEAD~ -- <path of unwanted change in file>
      git checkout HEAD~ -- <path of unwanted change in file>
      git checkout HEAD~ -- <path of unwanted change in file>
      git checkout HEAD~ -- <path of unwanted change in file>
      git commit -am "squash me"
      git rebase -i HEAD~~
      

      将樱桃采摘和结帐/还原在一起。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-09-19
        • 1970-01-01
        • 2014-07-08
        • 2010-11-17
        • 2018-10-04
        • 1970-01-01
        • 2013-05-17
        • 2012-05-21
        相关资源
        最近更新 更多