Is it possible to exclude specific commits when doing a git merge?

Let’s say that I want to merge from a release branch to the master branch and there are some commits in the release branch that I don’t want to include in the master branch. Is there a way to do the merge so that one or more of those commits will not be merged?

My strategy so far is to do the following (in master):

  • What are the reasons and cases that cause git merge conflicts?
  • Dealing with Jekyll and Git
  • Cannot clone GIT repository on network drive
  • Why is merge-based SCM better than a lock-based system?
  • Intellij ask ssh password for each project push/pull
  • Trigger build in Jenkins when git branches are created or deleted
  • 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
    

    Is there a better way to do this?

  • find all unreferred commit in git?
  • Using git, how to do a 'use theirs' during a conflict?
  • Use Git LFS with TFS 2015 Update 2 OnPremise
  • Phing and github
  • Move modifications made in develop branch into a new git-flow feature branch?
  • git clone is aborting due to possible repository corruption on the remote side even though memory settings are done properly
  • 7 Solutions collect form web for “Is it possible to exclude specific commits when doing a git merge?”

    Create a new branch, rebase the branch interactively and drop commits you don’t want, and then merge that.

    You can’t take changes out of the middle of a branch without rehashing, but the right thing will happen when it sees the same changes in a later merge (e.g. from cherry-picking and what-not).

    I’ve found a solution that works for me in the Pro Git book.

    Let’s say you want to exclude the file config.php.

    On branch A:

    1. Create a file named .gitattributes in the same dir, with this line: config.php merge=ours. This tells git what strategy to use when merging the file. In this case it always keep your version, ie. the version on the branch you are merging into.

    2. Add the .gitattributes file and commit

    On branch B: repeat steps 1-2

    Try merging now. Your file should be left untouched.

    If you have a support branch where you fix bugs and build new versions. On master you have the next version where you also build new versions frequently.

    Every time you build a new version you change the version in some file, commit that new file, create a tag and push. Now merges from support to master will always have conflicts in the file containing the version info.

    If the file containing the version information only contains the version information, you can go with the answer of fcurella. But if it does indeed may also contain mergeable information (pom.xml, gradle.properties, MANIFEST.MF, …), you must perform some extra action.

    Lets use the following example

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

    where commits with stars contain only changes due to version changes that should be ignored during merge.

    To merge support into master without merge-conflicts due to the version builds, you can do either of the following:

    Multiple merge commits

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

    With the -s ours argument we are telling git to only record a merge without altering the workspace. This is comparable to the --record-only option of svn.

    The above will result in the following layout

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

    One merge commit using cherry-pick

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

    first we are starting a merge but only record that we are merging, without altering the workspace and without doing the merge commit. Then we are cherry-picking the commits to merge, again without commit. Finally we are committing the merge.

    The above will result in the following layout

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

    One could even automate the cherry-picking.

    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'
    

    The reason why this can’t be done directly is that every commit contains links to the parent commits (typically just one but several for merges). That way if you have one commit (by its SHA1 sum) the whole history is also fixed as the parents also contain links to their parents and so on. So the only way to leave out patches in the history is to write a new one. git rebase -i on a newly created branch is probably the easiest way of achieving that.

    It’s also possible to modify .git/info/attributes file and keep it inside .git folder instead of adding .gitattribute files all over that will require adding them to source control eventually.

    The main question is: how do you want to represent the commits you want to skip?

    1. sneakily hide them (not my favorite)
    2. explicitly skip them
    3. explicitly undo them

    Unfortunately no. 2 is impossible to express in the history graph.

    No. 1 is possible, but I would never do that: a merge commit can contain changes. – Normally a merge commit points to the result of the merge of two more more branches: all things developed in those branches should be in the code after the merge (i.e. in the code pointed to by the merge commit). And nothing else should be in this commit.

    But surprise, surprise, you can change the entire code base and represent it as a merge. The effect of a merge is two-fold: it merges the history tree and it should merge two code bases. The former it does for sure (otherwise no-one calls it a merge), for the latter it might fail, e.g. when a merge conflict arose and it was resolved wrongly (then the code bases were not merged properly).

    Some of the other answers suggest this hiding. I recommend the explicit way: merge plus revert commits.

    If you only want to exclude some commits that are at the end, you can just commit to a specific commit number:

    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 Baby is a git and github fan, let's start git clone.