6

Is it possible to force git to only merge remote tracking branches into the corresponding local branch? E.g. assume origin/X tracks X on origin and corresponds to local X and the same for origin/Y and Y. I want to prevent users to do git checkout Y; git merge origin/X. Is it possible? How?

Edit:

To make it clear: The workflow is not the problem. People try to merge the wrong branches because they forgot to checkout the correct branch before merging. It is not about "offenders" or pushing to the central repo. It's just people forgetting at which branch they are. The last "incident" was literally:

"I should commit and push real quick before I leave.

git add .
git commit -am 'Feature Y'
git push origin

Whoops, whats that. It tells me to merge branch origin/X first. OK whatevs.

git merge origin/X

Whoops, whats that now. Lots of merge conflicts. What have I done. I better call somebody..."

The user was working in branch Y and did not understand what the git push origin was saying. It told it that origin/X needed merging and that's what he did, because he wanted to "push real quick". In the case above branch X was one commit ahead of the local X, so pushing all branches yielded the "needs merging" error.

I adjusted the "workflow" now to always push a branch explicitly, e.g. git push origin Y instead of just git push origin, but that's not curing the problem. It should (usually) not be allowed without a warning to merge origin/X with Y. For merging feature branches X and Y can be merged.

4
  • I guess you cannot force this from the server. If it is possible (I don't know), your users will have to set up their repo (.git metadata) to forbid this behavior. Commented Aug 7, 2012 at 15:40
  • 3
    Your question is in the form of a solution. Could you please provide details on what you exactly want to achieve? Why can't users make such merges?
    – Ikke
    Commented Aug 7, 2012 at 15:59
  • @Ikke: I don't think I understand what you mean. Users can make such merges but I don't want that, because it is almost always by mistake. Commented Aug 7, 2012 at 16:30
  • Might be best to approach it as a workflow policy. Can you strip push access for repeat offenders? Commented Aug 7, 2012 at 21:18

3 Answers 3

3

As git is distributed, there is no way to prohibit users to do it locally, and I'm not even sure if it's possible with local hooks.

And because a user doesn't have to push all local refs, there is no way to prevent it on the server either.

Edit:

You are talking about mistakes. Git allows users to fix their mistakes and undo the error, but that requires them to notice it. Like I said in the comments you could try to use hooks for this, but there is no pre-merge hook or something.

3
  • I don't want to prohibit it on the server. It would be sufficient if users can configure their local repos to warn before such a merge or to disallow it locally. Commented Aug 7, 2012 at 16:33
  • The best bet you could make is the precommit hook. But I can't think of a way to do that.
    – Ikke
    Commented Aug 7, 2012 at 16:35
  • 1
    Yes, the mistakes can be corrected, but I am the one who has to do it. This happened multiple times in the last weeks and they noticed the mistake but did not know how to correct it. Commented Aug 7, 2012 at 16:43
2

I think that you may be approaching this from the wrong angle.

Why is merging origin/X into Y a problem? If it is because, for instance, Y is a release branch (which is tracking origin/Y), while origin/X is a development branch, and you don't want development code leaking into a production release, then it is more important to control origin/Y than to control Y.

As Christopher suggests in a comment, this should really be taken care of by your workflow.

To prevent mistakes though, as Ikke points out, you may want to make use of permissions to limit who can update different remote references. For example, gitolite allows very fine grained access control. From Scott Chacon's excellent Pro Git:

Gitolite allows you to specify permissions not just by repository, but also by branch or tag names within each repository. That is, you can specify that certain people (or groups of people) can only push certain "refs" (branches or tags) but not others.

One option is to only allow your continuous integration server to push to your release branches, and only then after your integration and unit tests have passed. This sort of automated workflow can really help prevent mistakes propagating.

1

One way is to give them alternative commands. I rarely use git merge; instead, I use the bash functions below. If you're running on Windows (and not using Cygwin), I suppose you could create batch files to do the same thing.


function branch
{ 
    if [ $# == 0 ] ; then
        git branch | grep '^\*' | sed -e 's/.* //' ;
    elif git branch | grep -q " $1\$" ; then
        git checkout $1
    else
        git checkout master
        git checkout -b $1
    fi ;
}

function push
{
    src=`branch`
    if [ $# == 0 ] ; then
        git push origin ${src} ;
    elif [ $# == 1 ] ; then
        git push $1 ${src} ;
    else
        git push $1 ${src}:${2} ;
    fi ;
}

function pull
{
    if [ $# == 0 ] ; then
        src=`branch` ;
        git pull origin ${src} ;
    elif [ $# == 1 ] ; then
        branch $1
        git pull origin $1 ;
    else
        echo "usage: pull [BRANCH]" ;
    fi ;
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.