Git - игнорировать файлы во время слияния

115

У меня есть репо myrepoна удаленном beanstalkсервере.

Я клонировал его на свою локальную машину. Создал две дополнительные ветки: stagingи dev. Эти ветки тоже были перенесены на удаленные.

Сейчас:

 local                   remote                   server
 --------------------------------------------------------  
 master  ==> Pushes to  `master`  ==> deployed to `prod`
 staging ==> Pushes to  `staging` ==> deployed to `staging`
 dev     ==> Pushes to  `dev`     ==> deployed to `dev`

У меня есть файл с именем, config.xmlкоторый отличается в каждой ветке.

Я хочу игнорировать этот файл только во время слияния. Но я хочу, чтобы это было включено, когда я оформляю заказ или фиксирую из / в ветку репо.

Причина, по которой я этого хочу, заключается в том, что у нас есть сценарий развертывания, который извлекает (проверяет) конкретную ветку и развертывает ее на соответствующих серверах. Поэтому нам нужно, чтобы config.xmlфайл этой конкретной ветки при развертывании перешел на конкретный сервер, как указано выше.

Я думаю, не .gitignoreсработает. Какие еще варианты? Обратите внимание, что игнорируемый файл должен быть частью проверки и фиксации, что важно. его следует игнорировать только во время слияния.

Спасибо!

Кевин Рэйв
источник
В режиме по умолчанию git pull является сокращением для git fetch, за которым следует git merge FETCH_HEAD. Таким образом, ваши заявления как бы противоречат друг другу.
zzk 05
Ну, я бы сказал, его касса. Не тянуть. Я обновлю вопрос, чтобы было понятно.
Кевин Рэйв
2
Вы когда-нибудь находили решение этой проблемы? Атрибуты git полезны только в случае, когда файл имеет конфликты между объединяемыми ветвями, поэтому этого не всегда достаточно.
pvinis
вы искали символические (без git) или даже жесткие ссылки на помощь?
Фрэнк

Ответы:

94

Я решил эту проблему, используя команду git merge с --no-commitопцией, а затем явно удалил подготовленный файл и проигнорировал изменения в файле. Например: скажем, я хочу игнорировать любые изменения, myfile.txtя действую следующим образом:

git merge --no-ff --no-commit <merge-branch>
git reset HEAD myfile.txt
git checkout -- myfile.txt
git commit -m "merged <merge-branch>"

Вы можете поместить операторы 2 и 3 в цикл for, если у вас есть список файлов, которые нужно пропустить.

unmesh-гуджар
источник
2
Я бы добавил "--no-ff", если вы хотите, чтобы файл не перезаписывался, когда слияние происходит в стратегии быстрой перемотки вперед.
Илья Шакитко
1
так что git reset HEAD myfile.txtименно? Как это помогает в достижении нашей цели?
Kid_Learning_C
Как поместить строки 2 и 3 в цикл?
AndroidDev
52

В итоге я нашел мерзавца attributes. Пробуем. Пока работает. Еще не проверял все сценарии. Но это должно быть решение.

Стратегии слияния - атрибуты Git

Кевин Рэйв
источник
4
но я нашел это git-scm.com/book/ch7-2.html#Merge-Strategies
Nate
1
Вот правильная ссылка на раздел стратегий слияния в документации по атрибутам git: git-scm.com/book/en/v2/…
Адриан
3
Нашел это хорошо объяснено в статье medium.com/@porteneuve/…
ShawnFeatherly
10
Вроде проблема, если конфликтов нет? Файлы все равно будут объединяться?
Brett
18

.gitattributes - это файл корневого уровня вашего репозитория, который определяет атрибуты для подкаталога или подмножества файлов.

Вы можете указать атрибут, чтобы указать Git использовать разные стратегии слияния для определенного файла. Здесь мы хотим сохранить существующее config.xmlдля нашей ветки. Нам нужно установить , merge=oursчтобы config.xmlв .gitattributesфайле.

merge=ours скажите git использовать наш файл (текущей ветки), если возникнет конфликт слияния.

  1. Добавить .gitattributesфайл на корневой уровень репозитория

  2. Вы можете настроить атрибут для confix.xml в .gitattributesфайле

    config.xml merge=ours
    
  3. А затем определите фиктивную нашу стратегию слияния с помощью:

    $ git config --global merge.ours.driver true
    

Если вы объединяете ветвь stagформы dev, вместо конфликта слияния с файлом config.xml, config.xml ветки stag сохранится в той версии, которая у вас была изначально.

eigenharsha
источник
16
Но что делать, если конфликта нет? Как всегда сохранить определенный файл при слиянии?
Игорь Яловой
2
@IgorYalovoy: Если нет конфликта ... ну, это немного сложно, поскольку на самом деле он работает с хеш-идентификаторами, но: если config.xmlон полностью не изменился от базы слияния до любой версии подсказки ветки, Git просто берет измененную версию, без глядя на merge.ours.driverнастройку. Так что вы правы, что беспокоитесь.
torek
1
копипаст из Git Docs: стратегии слияния - атрибуты Git. Ссылка
kyb 07
Этот метод приводит к «коммитам слияния» каждый раз, когда FYI.
rsmets
2
«наш», похоже, произвольное название для вводимой новой стратегии. Меня это сбивает с толку, потому что theirsэто встроенная стратегия слияния. Но мне кажется , что можно писать <pattern> merge=foo, а затем git config --global merge.foo.driver true, и он будет работать точно так же.
Кайл Стрэнд
8

Вы можете начать с использования git merge --no-commit, а затем отредактировать слияние, как вам нравится, например, отключив установку config.xmlили любой другой файл, а затем зафиксировать. Я подозреваю, что после этого вы захотите автоматизировать это дальше, используя хуки, но я думаю, что стоит хотя бы раз пройти вручную.

gcbenison
источник
2
Есть ли git attributesпредложить какие - либо прямые решения? Я не могу этого понять. git-scm.com/book/en/…
Кевин Рэйв
4

Вы можете использовать, .gitignoreчтобы не допустить config.xmlпопадания в репозиторий, а затем использовать обработчик post commit, чтобы загрузить соответствующий config.xmlфайл на сервер.

tlehman
источник
1
Я знаю, что это своего рода хакерство. Я пытаюсь найти чистое решение. Что насчет git attributes. Есть идеи, как это работает? Я не могу этого понять. git-scm.com/book/en/…
Кевин Рэйв
1
Я не слышал об этом, я пытаюсь применить атрибут merge = ours, выглядит многообещающе.
tlehman 05
1
Атрибуты Git потрясающие! Вы даже можете указать git, как различать нетекстовые файлы, чтобы вы могли использовать pdf2text для сравнения PDF-файлов!
tlehman 05
2

Пример:

  1. У вас есть две ветви: master,develop
  2. Вы создали файл в developветке и хотите игнорировать его при слиянии

Код:

git config --global merge.ours.driver true
git checkout master
echo "path/file_to_ignore merge=ours" >> .gitattributes
git merge develop

Вы также можете игнорировать файлы с таким же расширением

например все файлы с .txtрасширением:

echo "*.txt merge=ours" >> .gitattributes
Единственный сенсей
источник
1

Здесь git-update-index - Зарегистрируйте содержимое файла в рабочем дереве в index.

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

Пример:-

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

Сириш Ярлагадда
источник
Это приятно при нажатии, но все равно жалуется, что при вытягивании файл может быть перезаписан.
Рольф
1
Вы пытались добавить запись файла в файл .gitignore. @Rolf
Sireesh Yarlagadda