"git merge -ssis" нужен - но я знаю, что его не существует
У меня есть несколько удаленных репозиториев, которые я хочу объединить. Некоторые из поддеревьев в этих репозиториях являются уникальными для удаленного узла (они содержат данные, относящиеся к конкретному хосту), другие поддеревья содержат данные, которые (должны быть) общими для всех удаленных устройств.
По сути, я хочу запустить git pull для каждого пульта. Это приведет к быстрой перемотке вперед локальной ветви мастера вдоль ветви отслеживания для удаленного мастера для файлов, специфичных для хоста, которые изменились на удаленном компьютере, и ничего не изменит для общих файлов, поскольку они не изменились.
Изменение в общем файле (назовите его F, с изменением F') не должно быть проблемой, даже если это происходит сначала только на одном пульте. git-merge сделает все правильно и даст мне копию F 'в моем составном рабочем пространстве, что я и хочу. Проблема возникает, если тот же самый общий файл изменяется другим способом на другом пульте (назовите его F"). Git-merge даст мне смесь F 'и F", а это не то, что я хочу. Все, что я хочу, это F".
Когда я работал с ClearCase, мы называли это копированием-слиянием. Результатом слияния всегда была точная копия участника. Это звучит очень похоже на "git merge -s их", за исключением того, что он не существует.
Я задаюсь вопросом, могу ли я что-то приготовить с помощью "git-read-tree -m --trivial", чтобы убрать ускоренные слияния, а затем поработать с git-merge и пользовательским mergetool, который просто копирует $ УДАЛЕННЫЙ файл в $MERGED. Но даже при этом я не вижу, как я могу остановить git-merge от объединения F 'и F ", если слияние тривиально.
Я прочитал ссылку. Есть ли "их" версия "git merge -s ours"? на этом сайте, а также на пост Джунио Хамано, в котором есть ссылки, объясняющие, почему "git merge -s их" такая плохая идея, но это не так для меня. Я действительно ценю старую историю, но мне нужно соскочить с корабля и следить за изменениями на удаленном сайте, когда это произойдет. На местном сайте не ведется никакой новой работы. Он просто должен сформировать совокупность всех удаленных сайтов, взяв последний "общий" файл из последнего опрошенного удаленного, когда он изменяется.
Заранее благодарим за любую помощь, которую вы можете оказать мне.
5 ответов
Большое спасибо @VonC за предложение использовать атрибут merge=custom-driver в файле .gitattributes. Хотя это будет работать, я неохотно загрязняю свое рабочее пространство файлами.git, и хотя я могу использовать атрибуты $GIT_DIR/info/, чтобы избежать загрязнения, меня беспокоит необходимость двух правил для отлова файлов точек и файлы без точек.
После нескольких экспериментов мне удалось найти решение с работающей переменной конфигурации 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/ для такого рода вещей, поскольку они имеют наивысший приоритет.
Столкнулся с этой проблемой на днях:
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
В версии 1.7.1 Git вы можете передать стратегию "их" для слияния и аргумент "-Xtheirs".
git merge -Xtheirs otherBranch
Не уверен, относится ли это к тому, что вы пытаетесь сделать, но, вероятно, стоит попробовать.
(Смотрите также этот связанный вопрос)
(обновление 2011 года:
В ответе " команда git для создания одной ветви как другой " перечислены все возможные способы симуляции git merge -s их`)
Для конкретных файлов / деревьев, которые вы хотите скопировать-объединить, вы можете установить значение атрибутов 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 как:
mv -f $3 $2
exit 0
вам не нужно изменять какой-либо драйвер слияния "по умолчанию", и вы применяете свой собственный только к нужным файлам.
После тонны исследований, пройдя через весь шум SO, и узнав больше о git
опять же (это когда-нибудь заканчивается?), я считаю, что этот ответ является наиболее бесшумным и оптимальным способом достижения --strategy theirs
драйвер слияния симуляции. Используется по запросу, нет gitattributes
мусорить надо.
Я на самом деле все еще немного головокружение от того, является ли это --strategy theirs
симуляция, или самый гладкий в использовании checkout --theirs .
метод разрешения конфликтов. Может быть, они эквиваленты, но мне нужно было бы диагностировать несколько графиков результатов, чтобы полностью понять, что сейчас не время.
Проповедь к тому, что @kbro делает правильные вещи, гоняясь за мелкими деталями и подходя довольно близко к /questions/41526015/git-merge-ssis-nuzhen-no-ya-znayu-chto-ego-ne-suschestvuet/41526040#41526040
[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
ИСПОЛЬЗОВАНИЕ
$ [git:master] GIT_CONFIG_PARAMETERS="'merge.default=theirs'" git merge develop
БОНУС: АЛИАС
$ [git:master] git config alias.merge-theirs \!GIT_CONFIG_PARAMETERS=\""'"merge.default=theirs"'"\"\ git\ merge
ИСПОЛЬЗОВАНИЕ: АЛИАС
$ [git:master] git merge-theirs develop
Обратите внимание на структуру цитат GIT_CONFIG_PARAMETERS
потому что он должен иметь возможность принимать несколько сложных значений. Чтобы получить эту БОНУСНУЮ командную строку, нужно было разобраться.
PS GIT_CONFIG_PARAMETERS
должен быть самым надежным секретом для SO, мы почти закончили с 2016 годом, https://stackru.com/search?q=git_config_parameters имеет 1 (один) результат ( 1)