0

Some contributors in our project likes to work on master directly and still forget to git pull --rebase.

Is there a way to refuse on the server side commit with commit like Merge branch 'master' of ... into master ?

malat
  • 12,152
  • 13
  • 89
  • 158
  • A bit similar to this, no? http://stackoverflow.com/questions/2039773/have-remote-git-repository-refuse-merge-commits-on-push – VonC Mar 30 '11 at 07:24

1 Answers1

1

As VonC comments, you can do this with a simpler version of the pre-receive hook that I wrote for that question.

To rephrase what you're asking, you would like a pre-receive hook on your server that will refuse any push to master which has any non-linear history, i.e. introduces any commit with more than one parent. This hook should do what you want:

#!/usr/bin/ruby -w

ref_to_check = "refs/heads/master"

STDIN.each_line do |line|
    rev_old, rev_new, ref = line.split(" ")

    if ref == ref_to_check
        merges_introduced = `git rev-list --merges #{rev_old}..#{rev_new}`
        unless merges_introduced.strip.empty?
            STDERR.puts "Refusing push to #{ref}, since it would create non-linear"
            STDERR.puts "history by introducing the following merge commits:"
            STDERR.puts merges_introduced
            exit(1)
        end
    end
end

Update: in Jefromi's answer to the linked question, he demonstrates that using git rev-list --merges is much neater, so I've updated this script to use that, and fixed it to loop over every ref that the push is trying to update.

Community
  • 1
  • 1
Mark Longair
  • 446,582
  • 72
  • 411
  • 327
  • Do I something special. Here is what I get: Counting objects: 13, done. Delta compression using up to 4 threads. Compressing objects: 100% (7/7), done. Writing objects: 100% (7/7), 668 bytes, done. Total 7 (delta 6), reused 0 (delta 0) error: cannot run hooks/pre-receive: No such file or directory To ssh://malat@gdcm.git.sourceforge.net/gitroot/gdcm/gdcm ! [remote rejected] master -> master (pre-receive hook declined) error: failed to push some refs to 'ssh://malat@gdcm.git.sourceforge.net/gitroot/gdcm/gdcm' – malat Mar 30 '11 at 12:47
  • The "shebang" line points to `/usr/bin/ruby` - do you have ruby installed on that machine, and is that where the binary is located? – Mark Longair Mar 30 '11 at 13:17
  • (You could easily do the same in shell script or any other scripting language, of course.) – Mark Longair Mar 30 '11 at 13:18
  • I do have ruby. This is a sourceforge restriction. The following does not even work for me: https://fedorahosted.org/fedora-infrastructure/attachment/ticket/1342/pre-receive – malat Mar 30 '11 at 15:02
  • 1
    Whether you have Ruby on your local machine obviously doesn't matter - it's whether SourceForge allows hooks in that language. That this hook needs to be set up on SourceForge is the kind of important point that it would be helpful to mention in the question in the first place :) – Mark Longair Mar 31 '11 at 07:26
  • ruby is installed on sourceforge. I can see it when ssh'ing on sf.net. – malat Mar 31 '11 at 07:33