Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7895067
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 3, 20262026-06-03T07:33:08+00:00 2026-06-03T07:33:08+00:00

I wanted to set up a pre-receive hook that does a logic such that

  • 0

I wanted to set up a pre-receive hook that does a logic such that

  • Checks if there are any merge commits
  • Checks if a new branch is pushed
  • Checks if there are multiple commits.

If any of the above is present, then interact with the user to check with him if he would like to push the change and if yes, then push the change and else drop it.

Is there a possibility to achieve the above in pre-receive hook in git?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-03T07:33:10+00:00Added an answer on June 3, 2026 at 7:33 am

    You can’t interact with the user in the pre-receive hook, at least not in general, since the user might be on some other machine doing an “ssh”, and standard input is not going to the user. (You might be able to cobble something up by inspecting uids and/or user names and such, and escaping out to a script that “calls back” the user. I leave experiments in that direction for you.) You can do all those checks, though.

    The pre-receive hook gets (on stdin) a series of lines:

    <old-value> SP <new-value> SP <ref-name> LF
    

    (quoted from githooks(5)). If the ref-name has the form:

    refs/heads/<branchname>
    

    then the given branch is being created, deleted, or updated. The branch is being created if <old-value> is 40 0s; it’s being deleted if <new-value> is 40 0s; and it’s being updated otherwise. (There are things other than refs/heads/*; see the git-send-email hook for a complete list.)

    If the branch is being updated, <old-value> is the commit ID to which it used to point, and <new-value> is the commit ID to which it will point if the update is allowed (this depends on both the pre-receive hook and the update hook).

    Here’s a hook that simply detects your second and third cases (plus deletion). To find out if there are merges, you’ll have to go through each rev in $between and see whether any is a merge (i.e., has more than one parent). To stop the commit, exit nonzero instead of returning 0.

    #! /bin/sh
    
    check()
    {
        local old=$1 new=$2 longref=$3
        local between rev
    
        if expr $old : '^00*$' >/dev/null; then
            echo creating new branch ${longref#refs/heads/}
            return 0
        fi
        if expr $new : '^00*$' >/dev/null; then
            echo removing branch ${longref#refs/heads/}
            return 0
        fi
        between=$(git rev-list $old..$new)
        case "$between" in
        *$'\n'*)
            echo at least two revs
            for rev in $between; do git log -1 --oneline $rev; done
            return 0
        esac
        echo only one rev
        return 0
    }
    
    while read old new longref; do
        case $longref in
        refs/heads/*) check $old $new $longref;;
        esac
    done
    

    (you can inspect all the revs in $between as they have already been sent to the remote repo, even if you’re going to reject them).


    Update: I figured out a way to make this work even when using the ssh transport, which does not let you smuggle in any extra data.

    I modified (and renamed) the check function. Under the new name, get_confirmation, it’s meant to figure out (and return 0 for) cases where you don’t want to allow the push by default (and return 1 for cases where it’s to be allowed).

    Then, in the main loop, you can do this:

    case $longref in
    refs/heads/*)
        if get_confirmation $old $new $longref; then
            case $PWD in
            *.allow.git)
                echo 'allowed via alternate path'
                ;;
            *.git)
                echo "denied ... push to ${PWD%.git}.allow.git to allow"
                exit 1
                ;;
            *)
                echo "denied, don't know where I am"
                exit 1
                ;;
            esac
        fi
        ;;
    # add more cases here if desired
    esac
    

    This assumes that you push to a --bare clone that lives in /some/path/to/repo.git.

    To make an equivalent repo that allows pushes, you have to create an actual parallel directory whose name ends in repo.allow.git. This directory should contain one actual file, HEAD, copied from the plain repo; and everything else in the directory can be a symbolic link to ../repo.git/<same>:

    cd /some/path/to
    mkdir repo.allow.git
    cd repo.allow.git
    ln -s ../repo.git/* .
    rm HEAD; cp ../repo.git/HEAD .
    

    The reason that HEAD has to be an ordinary file is that otherwise git push won’t treat this as a valid repo (it’s only allowed to be a symlink if it’s a link to a branch, and that’s the “old way” of doing a symbolic ref).

    A regular git push fails, and you can instead git push remotehost:/some/path/to/repo.allow.git to make it go through. Of course your users might get in the habit of doing that all the time, obviating the entire purpose of this hack, but maybe they won’t.

    This all does assume that your remote repo is a Unix-like host, of course (i.e., supports symlinks).

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I set up a new webapp Maven project and wanted to test it with
I am new to jquery. I wanted to generated a set of image button
I just started a new Haskell project and wanted to set up a good
I know there is an invoke function that does the stuff, I am overall
I wanted to set some handler for all the unexpected exceptions that I might
I have a div that's set to width 100%. I wanted to set a
I wanted to set up a simple data communication between two C# applications, and
I wanted to use a hashtable as set of some objects for a graphic
I wanted to be able to set the keyEquivalent of an NSMenuItem based on
I set up a Zend Framework application using Zend_Tool, but I wanted multiple modules

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.