"git merge -s theirs" необходимо - но я знаю, что этого не существует

У меня есть несколько удаленных репозиториев, которые я хочу объединить вместе. Некоторые из поддеревьев в этих репозиториях уникальны для удаленного (они содержат данные, специфичные для узла), другие поддеревья содержат данные, которые (предположительно) являются общими для всех пультов.

Что я хочу сделать, по существу, запускается "git pull" для каждого пульта. Это ускорит переадресацию локальной ведущей ветки вдоль ветки отслеживания для удаленного мастера для файлов, специфичных для хоста, которые были изменены на удаленном компьютере, и ничего не сделает для обычных файлов, потому что они не будут изменены.

Изменение общего файла (называть его F, с изменением F ') не должно быть проблемой, даже если это происходит только на одном пульте. git -merge выполнит правильную вещь и даст мне копию F 'в моем составном рабочем пространстве, чего я хочу. Проблема возникает, если один и тот же общий файл изменится другим способом на другом удаленном устройстве (назовите его F). git -merge предоставит мне композицию из F 'и F ", чего я не хочу. Все, что я хочу, это F".

Когда я работал с ClearCase, мы назвали это копирование-слияние. Результатом слияния всегда была точная копия вкладчика. Это звучит так же, как "git merge -s theirs", за исключением того, что он не существует.

Мне интересно, могу ли я что-то приготовить с помощью "git -read-tree -m-trivial", чтобы ускорить слияние с пути, затем сделайте некоторую магию с помощью git -merge и custom mergetool, который просто копирует файл $REMOTE в $MERGED. Но даже с этим я не вижу, как я могу остановить git -merge от компоновки F 'и F ", если это то, что слияние тривиально.

Я прочитал ссылку Есть ли "их" " версия "git merge -s ours" ? на этом сайте, а сообщение Junio ​​Hamano ссылается на объяснение, почему "git merge -s theirs" - такая плохая идея, но это не "Это случай для меня. Я действительно ценю старую историю, но мне нужно прыгать с корабля и следить за изменениями на удаленном сайте, когда это происходит. На локальном сайте нет новых работ. Ему просто нужно сформировать состав всех удаленных сайтов, взяв последний" общий" файл с последнего опрошенного пульта при его изменении.

Заранее благодарим за любую помощь, которую вы можете мне дать.

Ответ 1

Большое спасибо @VonC за предложение использования атрибута merge = custom-driver в файле .gitattributes. Хотя это будет работать, я не хочу загрязнять свое рабочее пространство файлами .git, и хотя я мог бы использовать $GIT_DIR/info/attributes, чтобы избежать загрязнения, меня беспокоит необходимость в 2 правила поймать dot файлы и неточечные файлы.

После нескольких экспериментов мне удалось найти решение с переменной конфигурации merge.default (упомянутой в man-странице gitattributes (5)). Трюк, который я пропустил, состоял в том, что merge.default берет имя настраиваемого драйвера, который вы определили ранее; вы не даете ему пользовательскую команду напрямую. Вот что работает для меня...

Сначала определите свой пользовательский драйвер копирования-слияния. Вы можете напрямую использовать команды оболочки; нет необходимости в внешнем script (просто убедитесь, что вы правильно указали метасимвол вашей оболочки):

git config merge.copy-merge.name   'Copy Merge'
git config merge.copy-merge.driver 'mv %B %A'

Обратите внимание, что mv возвращает 0 при успешном завершении, 1 при ошибке, удовлетворяя критериям для отчета, объединяет "успех" обратно в git.

Теперь скажите git, что ВСЕ слияния объединяются в копии:

git config merge.default copy-merge

Привет, Престо! Работа выполнена. git merge <branch> теперь скопирует-объединить все, чтобы ветка, на которой вы находитесь, содержит точные копии всех файлов на <branch> . Что и требовалось доказать.

Если вы хотите выполнить не-копирование-слияние, просто reset драйвер слияния по умолчанию:

git config --unset merge.default

Если вы хотите быть более избирательным, оставьте merge.default отключенным и используйте атрибуты, поскольку @VonC говорит:

cd path/to/copy-merge/in
echo '* merge=copy-merge'  >  .gitattributes
echo '.* merge=copy-merge' >> .gitattributes

Сделайте это в верхней части каждого поддерева, с которым вы хотите скопировать-слияние. Если есть суб-поддерево, которое вы НЕ хотите копировать-объединить, вы можете отключить его снова:

cd path/to/copy-merge/in/path/to/normal-merge/in
echo '* merge'  >  .gitattributes
echo '.* merge' >> .gitattributes

ПРЕДУПРЕЖДЕНИЕ: засорение рабочего дерева большим количеством файлов .gitattributes неизбежно приведет к путанице, особенно если вы также используете в других каталогах такие вещи, как "*.bin -merge", чтобы сбой всех слияний .bin файлов с ошибкой конфликты. Возможно, лучше использовать $GIT_DIR/info/attributes для такого рода вещей, так как он имеет наивысший приоритет.

Ответ 2

В версии 1.7.1 из Git вы можете передать стратегию "их", чтобы объединиться с аргументом "-Xtheirs".

git merge -Xtheirs otherBranch

Не уверен, что это относится к тому, что вы пытаетесь сделать, но это, вероятно, стоит того.

(См. также этот связанный вопрос)

Ответ 3

На днях перейдем к этой проблеме:

http://seanius.net/blog/2011/02/git-merge-s-theirs/

git merge -s ours ref-to-be-merged
git diff --binary ref-to-be-merged | git apply -R --index
git commit -F .git/COMMIT_EDITMSG --amend

Ответ 4

(обновление 2011:
Ответ " git команда для создания одной ветки как другой" перечислены все возможные способы моделировать слияние git -s theirs)


Для конкретных файлов/деревьев, которые вы хотите скопировать-слияние, вы можете настроить значение gitattributes как тот, который я упоминаю в этом вопросе fooobar.com/questions/6108/..., определяя пользовательский драйвер слияния.
script, связанный с атрибутом merge, всегда будет сохранять удаленный файл в качестве результата слияния (см. Этот SO ответ для иллюстрации, хотя и для противоположного сценария - сохраняя локальную версию).

echo * merge=keepTheir > dirWithCopyMerge\.gitattributes
git config merge.keepTheir.name "always keep theirduring merge"
git config merge.keepTheir.driver "keepTheir.sh %O %A %B"

Установив атрибут .gitattribute поверх поддерева, который вы хотите скопировать, с '* merge=keepTheir' в качестве своего содержимого, вы фактически привязываете настраиваемый драйвер слияния ко всем файлам этого поддерева (обратите внимание на использование шаблона '*' здесь.)

С keepTheir.sh как:

mv -f $3 $2
exit 0

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

Ответ 5

После тонны исследований, пройдя весь шум SO и снова узнав о git (это когда-нибудь закончилось?), я считаю, что этот ответ является самым бесшумным и оптимальным способом достижения пользовательского --strategy theirs драйвер моделирования слияния. Полезно по требованию, не требуется gitattributes подстилка.

На самом деле у меня все еще немного головокружение относительно того, является ли это симулятором --strategy theirs или самым плавным использованием метода разрешения конфликтов checkout --theirs .. Возможно, они эквиваленты, но мне пришлось бы диагностировать несколько графиков результатов, чтобы полностью понять, что сейчас нет времени.

Подходит для @kbro, делая правильную вещь, преследуя мелкие детали и становясь совсем близко в fooobar.com/info/4326/...

[git:master] - отображение приглашения в командной строке.

НАСТРОЙКИ

$ [git:master] git config merge.theirs.name 'simulate `-s theirs`'
$ [git:master] git config merge.theirs.driver 'cat %B > %A' # same as `mv` or `cp`, matter of taste

USE

$ [git:master] GIT_CONFIG_PARAMETERS="'merge.default=theirs'" git merge develop

БОНУС: ALIAS

$ [git:master] git config alias.merge-theirs \!GIT_CONFIG_PARAMETERS=\""'"merge.default=theirs"'"\"\ git\ merge

ИСПОЛЬЗОВАНИЕ: ALIAS

$ [git:master] git merge-theirs develop

Обратите внимание на структуру кавычек GIT_CONFIG_PARAMETERS, потому что она должна иметь возможность принимать множество сложных значений. Получение этой командной строки BONUS приложило все усилия, чтобы понять.

PS GIT_CONFIG_PARAMETERS должен быть самым лучшим секретом в SO, мы почти закончили с 2016 года, https://stackoverflow.com/search?q=git_config_parameters имеет 1 (один) результат (1)