Git - как исключить файлы из слияния

Я пытаюсь сохранить 2 проекта веб-сайта в одном хранилище. Эти веб-сайты в основном такие же, кроме файлов шаблонов (html, css) и нескольких файлов конфигурации. Основной сайт (который, по моему мнению, Supersite) находится в главном сервере. Второй сайт находится в филиале secondarySite. Каждый раз, когда я разрабатываю новую функцию в основной ветке, я хочу объединить ее с secondarySite, но я хочу исключить слияние файлов шаблонов.

Я нашел частичное решение здесь Как сообщить git, чтобы всегда выбирать локальную версию для конфликтующих слияний в определенном файле?, но она работает только тогда, когда я меняю файл шаблона в обеих ветвях и возникает конфликт. Когда нет конфликта git просто используйте более новую удаленную версию файла.

Как я могу сообщить git всегда оставить указанные локальные файлы неизменными, даже если конфликт отсутствует.

Или, может быть, я использую совершенно неправильный подход к проблеме?

Заранее благодарим за помощь.

Ответ 1

Как упоминается в моем ответе о драйверах слияния, они полезны только в случае конфликта.
Это относится к merge=ours в файле .gitattributes: см. Стратегии объединения.

Один очень полезный вариант - сообщить Git не пытаться объединить определенные файлы , когда у них есть конфликты, а скорее использовать вашу сторону слияния над кем-то elses.

Этот недавний поток (2012) подтверждает это:

Есть ли способ слияния из branchA в branchB и от ветки B до   branchA, полностью игнорируя изменения в файле, который отслеживается   и существует в обеих ветвях?

Нет. По существу объект фиксации в Git состоит из состояния содержимого (то есть указателя на объект дерева) и указателя на всю предыдущую историю (то есть, ноль или более "родительские" указатели для совершения объектов).
Семантику объекта фиксации можно рассматривать как "Я просмотрел всю историю во всех родительских коммитах, а состояние, содержащееся в моем указателе на дерево, заменяет их всех".

Итак, вы можете сделать merge B в A, но сохраните A копию файла (например, используя стратегию "ours" ). Но это говорит о том, что вы считали состояние как A, так и B, и решили, что версия A заменяет то, что произошло в B. Если позже вы захотите объединиться с A на B, версия файла B даже не будет считаться результатом слияния.

Существует не очень умный способ обойти это с помощью другой стратегии слияния; это фундаментальный аспект структуры данных Git для хранения истории.

Если эти шаблоны находятся в подкаталоге, лучше выделить их в репозитории Git, чтобы включить это репо в качестве подмодуля.

Если нет, то вам необходимо вернуть файлы, которые были неправильно объединены перед фиксацией (как в этот поток):

git merge --no-commit other
git checkout HEAD XYZ  # or 'git rm XYZ' if XYZ does not exist on master
git commit 

Ответ 2

Пробовали ли вы использовать .gitignore? Подробности, доступные в документации git здесь

Ответ 3

Здесь git -update-index - записывать содержимое файла в рабочем дереве в индекс.

git update-index --assume-unchanged <PATH_OF_THE_FILE>

Пример: -

git update-index --assume-unchanged somelocation/pom.xml

или

Добавить пути к файлам в .gitignore

Ответ 4

Или, может быть, я использую совершенно неправильный подход к проблеме?

Вы используете совершенно неправильный подход к этой проблеме:)

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

Но ваши два веб-сайта на самом деле не являются одним и тем же основным, они - две разные вещи с некоторой общности, и вам приходится злоупотреблять git, потому что вы лжете ему об их отношениях.

Ваши разумные варианты:

  • сделайте свое репо представителем юниверса всех (нормально, обоих) сайтов. Таким образом, они оба видны в одной структуре каталогов и используют разные пути. У них могут быть отдельные ветки dev и release, но это необязательно. Если два сайта имеют некоторую общность, это может быть просто в виде общих файлов.

    например.

    repo/supersite
    repo/secondsite
    repo/common
    
  • сделать отдельное репо для каждого сайта и дублировать общие файлы. Вы можете просто скопировать изменения

  • сделать отдельное репо для каждого сайта и третье репо для обычных вещей и использовать подмодули для объединения суперсайта + общего в одном месте, а второй - с общим в другом.

    например.

    super-repo/site    # super site content
    super-repo/common  # common repo as submodule
    second-repo/site   # second site content
    second-repo/common # same common repo as submodule
    

    Обратите внимание, что подмодули относятся к одному и тому же репо, но каждый экземпляр может находиться в настоящее время на другой ветке или фиксировать

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

Ответ 5

В каждом из ваших ветвей добавьте файл .gitattributes в корневой каталог.

Для каждой ветки указаны файлы, которые следует игнорировать при слиянии следующим образом:

filename merge=ours

и не забудьте активировать драйвер для этого:

git config --global merge.ours.driver true

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