В отношении конкретного экземпляра файла конфигурации я согласен с ответом Рона :
Конфигурация должна быть «приватной» для вашей рабочей области (следовательно, «игнорируется», как в «объявленном в .gitignore
файле»).
У вас может быть файл конфигурации template с маркерными значениями в нем и сценарий, преобразующий этот config.template
файл в частный (и игнорируемый) файл конфигурации.
Однако это конкретное замечание не дает ответа на более общий вопрос, т. Е. На ваш вопрос (!):
Как мне сказать git всегда выбирать мою локальную версию для конфликтующих слияний в определенном файле? (для любого файла или группы файлов)
Этот вид слияния является «копированием слиянием», при котором вы всегда будете копировать «нашу» или «их» версию файла при возникновении конфликта.
(as Brian Vandenberg примечания в комментариях , 'ours
' и 'theirs
' здесь используются для слияния .
Они перевернуты для перебазирования : см. "Why is the meaning of “ours” and “theirs” reversed with git-svn
", в котором используется перебазировка "git rebase
, отслеживание 'local 'and' remote ' ")
Для "файла" (файла вообще, не говоря уже о файле "config", так как это плохой пример), вы бы достигли этого с помощью специального сценария, вызываемого слиянием.
Git вызовет этот скрипт, потому что у вас будет определено gitattributes value , которое определяет пользовательский драйвер слияния .
«Настраиваемый драйвер слияния» - это, в данном случае, очень простой скрипт, который в основном не изменяет текущую версию, что позволяет вам всегда выбирать вашу локальную версию.
Давайте проверим это в простом сценарии, с 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 и описал в разделе " Стратегии объединения " в Настройка Git - атрибутов Git , вы можете замените сценарий оболочки командой shell 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
Последний коммит представляет собой full merge:
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 через драйвер python git ".
Однако, как упоминалось в его другом вопросе , он работает только в случае конфликтов (одновременное изменение в обеих ветвях).