1

I'm merging changes from a stable branch back onto the development branch. I want it to be a "real" merge, by which I mean it should show a merge when I do git --graph --oneline.

The catch is, I don't want to commit all the messages from the branch, but just my merge commit message. (Our developers' commit messages must conform to a certain pattern, enforced by a remote hook, but some of the commits on the branch are from a 'release' user that doesn't have to conform and doesn't.)

Is there a way I can perform a "real" merge without pushing the commit messages from the branch?

Here is how I'm merging at the moment (from master):

git merge -s recursive -X ours --no-commit 1.0_BRANCH

And here is what my (sanitised) graph looks like after I commit, which is exactly what I want:

*   b3492a7 - (HEAD, master) DEV-3: Merging patch fix onto master <graham>
|\  
| * eec2ef6 - (origin/1.0_BRANCH, 1.0_BRANCH) [maven-release-plugin] prepare for next development iteration <release>
| * c14dee4 - (application-1.1) [maven-release-plugin] prepare release application-1.1 <release>
| * 40687a4 - DEV-3: Fix to go into the patch <graham>
| * 4e71c98 - [maven-release-plugin] prepare for next development iteration <release>
| * c8828bb - (application-1.0) [maven-release-plugin] prepare release application-1.0 <release>
| * 46a9a59 - [maven-release-plugin]  copy for branch 1.0_BRANCH <release>
* | 5ca3ec6 - (origin/master, origin/HEAD) DEV-2: First feature commit of next release <graham>
* | bd797d3 - [maven-release-plugin] prepare for next development iteration <release>
|/  
* afff00f - [maven-release-plugin] prepare branch 1.0_BRANCH <release>
* b9329fb - DEV-1: Last feature commit before release <graham>

My problem is when I try to push, our remote hook rejects the push because the commit message in eec2ef6 doesn't conform and I'm not the release user. Can I push my merge with just my message from b3492a7, or do I have to squash the merge (which I believe means the graph won't show it as a merge)?

Graham Lea
  • 5,797
  • 3
  • 40
  • 55

2 Answers2

2

You can't push a merge without the remote knowing about all parents of the commit.

You'll either have to squash, which as you guessed will destroy the history of that branch and merge, or ideally you can alter your remote git hook to be a little smarter about what it rejects. Perhaps it could ignore all commits from the 'release' user.

jbowes
  • 4,062
  • 22
  • 38
  • Making the hook smarter is a good suggestion. Under the hood, is it the case that I'm actually pushing those commits again, but on a different branch, or am I just telling remote that I've merged those commits in? – Graham Lea Nov 03 '12 at 12:23
  • If the commits already exist on the remote end, they won't be transferred again. However, the hooks don't know that the commits already existed on the remote end or not. You could try and write some logic in your hooks to ignore one side of a merge, or ignore commits reachable from other branches, but IMO special casing for your 'release' user would be easier. – jbowes Nov 03 '12 at 12:31
  • The hook can infer whether the commits already existed, depending on how it's implemented. If it's configured as an update hook, it'll be called once for each series of commits that are being pushed to the server – Daniel Dec 31 '12 at 05:44
0

Your current model seems to mean that only the user 'release' can merge back a feature branch to dev; which isn't practical since only developers can manage such a merge properly.

If you can improve on the hook, you could use an algorithm similar to the one presented in "Have remote git repository refuse merge commits on push":
By using git rev-list --parents <OLD>..<NEW>, you can determine if one of the parent has <release> in it, and choose to allow that.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250