Clintm
Clintm

Reputation: 4877

How can I prevent git push if local modifications are detected (including untracked files)?

Sometimes someone on our team does a git push and breaks the build because his local build works but he has forgotten to commit all his local modifications and untracked files to git before he pushes.

I'd like to prevent this... I poured over the docs for an hour or so today and couldn't find anything built in.

Does anyone have any solutions?

Upvotes: 8

Views: 3134

Answers (5)

Matt Curtis
Matt Curtis

Reputation: 23624

You can use the pre-push hook (since git 1.8.2).

Your pre-push hook could check the exit code of git status, returning 0 (OK to push) if git status returns non-zero, otherwise returning 1 (do not allow push).

The man page for git-status says:

If there is no path that is different between the index file and the current HEAD commit (i.e., there is nothing to commit by running git commit), the command exits with non-zero status.

Any repo created with git 1.8.2 or later will have pre-push.sample in the .git/hooks directory, which is a useful starting point for implementing your policy. There are more good examples of using the pre-push hook here: http://blog.ittybittyapps.com/blog/2013/09/03/git-pre-push/

Be aware that the hook does not run on the upstream repo. Each clone would need to have this hook installed, to enforce your policy. (Hooks are not cloned as part of the repository. As hooks are executed by git, this design prevents malicious hooks running on a developer's machine. Malicious code should instead go into a Makefile or configure script, which developers run without looking.)

Upvotes: 8

Clintm
Clintm

Reputation: 4877

I ended up adding an ant target to our local build before pushing to our main repo... here's the target... in case someone else was looking for a step in the right direction.

Thanks to all who answered.

<target name="git-status-check">
    <echo>Performing git working directory check for local modifications or untracked files.</echo>
    <exec executable="git" failifexecutionfails="true"
        outputproperty="git.check">
        <arg value="status"/>
    </exec>
    <echo>${git.check}</echo>
    <propertyregex property="dirty.working.dir" input="${git.check}" regexp="working directory clean" 
        select="\1" casesensitive="false" />
    <fail message="Git status reports that you have local modifications or untracked changes in your working dir... did you forget to commit these changes? ${line.separator} ">
        <condition>
            <not>
                <isset property="dirty.working.dir" />
            </not>
        </condition>
    </fail>
    <echo>Git status reported a clean working dir continuing build...</echo>
</target>

Upvotes: 0

Tesserex
Tesserex

Reputation: 17314

Maybe put an alias, either in your shell or git config, that replaces the default push command with a custom script that does git status first and checks for "working directory clean"? I don't know if overwriting push is possible, or if it would make it so that you couldn't then call the real push. Just an idea off the top of my head, so I don't have any idea whether it really works.

Upvotes: 0

Brian McKenna
Brian McKenna

Reputation: 46228

To automatically add changes, you might want to look into using the -a flag. From the git-commit man page:

Tell the command to automatically stage files that have been modified and deleted, but new files you have not told git about are not affected.

There doesn't seem to be any flags for git commit that adds untracked files. Remembering to do a git add . before the commit is the best solution I can think of.

Upvotes: 0

Michael Aaron Safyan
Michael Aaron Safyan

Reputation: 95609

You can use the various hooks (pre-receive, I believe) to determine if the push will break the build and reject it. In addition to that, you should tell your developers to run git status before any commit or push operation, which is an incredibly sensible rule to have in place and would deter such problems.

Upvotes: 2

Related Questions