Sur l'instance spécifique d'un fichier de configuration, je serais d'accord avec la réponse de Ron :
une configuration devrait être "privée" pour votre espace de travail (donc "ignorée", comme dans "déclarée dans un .gitignore
fichier").
Vous pouvez avoir un modèle de fichier de configuration avec des valeurs symbolisées et un script transformant ce config.template
fichier en un fichier de configuration privé (et ignoré).
Cependant, cette remarque spécifique ne répond pas à ce qui est une question plus large, plus générale, à savoir votre question (!):
Comment dire à git de toujours sélectionner ma version locale pour les fusions en conflit sur un fichier spécifique? (pour tout fichier ou groupe de fichiers)
Ce type de fusion est une «fusion par copie», dans laquelle vous copiez toujours la version «nôtre» ou «la leur» d'un fichier chaque fois qu'il y a un conflit.
(comme Brian Vandenberg le note dans les commentaires , « ours
» et « theirs
» sont ici utilisés pour une fusion .
Ils sont inversés pour un rebase : voir " Why is the meaning of “ours” and “theirs” reversed with git-svn
", qui utilise un rebase, " git rebase
, en gardant une trace de" local "et" distant " " )
Pour "un fichier" (un fichier en général, sans parler d'un fichier "config", car c'est un mauvais exemple), vous y parviendrez avec un script personnalisé appelé par fusion.
Git appellera ce script car vous aurez défini une valeur gitattributes , qui définit un pilote de fusion personnalisé .
Le "pilote de fusion personnalisé" est, dans ce cas, un script très simple qui gardera fondamentalement inchangé la version actuelle, vous permettant ainsi de toujours sélectionner votre version locale.
IE., Comme indiqué par Ciro Santilli :
echo 'path/to/file merge=ours' >> .gitattributes
git config --global merge.ours.driver true
Testons cela dans un scénario simple, avec un msysgit 1.6.3 sous Windows, dans une simple session 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/
Maintenant, créons deux fichiers, qui auront tous deux des conflits, mais qui seront fusionnés différemment.
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
Nous allons introduire un "conflit" dans le contenu de ces deux fichiers dans deux branches git différentes:
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
Maintenant, essayons de fusionner "hisBranch" sur "myBranch", avec:
- résolution manuelle des fusions conflictuelles
- excepter pour
dirWithCopyMerge\b.txt
où je veux toujours garder ma version b.txt
.
Puisque la fusion se produit dans « MyBranch
», nous y retournerons et ajouterons les gitattributes
directives « » qui personnaliseront le comportement de fusion.
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
Nous avons un .gitattributes
fichier défini dans le dirWithCopyMerge
répertoire (défini uniquement dans la branche où la fusion aura lieu :) myBranch
, et nous avons un .git\config
fichier qui contient maintenant un pilote de fusion.
[merge "keepMine"]
name = always keep mine during merge
driver = keepMine.sh %O %A %B
Si vous ne définissez pas encore keepMine.sh et que vous lancez quand même la fusion, voici ce que vous obtenez.
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
C'est bon:
a.txt
est prêt à être fusionné et a un conflit
b.txt
est toujours inchangé, puisque le pilote de fusion est censé s'en occuper (en raison de la directive dans le .gitattributes
fichier dans son répertoire).
Définissez un keepMine.sh
n'importe où dans votre %PATH%
(ou $PATH
pour notre ami Unix. Je fais les deux bien sûr: j'ai une session Ubuntu dans une session VirtualBox)
Comme commenté par lrkwz et décrit dans la section « Stratégies de fusion » de Personnalisation des attributs Git - Git , vous pouvez remplacer le script shell par la commande shell true
.
git config merge.keepMine.driver true
Mais dans le cas général, vous pouvez définir un fichier 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
(qui était un conducteur simple de fusion;) (encore plus simple dans ce cas, l' utilisation true
)
(Si vous voulez garder l'autre version, il suffit d' ajouter avant la exit 0
ligne:
cp -f $3 $2
.
Ca y est vous fusionnez pilote serait aways garder la version à venir de l'autre. branche, annulant tout changement local)
Maintenant, réessayons la fusion depuis le début:
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.
La fusion échoue ... uniquement pour a.txt .
Editez a.txt et laissez la ligne de 'hisBranch', puis:
git add -A
git commit -m "resolve a.txt by accepting hisBranch version"
[myBranch 77bc81f] resolve a.txt by accepting hisBranch version
Vérifions que b.txt a été conservé lors de cette fusion
type dirWithCopyMerge\b.txt
b
myLineForB
Le dernier commit représente la fusion complète :
git show -v 77bc81f5e
commit 77bc81f5ed585f90fc1ca5e2e1ddef24a6913a1d
Merge: ec202aa 658c31c
git merge hisBranch
Already up-to-date.
(La ligne commençant par Merge le prouve)
Considérez que vous pouvez définir, combiner et / ou écraser le pilote de fusion, comme Git le fera:
- examine
<dir>/.gitattributes
(qui est dans le même répertoire que le chemin en question): prévaudra sur l'autre.gitattributes
dans les répertoires
- Ensuite, il examine
.gitattributes
(qui se trouve dans le répertoire parent), ne définira des directives que s'il n'est pas déjà défini
- Enfin, il examine
$GIT_DIR/info/attributes
. Ce fichier est utilisé pour remplacer les paramètres de l'arborescence. Cela écrasera les <dir>/.gitattributes
directives.
Par «combinaison», je veux dire «agréger» plusieurs pilotes de fusion.
Nick Green essaie, dans les commentaires , de combiner réellement les pilotes de fusion: voir " Fusionner les pom via le pilote python git ".
Cependant, comme mentionné dans son autre question , cela ne fonctionne qu'en cas de conflits (modification simultanée dans les deux branches).