如何在Git中合并特定的提交

net*_*ter 964 git merge

我从GitHub中的一个存储库中分叉了一个分支,并为我提交了一些特定的东西.现在我发现原始存储库有一个很好的功能HEAD.

我想在没有事先提交的情况下合并它.我该怎么办?我知道如何合并所有提交:

git branch -b a-good-feature
git pull repository master
git checkout master
git merge a-good-feature
git commit -a
git push
Run Code Online (Sandbox Code Playgroud)

Von*_*onC 1123

' git cherry-pick'应该是你的回答.

应用现有提交引入的更改.

不要忘记在这篇文章中阅读bdonlan关于挑选樱桃的结果的答案:
"从分支中提取所有提交,将指定的提交推送到另一个",其中:

A-----B------C
 \
  \
   D
Run Code Online (Sandbox Code Playgroud)

变为:

A-----B------C
 \
  \
   D-----C'
Run Code Online (Sandbox Code Playgroud)

这个提交的问题是git认为提交包括它们之前的所有历史

其中C'具有不同的SHA-1ID.
同样,从一个分支到另一个分支的樱桃选择提交基本上涉及生成补丁,然后应用它,从而也以这种方式丢失历史.

这种更改提交ID会破坏git的合并功能(尽管如果谨慎使用,还会有一些启发式方法可以解决这个问题).
更重要的是,它忽略了函数依赖 - 如果C实际使用了B中定义的函数,你将永远不会知道.

  • 注意:"git rebase"也会更改SHA-1.另请参阅"git rebase与git merge(http://stackoverflow.com/questions/804115/git-rebase-vs-git-merge)和"git workflow"(http://stackoverflow.com/questions/457927/对于"git rebase"合法的情况,git-workflow-and-rebase-vs-merge-questions. (8认同)
  • 这个答案不是合并:生成的提交没有指向合并提交的祖先。也许OP本身并不关心创建*合并*,但有时差异确实很重要。 (4认同)

bdo*_*lan 692

您可以使用git cherry-pick将单个提交单独应用于当前分支.

例: git cherry-pick d42c389f

  • 您之前关于樱桃采摘的帖子的+1(http://stackoverflow.com/questions/880957/pull-all-commits-from-a-branch-push-specified-commits-to-another/881014#881014).我冒昧地在上面的答案中复制了它的摘录. (65认同)
  • 可能`git cherry-pick d42c`或`git cherry-pick d42c3`会起作用.Git很聪明.;) (4认同)
  • 不幸的是,这并没有回答这个问题:它实际上并没有创建合并。没有指向“d42c389f”的祖先。也许OP本身并不关心创建*合并*,但有时差异确实很重要。 (4认同)
  • 我刚刚执行了这个命令,它似乎奏效了,但是当我执行 git status 时,它说“无需提交,工作树干净”。当我刷新我的 bitbucket 网页中的提交页面时,它没有显示。但是当我执行 git log 时它会出现。我看到了修改后的代码。有人可以解释一下我是否必须执行任何其他步骤吗? (3认同)
  • 致命的:错误的修订 (2认同)

Upe*_*pen 28

让我们试着举个例子来理解:

我有一个分支,比如说master,指向X <commit-id>,我有一个指向Y <sha1>的新分支.

其中Y <commit-id> = <master>分支提交 - 很少提交

现在说对于Y分支,我必须在主分支和新分支之间进行间隙关闭.以下是我们可以遵循的程序:

步骤1:

git checkout -b local origin/new
Run Code Online (Sandbox Code Playgroud)

其中local是分支名称.可以给出任何名称.

第2步:

  git merge origin/master --no-ff --stat -v --log=300
Run Code Online (Sandbox Code Playgroud)

将提交从主分支合并到新分支,并创建日志消息的合并提交,其中包含来自最多<n>实际提交的一行描述.

有关Git merge的更多信息和参数,请参阅:

git merge --help
Run Code Online (Sandbox Code Playgroud)

此外,如果您需要合并特定的提交,那么您可以使用:

git cherry-pick <commit-id>
Run Code Online (Sandbox Code Playgroud)


Kri*_*rya 28

如果您已向 master 分支提交了更改。现在您想将相同的提交移至发布分支。检查提交的提交 ID(例如:xyzabc123)。

现在尝试按照命令操作

git checkout release-branch
git cherry-pick xyzabc123
git push origin release-branch
Run Code Online (Sandbox Code Playgroud)


Shi*_*hah 18

假设您想将e27af03分支 X 的提交合并到 master。

git checkout master
git cherry-pick e27af03
git push
Run Code Online (Sandbox Code Playgroud)


Lar*_*rsH 17

主要答案描述了如何将来自特定提交的更改应用到当前分支。如果这就是“如何合并”的意思,那么就按照他们的建议使用cherry-pick。

但是如果你真的想要一个合并,即你想要一个有两个父级的新提交——当前分支上的现有提交,以及你想要应用更改的提交——那么樱桃挑选将无法实现这一点。

例如,如果您的构建过程利用 git ancestry 自动设置基于最新标记的版本字符串(使用git describe),则可能需要拥有真正的合并历史记录。

您可以做一个实际的git merge --no-commit,然后手动调整索引以删除您不想要的任何更改,而不是挑选樱桃。

假设您在分支上A并且想要在分支的尖端合并提交B

git checkout A
git merge --no-commit B
Run Code Online (Sandbox Code Playgroud)

现在您已准备好创建具有​​两个父项的提交,当前提示提交为AB。但是,您可能应用了比您想要的更多的更改,包括来自 B 分支上早期提交的更改。您需要撤消这些不需要的更改,然后提交。

(可能有一种简单的方法可以将工作目录和索引的状态设置回合并之前的状态,以便您有一个干净的石板,可以首先在上面挑选您想要的提交。但是我不知道如何实现那个干净的石板。git checkout HEAD并且git reset HEAD都会删除合并状态,从而破坏了这种方法的目的。)

所以手动撤消不需要的更改。例如,你可以

git revert --no-commit 012ea56
Run Code Online (Sandbox Code Playgroud)

对于每个不需要的提交012ea56

完成调整后,创建您的提交:

git commit -m "Merge in commit 823749a from B which tweaked the timeout code"
Run Code Online (Sandbox Code Playgroud)

现在您只有您想要的更改,并且祖先树显示您在技术上从 B 合并。


Bra*_*000 13

我以前很挑剔,但不时发现我有一些神秘的问题。我在 Microsoft 工作了 25 年的资深人士 Raymond Chen 看到了一篇博客,其中描述了在某些情况下挑选樱桃可能会导致问题的一些场景。

经验法则之一是,如果您从一个分支挑选到另一个分支,然后在这些分支之间合并,那么您迟早会遇到问题。

以下是 Raymond Chen 关于此主题的博客的参考:https : //devblogs.microsoft.com/oldnewthing/20180312-00/?p=98215

我对 Raymond 博客的唯一问题是他没有提供完整的工作示例。所以我会尝试在这里提供一个。

上面的问题询问如何仅将a-good-feature分支中HEAD 指向的提交合并到master

这是如何做到的:

  1. 找到mastera-good-feature 分支之间的共同祖先。
  2. 从那个祖先创建一个新分支,我们将这个新分支称为patch
  3. Cherry 选择一个或多个提交到这个新的补丁分支。
  4. 合并的补丁分支成两个主人一个良好的特征分支机构。
  5. 分支现在将包含提交,既掌握一个良好的特征分支机构也将有一个新的共同祖先,如果执行稍后进一步合并,这将解决未来的问题。

以下是这些命令的示例:

git checkout master...a-good-feature  [checkout the common ancestor]
git checkout -b patch
git cherry-pick a-good-feature  [this is not only the branch name, but also the commit we want]
git checkout master
git merge patch
git checkout a-good-feature
git merge -s ours patch
Run Code Online (Sandbox Code Playgroud)

可能值得注意的是,合并到a-good-feature分支的最后一行使用了“ -s ours ”合并策略。这样做的原因是因为我们只需要在指向新共同祖先的a-good-feature分支中创建一个提交,并且由于代码已经在该分支中,我们希望确保没有任何机会合并冲突。如果您要合并的提交不是最新的,这将变得更加重要。

围绕部分合并的场景和细节可能非常深入,因此我建议通读 Raymond Chen 博客的所有 10 部分,以全面了解可能出错的地方、如何避免它以及为什么会出错。

  • 我认为这是完美的答案。谢谢。樱桃采摘是非常危险的。如果您从branchB 到branchA 挑选一个提交X,然后如果您在branchB 中进行提交Y 更改了提交X 的操作,并且稍后尝试将branchB 合并到branchA,则肯定会遇到合并冲突。 (3认同)

Ris*_*wal 12

我们将不得不使用git cherry-pick <commit-number>

场景:我位于一个名为release的分支上,我只想添加从master分支到release分支的少量更改。

第 1 步:签出要添加更改的分支

git checkout release

第 2 步:获取您要添加的更改的提交编号

例如

git cherry-pick 634af7b56ec
Run Code Online (Sandbox Code Playgroud)

步骤3:git push

注意:每次合并时都会创建一个单独的提交号。不要将提交号用于合并,因为这是行不通的。相反,您想要添加的任何常规提交的提交编号。

  • 并且,如果您想仔细检查结果,请使用“gitcherry-pick --no-commit 634af7b56ec”。一旦你感到高兴就承诺。 (3认同)

nrk*_*yan 5

在我的用例中,我们对 CI CD 有类似的需求。我们将 git flow 与 develop 和 master 分支一起使用。开发人员可以自由地直接合并他们的更改以进行开发或通过来自功能分支的拉取请求。然而,为了掌握,我们只通过 Jenkins 以自动方式合并来自开发分支的稳定提交。

在这种情况下,挑选樱桃不是一个好选择。然而,我们从 commit-id 创建了一个本地分支,然后将该本地分支合并到 master 并执行 mvn clean verify(我们使用 maven)。如果成功,则使用带有 localCheckout=true 选项和 pushChanges=false 的 maven 发布插件将生产版本工件发布到 nexus。最后,当一切都成功时,将更改和标签推送到原点。

示例代码片段:

如果手动完成,假设您在 master 上。但是,在 jenkins 上,当您检出 repo 时,您将位于默认分支上(如果已配置,则为 master)。

git pull  // Just to pull any changes.
git branch local-<commitd-id> <commit-id>  // Create a branch from the given commit-id
git merge local-<commit-id>  // Merge that local branch to master.
mvn clean verify   // Verify if the code is build able
mvn <any args> release:clean release:prepare release:perform // Release artifacts
git push origin/master  // Push the local changes performed above to origin.
git push origin <tag>  // Push the tag to origin
Run Code Online (Sandbox Code Playgroud)

这将使您完全控制无畏的合并或冲突地狱。

如果有更好的选择,请随时提出建议。