在进行git合并时是否可以排除特定的提交?

在进行git合并时是否可以排除特定的提交?,git,Git,假设我想从发布分支合并到主分支,并且在发布分支中有一些我不想包含在主分支中的提交。是否有方法进行合并,以使一个或多个提交不会被合并 到目前为止,我的策略是(在master中)执行以下操作: 有更好的方法吗?创建一个新分支,以交互方式重新设置分支的基础,删除不需要的提交,然后合并该分支 您不能在不重新灰化的情况下从分支的中间进行更改,但当它在以后的合并中看到相同的更改时(例如,从樱桃采摘和其他方式中看到相同的更改),就会发生正确的事情。无法直接执行此操作的原因是,每个提交都包含指向父提交的链接(通

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

到目前为止,我的策略是(在master中)执行以下操作:


有更好的方法吗?

创建一个新分支,以交互方式重新设置分支的基础,删除不需要的提交,然后合并该分支


您不能在不重新灰化的情况下从分支的中间进行更改,但当它在以后的合并中看到相同的更改时(例如,从樱桃采摘和其他方式中看到相同的更改),就会发生正确的事情。

无法直接执行此操作的原因是,每个提交都包含指向父提交的链接(通常只有一个,但对于合并有多个链接)。这样,如果您有一个commit(通过它的SHA1和),整个历史也是固定的,因为父对象还包含到其父对象的链接,等等。因此,在历史上删除补丁的唯一方法就是编写一个新的补丁。在新创建的分支上使用git-rebase-i可能是实现这一点的最简单方法。

我找到了一个适合我的解决方案

假设您想排除文件
config.php

关于分支机构A:

  • 在同一目录中创建一个名为
    .gittributes
    的文件,行为:
    config.php merge=ours
    。这告诉git在合并文件时要使用什么策略。在这种情况下,它始终保留您的版本,即您要合并到的分支上的版本

  • 添加
    .gittributes
    文件并提交

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


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

    如果您只想排除最后的一些提交,您可以只提交到特定的提交编号:

    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
    

    还可以修改.git/info/attributes文件并将其保存在.git文件夹中,而不是添加所有需要最终将其添加到源代码管理中的.gittribute文件。

    如果您有一个支持分支来修复bug并生成新版本。在master上,您有下一个版本,您还可以在其中频繁构建新版本

    每次构建新版本时,您都会更改某个文件中的版本,提交该新文件,创建标记并推送。现在,从support到master的合并在包含版本信息的文件中始终存在冲突

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

    让我们使用下面的例子

          C---D*---E---F* support
         /
    A---B---G---H*---I master
    
    其中,带星号的提交仅包含因版本更改而引起的更改,这些更改应在合并过程中忽略

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

    多个合并提交 使用
    -s-ours
    参数,我们告诉git只记录合并而不改变工作区。这是可比的

    以上内容将导致以下布局

          -------------C---D*---E---F* support
         /              \   \    \   \
    A---B---G---H*---I---J---K----L---M master
    
          C---D*---E---F* support
         /              \
    A---B---G---H*---I---J master
    
    使用cherry-pick进行一次合并提交 首先,我们开始合并,但只记录我们正在合并的内容,不改变工作区,也不进行合并提交。然后我们选择合并提交,同样没有提交。最后,我们提交合并

    以上内容将导致以下布局

          -------------C---D*---E---F* support
         /              \   \    \   \
    A---B---G---H*---I---J---K----L---M master
    
          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'
    

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

  • 偷偷地把它们藏起来(不是我最喜欢的)
  • 明确跳过它们
  • 显式撤消它们
  • 不幸的是,2号不可能在历史图表中表达出来

    1是可能的,但我永远不会这样做:合并提交可以包含更改通常,合并提交指向另外两个分支合并的结果:在这些分支中开发的所有内容都应该在合并后的代码中(即,在合并提交所指向的代码中)。在这件事上不应该有别的事

    但是令人惊讶的是,您可以更改整个代码库并将其表示为合并。合并的效果是双重的:它合并了历史树,并且应该合并两个代码库。前者确实如此(否则没有人称之为合并),后者则可能失败,例如,当出现合并冲突时,它被错误地解决了(然后代码库没有正确地合并)


    其他一些答案暗示了这种隐藏。我建议使用显式方式:合并加还原提交。

    但是,当您再次尝试合并该分支时会发生什么情况?要使用哪些确切的命令来完成此操作?我看不出有什么办法可以“放弃”不想要的东西commits@Henning当您
    git rebase-i other branch
    时,它会为您提供一个包含大量提交的文本编辑器。删除不需要的行。对于将来的读者,这对于明确不包括特定文件非常有用。(在我的例子中,我将不同的分支部署到不同的服务器,并希望在每个分支上保持我的Capistrano部署脚本的唯一性。)由于某些原因,这对我来说不起作用。我创建了一个新的分支,并在两个分支中添加了.gittributes文件。当我合并回原始分支时,它似乎完全忽略了.gittattributes中的行,并且不管怎样都会拉入更改过的文件。有什么我不知道的吗?对我不管用。我也遵循了VonC列出的问题中的说明。我在窗户上。我试图避免合并的文件是一个点文件(.core.config)。我需要在它的名字周围加引号吗?这只在两个文件被修改时有效,否则就不能合并我们的文件ignored@robbles考蒙斯是对的。基本上,t
    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'