Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

prevent file with merge conflicts from getting committed in git

Is there any way of preventing files with merge conflict from getting committed in git? No one is going to commit files with conflict intentionally. But is there a way to prevent files from getting committed in git?

Does git have any settings or configurable values anywhere, where it can prevent files by looking for <<<<<<<, ======= or >>>>>>> symbols?

like image 432
user3586664 Avatar asked Jun 13 '14 21:06

user3586664


People also ask

How do you resolve conflicts to prevent automatic merging?

Automatic merge failed; fix conflicts and then commit the result. At least one source branch change conflicts with a target branch change. Git halts the merge and waits for you to resolve the merge conflicts. Cancel the merge by running git merge --abort , or resolve all merge conflicts then run git merge --continue .

What is the best way to resolve conflicts in git?

Git commands that can help resolve merge conflicts Passing the --merge argument to the git log command will produce a log with a list of commits that conflict between the merging branches. diff helps find differences between states of a repository/files. This is useful in predicting and preventing merge conflicts.


2 Answers

VonC's answer already explains the different kinds of hooks where you might want to check for merge commits.

If you just want a simple solution to avoid committing conflicts, that is already included with git in the default pre-commit hook sample. Just enable the hook by renaming .git/hooks/pre-commit.sample to .git/hooks/pre-commit. If you then try to commit a conflict:

$ git commit -am "Fix crash in frobnicate"
src/foo.c:239: leftover conflict marker

Note:

The script uses git diff --check internally, which also checks for various white space problems - so you might get whitespace errors as well. You can also run git diff --check before committing to find problems. See the manpage of git diff for details and config options.

This is valid for git V2.0; no idea when it was introduced.

like image 170
sleske Avatar answered Oct 09 '22 13:10

sleske


You can use a pre-commit hook, but be aware that a git commit --no-verify would effectively ignore that.

I generally put a pre-receive hook in order to control in a (more) central point what is being pushed.

But a pre-commmit allows for a more timely detection (earlier in the development cycle).

Here is another example (in addition of jthill's comment), in perl.
It uses git diff-index -p -M --cached HEAD, that is git diff-index instead of git diff.
I have left a few other controls done by this hook, just to showcase the kind of checks you can do in such a script.

#!/usr/bin/perl

use Modern::Perl;
use File::Basename;

my $nb_errors = 0;
my $filepath;
for my $l ( split '\n', `git diff-index -p -M --cached HEAD` ) {
    if ( $l =~ /^diff --git a\/([^ ]*) .*$/ ) {
        $filepath = $1;
    }
    given ( $l ) {
        # if there is a file called *.log, stop
        when ( /\.log/ ) {
            say "$filepath contains console.log ($l)";
            $nb_errors++;
        }
        # check if there is a warn, that could be unconditionnal, but just warn, don't stop
        when ( /^[^(\#|\-)]+warn/ ) {
            # stay silent if we're in a template, a "warn" here is fair, it's usually a message or a css class
            unless ($filepath =~ /\.tt$/) {
            say "$filepath contains warn ($l)";
            }
        }
        # check if there is a ` introduced, that is a mysqlism in databases. Can be valid so don't stop, just warn
        when (/^\+.*`.*/) {
            say "$filepath contains a ` ($l)";
        }
        # check if there is a merge conflict marker and just warn (we probably could stop if there is one)
        when ( m/^<<<<<</ or m/^>>>>>>/ or m/^======/ ) {
            say "$filepath contains $& ($l)";
        }
    }
}

if ( $nb_errors ) {
    say "\nAre you sure you want to commit ?";
    say "You can commit with the --no-verify argument";
    exit 1;
}
exit 0;
like image 6
VonC Avatar answered Oct 09 '22 13:10

VonC