Ответ 1
В конкретном экземпляре конфигурационного файла я согласен с ответом Рона:
config должен быть "private" для вашей рабочей области (следовательно, "проигнорирован", как в "объявленном в файле .gitignore
" ).
У вас может быть шаблон конфигурационного файла с токенированными значениями в нем и script, преобразующий этот файл config.template
в закрытый (и проигнорированный) файл конфигурации.
Однако это конкретное замечание не отвечает на то, что является более общим более общим вопросом, т.е. ваш вопрос (!):
Как сообщить git всегда выбирать локальную версию для конфликтующих слияний в определенном файле? (для любого файла или группы файлов)
Этот вид слияния представляет собой "копирование слияния", в котором вы всегда будете копировать "нашу" или "свою" версию файла всякий раз, когда есть конфликт.
(как Брайан Ванденберг отмечает в комментариях, '
ours
' и 'theirs
'здесь используются для слияния.
Они перевернуты для rebase: см. "Why is the meaning of "ours" and "theirs" reversed with git-svn
", в котором используется rebase,git rebase
, отслеживая "local" и 'remote' ")
Для "файла" (файла вообще, не говоря о файле "config", поскольку это плохой пример), вы бы достигли этого с помощью пользовательского script, вызванного слияниями.
Git будет называть это script, потому что вы определите gitattributes значение, которое определяет пользовательский драйвер слияния.
"Пользовательский драйвер слияния" в этом случае представляет собой очень простой script, который в основном будет сохранять неизменную текущую версию, следовательно, позволяя вам всегда выбирать локальную версию.
Позвольте проверить, что в простом сценарии, с 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 и описан в Merge Strategies " Настройка git - git Атрибуты, вы можете замените оболочку script командой оболочки true
.
git config merge.keepMine.driver true
Но в общем случае вы можете определить файл script:
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
.
Под "объединением" я имею в виду "совокупный" множественный драйвер слияния.
Nick Green пытается, в комментариях, чтобы фактически объединить драйверы слияния: см. " Объединить pom через драйвер python git.
Однако, как упоминалось в его другом вопросе, он работает только в случае конфликтов (одновременная модификация в обеих ветвях).