Подтвердить что ты не робот

Предотвращать попытку файла с конфликтами слияния в git

Есть ли способ предотвратить файлы с конфликтом слияния, чтобы получить сообщение в git? Никто не намерен собирать файлы с конфликтом намеренно. Но есть ли способ предотвратить фиксацию файлов в git?

Имеет ли git какие-либо настройки или настраиваемые значения в любом месте, где он может предотвращать файлы, ища символы <<<<<<<, ======= или >>>>>>>?

4b9b3361

Ответ 1

Вы можете использовать pre-commit hook, но имейте в виду, что git commit --no-verify эффективно игнорирует это.

Я обычно кладу крюк pre-receive, чтобы контролировать в (более) центральной точке то, что толкается.

Но a pre-commmit позволяет более своевременно обнаруживать (ранее в цикле разработки).

Вот еще один пример (кроме jthill comment), в perl.
Он использует git diff-index -p -M --cached HEAD, то есть git diff-index вместо git diff.
Я оставил несколько других элементов управления, сделанных этим крюком, просто чтобы продемонстрировать вид проверок, которые вы можете сделать в таком 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 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;

Ответ 2

Ответ VonC уже объясняет разные типы перехватов, в которых вы можете проверить фиксацию слияния.

Если вам просто нужно простое решение, чтобы избежать конфликтов, которые уже включены в git в образце привязки pre-commit по умолчанию. Просто включите hook, переименовав .git/hooks/pre-commit.sample в .git/hooks/pre-commit. Если вы затем попытаетесь зафиксировать конфликт:

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

Примечание:

script использует git diff --check внутренне, что также проверяет различные проблемы с пробелом - так что вы можете получить ошибки в пробелах. Вы также можете запустить git diff --check перед тем, как найти проблемы. См. Справочную страницу git diff для подробностей и параметров конфигурации.

Это справедливо для git V2.0; не знаю, когда он был представлен.

Ответ 3

Я добавил unit test, чтобы просмотреть все файлы в каталоге решений для строки маркера конфликта

[TestClass]
public class SolutionValidationTests
{
    [TestMethod]
    public void CheckForMergeConflicts()
    {
        var solutionValidationScripts = new SolutionValidationScripts();
        var mergeConflictCheckOkay = solutionValidationScripts.CheckForGitMergeConflict();
        Assert.IsTrue(mergeConflictCheckOkay);
    }
}

SolutionValidationScripts, определенные ниже:

public class SolutionValidationScripts
{
    public bool CheckForGitMergeConflict()
    {
        var failCount = 0;
        System.Diagnostics.Debug.WriteLine($"{DateTime.Now.ToString(@"dd-MMM-yyyy HH:mm:ss")}: Starting");

        var currentDirectory = System.IO.Directory.GetCurrentDirectory();
        var sourceFolder = "";

        // Change to suit the build location of your solution
        sourceFolder = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(System.IO.Directory.GetCurrentDirectory())));
        // break up the string so this file doesn't get flagged in the test
        string searchWord = "<<<<<<< " + "HEAD";

        List<string> allFiles = new List<string>();
        AddFileNamesToList(sourceFolder, allFiles);
        for (int i = 0; i < allFiles.Count; i++)
        {
            // 35 sec
            var fileName = allFiles[i];
            string contents = File.ReadAllText(fileName);
            if (contents.Contains(searchWord))
            {
                // For faster result.. no need to continue once a problem is found
                // throwing an exception here actually works better than an early return to help resolve the issue
                throw new Exception(fileName);
            }
        }
        return (failCount == 0);
    }

    private void AddFileNamesToList(string sourceDir, List<string> allFiles)
    {
        string[] fileEntries = Directory.GetFiles(sourceDir);
        foreach (string fileName in fileEntries)
        {
            allFiles.Add(fileName);
        }

        //Recursion    
        string[] subdirectoryEntries = Directory.GetDirectories(sourceDir);
        foreach (string item in subdirectoryEntries)
        {
            // Avoid "reparse points"
            if ((File.GetAttributes(item) & FileAttributes.ReparsePoint) != FileAttributes.ReparsePoint)
            {
                AddFileNamesToList(item, allFiles);
            }
        }
    }
}

Ответ 4

Прямой подход с использованием крючка предварительной фиксации, адаптированный из здесь, но улучшенный, чтобы быть немного более тщательным и тщательным:

#!/bin/sh

changed=$(git diff --cached --name-only)

if [[ -z "$changed" ]]; then
    exit 0
fi

echo $changed | xargs egrep '^[><=]{7}( |$)' -H -I --line-number

# If the egrep command has any hits - echo a warning and exit with non-zero status.
if [ $? == 0 ]; then
    echo "WARNING: You have merge markers in the above files. Fix them before committing."
    echo "         If these markers are intentional, you can force the commit with the --no-verify argument."
    exit 1
fi

Не забудьте сделать исполняемый файл hook (chmod u+x pre-commit)!