«git merge -ssis» нужен - но я знаю, что его не существует - PullRequest
12 голосов
/ 16 декабря 2009

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

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

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

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

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

Я прочитал ссылку Существует ли "их" версия "git merge -s ours"? на этом сайте, и на пост Джунио Хамано, в котором упоминается, почему "git merge -s" их "такая плохая идея, но это не так для меня. Я действительно ценю старую историю, но мне нужно соскочить с корабля и следить за изменениями на удаленном сайте, когда это произойдет. На этом сайте не ведется никакой новой работы. Он просто должен сформировать совокупность всех удаленных сайтов, взяв последний «общий» файл из последнего опрошенного удаленного, когда он изменяется.

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

Ответы [ 5 ]

8 голосов
/ 16 декабря 2009

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

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

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

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 теперь будет копировать-объединять все, поэтому в вашей ветке содержатся точные копии всех файлов на . Что и требовалось доказать.

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

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 / attribute для такого рода вещей, поскольку он имеет наивысший приоритет.

3 голосов
/ 06 марта 2011

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

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
2 голосов
/ 29 июля 2010

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

git merge -Xtheirs otherBranch

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

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

2 голосов
/ 16 декабря 2009

(обновление 2011 года:
В ответе " команда git для создания одной ветви как другой " перечислены все возможные способы имитации git merge -s их`` ) * +1010 *


Для конкретных файлов / деревьев, которые вы хотите скопировать-объединить, вы можете установить значение gitattributes , подобное тому, которое я упоминал в этом SO вопросе, определяя пользовательский драйвер слияния.
Сценарий, связанный с атрибутом слияния, обеспечит постоянное сохранение удаленного файла в качестве результата слияния (см. Этот 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 as:

mv -f $3 $2
exit 0

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

0 голосов
/ 13 сентября 2016

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

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

Поддерживает @kbro, делая правильные вещи, гоняясь за мелкими деталями и приближаясь к https://stackoverflow.com/a/1911370/35946

[git:master] - отображение подсказки оболочки.

SETUP

$ [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, потому что она должна иметь возможность принимать несколько комплексных значений. Чтобы получить эту БОНУСНУЮ командную строку, нужно было разобраться.

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

...