116 votes

Comment dois-je dire à git de toujours choisir ma version locale de conflit fusionne sur un fichier en particulier?

Dire que je suis de collaborer avec quelqu'un via un dépôt git, et il y a un fichier que je ne veux plus jamais accepter toute modification externe.

Est-il possible pour moi de créer mon local repo de ne pas se plaindre d'un conflit de fusion à chaque fois que je la commande git pull? J'aimerais toujours choisir ma version locale lors de la fusion de ce fichier.

152voto

VonC Points 414372

Sur l'instance spécifique d'un fichier de config, je suis d'accord avec Ron réponse:
une config doit être "privé" à votre espace de travail (d'où "ignoré", comme dans ", a déclaré dans un .gitignore le fichier").
Vous pouvez avoir un fichier de config modèle avec segmentées en valeurs , et un script de transformation qu' config.template le fichier en privé (et ignoré) fichier de configuration.


Cependant, la remarque ne répond pas à ce qui est une question plus générale, c'est à dire votre question(!):

Comment dois-je dire à git de toujours choisir ma version locale de conflit fusionne sur un fichier en particulier ? (pour n'importe quel fichier ou groupe de fichiers)

Ce type de fusion est une "copie de fusion", dans lequel vous aurez toujours copier "nôtre" ou "leur" version d'un fichier chaque fois qu'il y a un conflit.

(comme Brian Vandenberg notes dans les commentaires, 'ours"et"theirs"sont ici utilisés pour une fusion.
Ils sont inversées pour un rebase: voir "Why is the meaning of "ours" and "theirs" reversed with git-svn", qui utilise un rebase, "git rebase, suivi de "local" et "distant"")

Pour "un fichier (un fichier en général, il ne parle pas de "config" du fichier, car il est un mauvais exemple), vous permettrait d'atteindre cet objectif avec un script personnalisé appelé par le biais de fusions.
Git vais appeler ce script parce que vous aurez à définir un gitattributes valeur, qui définit une coutume de fusion pilote.

La "coutume de fusion pilote" est, dans ce cas, un script très simple qui, en gros, va conserver la version actuelle, donc vous permettant de toujours sélectionner votre version locale.


Nous allons tester que dans un scénario simple, avec un msysgit 1.6.3 sur Windows, dans un simple DOS de la session:

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, nous allons faire deux fichiers, ce qui permettra à la fois d'avoir des conflits, mais qui vont être regroupées 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 mettrons en place un "conflit" dans le contenu de ces deux fichiers dans deux différentes branches 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

Maintenant, nous allons essayer de fusionner "hisBranch" sur "myBranch", avec:

  • manuel de résolution de conflits fusionne
  • sauf pour dirWithCopyMerge\b.txt où j'ai toujours envie de garder ma version de b.txt.

Depuis la fusion se produit dans 'MyBranch', nous allons y revenir, et d'ajouter le 'gitattributes"directives qui permettra de personnaliser 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 l' dirWithCopyMerge répertoire (définie uniquement dans la direction où la fusion sera effectuée: myBranch), et nous avons un .git\config le fichier qui contient maintenant une fusion pilote.

[merge "keepMine"]
        name = always keep mine during merge
        driver = keepMine.sh %O %A %B

Si vous n'avez pas encore définir keepMine.sh et pour lancer la fusion de toute façon, ici est 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 très bien:

  • a.txt est prêt à être fusionné et a conflit, il
  • b.txt est encore intacte, depuis la fusion pilote est censé prendre soin d'elle (en raison de la directive dans l' .gitattributes fichier dans son répertoire).

Définir un keepMine.sh n'importe où dans votre %PATH% (ou $PATH de notre Unix ami. Je fais les deux, bien sûr: j'ai une session Ubuntu dans VirtualBox session)

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

(c'était une simple opération de fusion pilote ;) )
(Si vous voulez garder l'autre version, il suffit d'ajouter avant la exit 0 ligne:
cp -f $3 $2.
C'est tout. La fusion conducteur souvenirs conservez la version à venir de l'autre branche, en remplaçant toute modification locale)

Maintenant, nous allons réessayer de le fusionner à partir du 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... seulement pour a.txt.
Modifier a.txt et de laisser 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

Nous allons vérifier que b.txt a été préservée au cours de cette fusion

type dirWithCopyMerge\b.txt
b
myLineForB

Le dernier commit représentent le plein de fusion:

git show -v 77bc81f5e
commit 77bc81f5ed585f90fc1ca5e2e1ddef24a6913a1d
Merge: ec202aa 658c31c
git merge hisBranch
Already up-to-date.

(Le début de ligne avec de Fusion ne se révéler qu')


Considérez que vous pouvez définir, de combiner et/ou remplacer fusion pilote, comme Git:

  • examiner <dir>/.gitattributes (qui est dans le même répertoire que le chemin en question): prévaudra sur les autres .gitattributes dans les annuaires
  • Puis il examine .gitattributes (qui est dans le répertoire parent), ne les directives si ce n'est déjà fait
  • Enfin, il examine $GIT_DIR/info/attributes. Ce fichier est utilisé pour remplacer les paramètres de l'arborescence. Il remplacera <dir>/.gitattributes directives.

.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X