在做git合并时可以排除特定的提交吗?

假设我想从发布分支合并到主分支,并且在发布分支中有一些提交,我不想包含在主分支中。 有没有办法进行合并,以便这些提交中的一个或多个不会被合并?

我到目前为止的策略是做以下事情(主人):

git merge --no-commit release-branch # Resolve conflicts and apply reverse patch of the commits that I don't want included git commit # Edit commit message so that it lists the commits that have been reverse-patched 

有没有更好的方法来做到这一点?

创build一个新的分支,交互地重新分支分支,并放弃你不想要的提交,然后合并。

你不能在没有重新哈希的情况下从一个分支中取出变化,但是当它在后面的合并中看到相同的变化时(例如,从樱桃采摘到什么),正确的事情将会发生。

我在Pro Git书中find了适合我的解决scheme。

假设你想排除文件config.php

分支A:

  1. 在同一个目录下创build一个名为.gitattributes的文件,这行代码如下: config.php merge=ours 。 这告诉git合并文件时使用什么策略。 在这种情况下,它始终保持您的版本,即。 您正在合并到的分支上的版本。

  2. 添加.gitattributes文件并提交

在分支B上:重复步骤1-2

现在尝试合并。 你的文件应该保持不变。

如果您有一个支持分支,您可以修复错误并构build新版本。 在大师你有下一个版本,你也经常build立新版本。

每当你build立一个新的版本,你在某个文件中改变版本,提交这个新文件,创build一个标签并推送。 现在从支持合并到主将在包含版本信息的文件中总是有冲突。

如果包含版本信息的文件包含版本信息,则可以使用fcurella的答案。 但是,如果它确实也可能包含可合并信息(pom.xml,gradle.properties,MANIFEST.MF,…),则必须执行一些额外的操作。

让我们使用下面的例子

  C---D*---E---F* support / A---B---G---H*---I master 

其中星星提交只包含由于在合并期间应该忽略的版本更改所引起的更改。

要将支持合并到主版本中而不会因版本构build而发生合并冲突,可以执行以下任一操作:

多次合并提交

 git checkout master git merge C git merge D -s ours git merge E git merge F -s ours 

通过-s ours论点,我们告诉git只logging合并而不改变工作空间。 这相当于svn的--record-only选项 。

以上将导致以下布局

  -------------C---D*---E---F* support / \ \ \ \ A---B---G---H*---I---J---K----L---M master 

一个合并提交使用樱桃挑选

 git checkout master git merge support -s ours --no-commit git cherry-pick CE --no-commit git commit -m 'merged support into master' 

首先我们开始一个合并,但只logging我们正在合并,而不改变工作区,没有合并提交。 然后,我们挑选合并的承诺,再次没有承诺。 最后,我们正在进行合并。

以上将导致以下布局

  C---D*---E---F* support / \ A---B---G---H*---I---J master 

甚至可以自动采摘樱桃。

 git checkout master git merge support -s ours --no-commit for id in `git log support --reverse --not HEAD --format="%H [%an] %s" | grep -v "bump version" | sed "s/\(\w*\)\s.*/\1/g"` do git cherry-pick --no-commit $id done git commit -m 'merged support into master' 

为什么这不能直接完成的原因是,每个提交包含父提交的链接(通常只有一个,但合并几个)。 这样,如果你有一个提交(通过它的SHA1总和),整个历史也是固定的,因为父母也包含与父母的链接等等。 所以在历史上留下补丁的唯一方法是写一个新的补丁。 在新创build的分支上的git rebase -i可能是最简单的方法。

还可以修改.git / info / attributes文件并将其保存在.git文件夹中,而不是添加.gitattribute文件,最终将它们添加到源代码控制中。

主要的问题是:你想如何表示你想跳过的提交?

  1. 偷偷地藏起来(不是我最喜欢的)
  2. 明确地跳过它们
  3. 明确地撤消它们

很不幸的是,不行。 2在历史图中是不可能expression的。

第一是可能的,但我永远不会这样做:合并提交可以包含更改。 – 通常合并提交指向两个以上更多分支合并的结果:在这些分支中开发的所有东西都应在合并后的代码中(即在合并提交所指向的代码中)。 在这个提交中没有别的东西。

但令人惊讶的是,您可以更改整个代码库并将其表示为合并。 合并的效果有两方面:合并历史树合并两个代码库。 前者确实(否则没有人称之为合并),后者可能会失败,例如,当合并冲突发生并且被错误地解决(那么代码库没有合并)。

其他一些答案暗示了这种隐藏。 我build议明确的方式:合并加回复提交。

如果你只想排除最后一些提交,你可以提交一个特定的提交号码:

 git checkout partlyMergedFrom git whatchanged --> find the commit hash up to where you want to merge git checkout partlyMergedInto git merge e40a0e384f58409fe3c864c655a8d252b6422bfc git whatchanged --> check that you really got all the changes you want to have