Git: как запросить «интерактивное слияние» всегда? - PullRequest
2 голосов
/ 16 марта 2012

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

Если я правильно понял, пользовательский драйвер слияния - это почти то, что мне нужно.Лучшее, что я понял, - это использование git-merge-file в специальном драйвере слияния, чтобы получить нормальный результат слияния, и просто выйти из 1, чтобы пометить результат как всегда конфликтующий.Таким образом, git остановится во время слияния, и я могу проверить результат слияния перед завершением слияния.

Однако ожидаемые изменения в этом файле очень малы, и лучшим способом будет запустить что-то похожее на "gitдобавить -i "и выбрать" patch "и применить один блок за раз.

Есть ли простой способ написать драйвер слияния, который ведет себя как" git add -i "для всех слияний в этот файл (гдевозможный ханк для применения - результат автоматического слияния)?

Кроме того, если я правильно понял, драйвер слияния будет вызываться только для конфликтов на уровне файлов.Можно ли запросить аналогичную ручную проверку для специально помеченных файлов?Я думаю, что пометив новый файл как «хрупкий» в gitattributes перед выполнением слияния, а затем некоторая магия git merge (или фильтр filter) попросит меня проверить, что новый специальный файл подходит для объединенной ветви.

1 Ответ

0 голосов
/ 08 августа 2012

Я добавляю свое текущее решение сюда, потому что это лучше, чем ничего, но все еще не хватает интерактивного решения, которое я ищу. Решение состоит из трех частей:

  1. создать файл bin/merge-and-verify со следующим содержимым:

    #!/bin/bash
    # git merge driver that does normal merge but marks the result as conflicting
    
    # make a copy of original version
    cp "${1}" "${1}.tmp"
    ORIG_HASH=$(git hash-object "${1}")
    WORKFILE=$(git ls-tree -r HEAD | fgrep "$ORIG_HASH" | cut -b54-)
    git merge-file -L "My version (working directory)" -L "Base (common ancestor)" -L "Merge head (remote change)" "${1}" "${2}" "${3}"
    # display changes made
    echo "-----------------------------------------------------"
    echo "Making following changes automatically:"
    echo "(Confirm changes with 'git add $WORKFILE')"
    echo "-----------------------------------------------------"
    diff -u --label "Original" "${1}.tmp" --label "Automatically modified" "${1}"
    echo "-------------------------------------------------"
    # remove our extra copy
    rm -f "${1}.tmp"
    exit 1
    
  2. создать / изменить файл `.gitattributes следующим образом:

    [attr]FRAGILE merge=merge-and-verify
    
    relative/path/to/fragile.file FRAGILE
    
  3. выполните следующую команду, чтобы активировать драйвер в рабочем каталоге

    git config merge.merge-and-verify.driver "./bin/merge-and-verify %A %O %B"
    

Теперь любое изменение любого файла, помеченного FRAGILE, приведет к обычному автоматическому слиянию, при котором результат автоматического слияния будет отображаться в консоли с подсказкой о том, как подтвердить изменения (git add relative/path/to/fragile.file), если изменения выглядят вменяемыми. Если вам не нужен подробный вывод на консоль во время слияния, вам просто нужны git merge-file и exit 1 в драйвере.

Отсутствующие фрагменты: из-за внутреннего поведения git драйвер слияния не вызывается, если в истории файла нет конфликта. Например, если новый файл FRAGILE был добавлен в другую ветку, которая объединена с master, драйвер объединения не будет вызван, потому что нет необходимости объединять какие-либо файлы (насколько известно git, в этом случае объединение ветвь просто добавляет новый файл, который ни с чем не конфликтует, поэтому нет необходимости в драйвере слияния).

...