В отношении конкретного экземпляра файла конфигурации я согласен с ответом Рона :
конфигурация должна быть «частной» для вашей рабочей области (следовательно, «игнорироваться», как в «объявленной в .gitignore
файле»).
У вас может быть шаблон файла конфигурации с токенизированными значениями в нем и сценарий, преобразующий этот config.template
файл в частный (и игнорируемый) файл конфигурации.
Однако это конкретное замечание не отвечает на более широкий вопрос, то есть на ваш вопрос (!):
Как мне сообщить git, чтобы он всегда выбирал мою локальную версию для конфликтующих слияний в определенном файле? (для любого файла или группы файлов)
Этот вид слияния представляет собой «копирование слияния», при котором вы всегда будете копировать «нашу» или «их» версию файла всякий раз, когда возникает конфликт.
(как отмечает Брайан Ванденберг в комментариях , ' ours
' и ' theirs
' здесь используются для слияния .
Они меняются местами для перебазирования : см. " Why is the meaning of “ours” and “theirs” reversed with git-svn
", который использует перебазирование, " git rebase
отслеживая" локальные "и" удаленные " " )
Для «файла» (файла в целом, не говоря уже о файле «конфигурации», поскольку это плохой пример), вы можете добиться этого с помощью специального сценария, вызываемого посредством слияния.
Git вызовет этот скрипт, потому что вы определите значение gitattributes , которое определяет настраиваемый драйвер слияния .
«Пользовательский драйвер слияния» в данном случае представляет собой очень простой скрипт, который в основном сохраняет неизменной текущую версию, что позволяет вам всегда выбирать локальную версию.
. IE, Как отмечено на Ciro Сантилли :
echo 'path/to/file merge=ours' >> .gitattributes
git config --global merge.ours.driver true
Давайте проверим это на простом сценарии с msysgit 1.6.3 в Windows, в простом сеансе DOS:
cd f:\prog\git\test
mkdir copyMerge\dirWithConflicts
mkdir copyMerge\dirWithCopyMerge
cd copyMerge
git init
Initialized empty Git repository in F:/prog/git/test/copyMerge/.git/
Теперь давайте создадим два файла, у которых будут конфликты, но которые будут объединяться по-разному.
echo a > dirWithConflicts\a.txt
echo b > dirWithCopyMerge\b.txt
git add -A
git commit -m "first commit with 2 directories and 2 files"
[master (root-commit) 0adaf8e] first commit with 2 directories and 2 files
Мы введем «конфликт» в содержимое обоих этих файлов в двух разных ветках git:
git checkout -b myBranch
Switched to a new branch 'myBranch'
echo myLineForA >> dirWithConflicts\a.txt
echo myLineForB >> dirWithCopyMerge\b.txt
git add -A
git commit -m "add modification in myBranch"
[myBranch 97eac61] add modification in myBranch
git checkout master
Switched to branch 'master'
git checkout -b hisBranch
Switched to a new branch 'hisBranch'
echo hisLineForA >> dirWithConflicts\a.txt
echo hisLineForB >> dirWithCopyMerge\b.txt
git add -A
git commit -m "add modification in hisBranch"
[hisBranch 658c31c] add modification in hisBranch
Теперь давайте попробуем объединить hisBranch с myBranch с:
- ручное разрешение конфликтующих слияний
- за исключением того, на
dirWithCopyMerge\b.txt
котором я всегда хочу , чтобы сохранить свою версию b.txt
.
Поскольку слияние происходит в ' MyBranch
', мы вернемся к нему и добавим gitattributes
директивы ' ', которые будут настраивать поведение слияния.
git checkout myBranch
Switched to branch 'myBranch'
echo b.txt merge=keepMine > dirWithCopyMerge\.gitattributes
git config merge.keepMine.name "always keep mine during merge"
git config merge.keepMine.driver "keepMine.sh %O %A %B"
git add -A
git commit -m "prepare myBranch with .gitattributes merge strategy"
[myBranch ec202aa] prepare myBranch with .gitattributes merge strategy
У нас есть .gitattributes
файл, определенный в dirWithCopyMerge
каталоге (определенный только в ветке, где будет происходить слияние :) myBranch
, и у нас есть .git\config
файл, который теперь содержит драйвер слияния.
[merge "keepMine"]
name = always keep mine during merge
driver = keepMine.sh %O %A %B
Если вы еще не определили keepMine.sh и все равно запускаете слияние, вот что вы получите.
git merge hisBranch
sh: keepMine.sh: command not found
fatal: Failed to execute internal merge
git st
# On branch myBranch
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: dirWithConflicts/a.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
type dirWithConflicts\a.txt
a
<<<<<<< HEAD:dirWithConflicts/a.txt
myLineForA
=======
hisLineForA
>>>>>>> hisBranch:dirWithConflicts/a.txt
Это нормально:
a.txt
готов к слиянию и в нем есть конфликт
b.txt
остается нетронутым, поскольку предполагается, что драйвер слияния позаботится об этом (из-за директивы в .gitattributes
файле в его каталоге).
Определите keepMine.sh
где угодно в вашем %PATH%
(или $PATH
для нашего друга Unix. Я, конечно, делаю и то, и другое: у меня есть сеанс Ubuntu в сеансе VirtualBox)
Как отметил по lrkwz , и описано в разделе « Объединить Strategies разделе» из пользовательской настройки Git - Атрибуты Git , вы можете заменить скрипт с командой оболочки true
.
git config merge.keepMine.driver true
Но в общем случае вы можете определить файл сценария:
keepMine.sh
# I want to keep MY version when there is a conflict
# Nothing to do: %A (the second parameter) already contains my version
# Just indicate the merge has been successfully "resolved" with the exit status
exit 0
(это был один простой драйвер слияния;) (даже проще в этом случае, использование true
)
(Если вы хотите сохранить другую версию, просто добавьте перед exit 0
строкой:
cp -f $3 $2
.
Вот и вы сливаться водитель будет Визитки держать версию приходя от другого. ветвь, отменяя любое локальное изменение)
Теперь давайте повторим слияние с самого начала:
git reset --hard
HEAD is now at ec202aa prepare myBranch with .gitattributes merge strategy
git merge hisBranch
Auto-merging dirWithConflicts/a.txt
CONFLICT (content): Merge conflict in dirWithConflicts/a.txt
Auto-merging dirWithCopyMerge/b.txt
Automatic merge failed; fix conflicts and then commit the result.
Слияние не удается ... только для a.txt .
Отредактируйте a.txt и оставьте строку из hisBranch, затем:
git add -A
git commit -m "resolve a.txt by accepting hisBranch version"
[myBranch 77bc81f] resolve a.txt by accepting hisBranch version
Давайте проверим, что b.txt был сохранен во время этого слияния
type dirWithCopyMerge\b.txt
b
myLineForB
Последний коммит действительно представляет собой полное слияние:
git show -v 77bc81f5e
commit 77bc81f5ed585f90fc1ca5e2e1ddef24a6913a1d
Merge: ec202aa 658c31c
git merge hisBranch
Already up-to-date.
(Строка, начинающаяся с Merge, действительно доказывает это)
Считайте, что вы можете определить, объединить и / или перезаписать драйвер слияния, поскольку Git будет:
- исследуйте
<dir>/.gitattributes
(который находится в том же каталоге, что и рассматриваемый путь): будет преобладать над другим .gitattributes
в каталогах
- Затем он проверяет
.gitattributes
(который находится в родительском каталоге), устанавливает только директивы, если они еще не установлены
- Наконец он исследует
$GIT_DIR/info/attributes
. Этот файл используется для переопределения настроек в дереве. Это перезапишет <dir>/.gitattributes
директивы.
Под «объединением» я подразумеваю «объединение» нескольких драйверов слияния.
Ник Грин пытается в комментариях фактически объединить драйверы слияния: см. « Слияние pom через драйвер git python ».
Однако, как упоминалось в его другом вопросе , он работает только в случае конфликтов (одновременное изменение в обеих ветвях).