Nell'istanza specifica di un file di configurazione, sarei d'accordo con la risposta di Ron :
una configurazione dovrebbe essere "privata" per il tuo spazio di lavoro (quindi "ignorata", come in "dichiarata in un .gitignore
file").
Potresti avere un modello di file di configurazione con valori tokenizzati e uno script che trasforma quel config.template
file in un file di configurazione privato (e ignorato).
Tuttavia, quella specifica osservazione non risponde a quella che è una domanda più ampia e generale, ovvero la tua domanda (!):
Come faccio a dire a git di selezionare sempre la mia versione locale per unioni in conflitto su un file specifico? (per qualsiasi file o gruppo di file)
Questo tipo di unione è una "unione di copie", in cui copierai sempre la versione "nostra" o "loro" di un file ogni volta che si verifica un conflitto.
(come nota Brian Vandenberg nei commenti , " ours
" e " theirs
" sono qui usati per un merge .
Sono invertiti per un rebase : vedi " Why is the meaning of “ours” and “theirs” reversed with git-svn
", che usa un rebase, " git rebase
, tenendo traccia di 'local' e 'remote' " )
Per "un file" (un file in generale, non parlando di un file "config", poiché è un cattivo esempio), lo otterresti con uno script personalizzato chiamato tramite unioni.
Git chiamerà quello script perché dovrai definire un valore gitattributes , che definisce un driver di unione personalizzato .
Il "custom merge driver" è, in questo caso, uno script molto semplice che sostanzialmente manterrà invariata la versione corrente, permettendoti quindi di selezionare sempre la tua versione locale.
IE., Come notato da Ciro Santilli :
echo 'path/to/file merge=ours' >> .gitattributes
git config --global merge.ours.driver true
Proviamolo in uno scenario semplice, con un msysgit 1.6.3 su Windows, in una semplice sessione 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/
Ora, creiamo due file, che avranno entrambi conflitti, ma che verranno uniti in modo diverso.
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
Introdurremo un "conflitto" nel contenuto di entrambi i file in due diversi rami 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
Ora, proviamo a unire "hisBranch" a "myBranch", con:
- risoluzione manuale per unioni in conflitto
- tranne per
dirWithCopyMerge\b.txt
cui ho sempre voglia di mantenere la mia versione di b.txt
.
Poiché l'unione avviene in " MyBranch
", torneremo ad essa e aggiungeremo le gitattributes
direttive " " che personalizzeranno il comportamento di unione.
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
Abbiamo un .gitattributes
file definito nella dirWithCopyMerge
directory (definito solo nel ramo in cui avverrà l'unione :) myBranch
, e abbiamo un .git\config
file che ora contiene un merge driver.
[merge "keepMine"]
name = always keep mine during merge
driver = keepMine.sh %O %A %B
Se non definisci ancora keepMine.sh e avvii comunque l'unione, ecco cosa ottieni.
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
Questo va bene:
a.txt
è pronto per essere unito e contiene un conflitto
b.txt
è ancora intatto, poiché si suppone che il driver di fusione se ne occupi (a causa della direttiva nel .gitattributes
file nella sua directory).
Definisci un keepMine.sh
punto qualsiasi nel tuo %PATH%
(o $PATH
per il nostro amico Unix. Faccio entrambe le cose ovviamente: ho una sessione di Ubuntu in una sessione di VirtualBox)
Come commentato da lrkwz e descritto nella sezione " Unisci strategie " di Personalizzazione di Git - Attributi Git , puoi sostituire lo script della shell con il comando della shell true
.
git config merge.keepMine.driver true
Ma nel caso generale, puoi definire un file di 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
(che era un pilota merge semplice;) (Ancora più semplice in questo caso, l'uso true
)
(Se si voleva mantenere l'altra versione, basta aggiungere prima della exit 0
riga:
cp -f $3 $2
.
Questo è tutto Si uniscono conducente avrebbe away mantenere la versione proveniente dall'altro. branch, ignorando qualsiasi modifica locale)
Ora, riproviamo l'unione dall'inizio:
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.
L'unione fallisce ... solo per a.txt .
Modifica a.txt e lascia la riga da "hisBranch", quindi:
git add -A
git commit -m "resolve a.txt by accepting hisBranch version"
[myBranch 77bc81f] resolve a.txt by accepting hisBranch version
Controlliamo che b.txt sia stato preservato durante questa unione
type dirWithCopyMerge\b.txt
b
myLineForB
L'ultimo commit rappresenta l' unione completa :
git show -v 77bc81f5e
commit 77bc81f5ed585f90fc1ca5e2e1ddef24a6913a1d
Merge: ec202aa 658c31c
git merge hisBranch
Already up-to-date.
(La riga che inizia con Merge lo dimostra)
Considera di poter definire, combinare e / o sovrascrivere il driver di unione, come farà Git:
- esaminare
<dir>/.gitattributes
(che si trova nella stessa directory del percorso in questione): prevarrà sull'altro .gitattributes
nelle directory
- Quindi esamina
.gitattributes
(che si trova nella directory padre), imposterà solo le direttive se non già impostate
- Infine esamina
$GIT_DIR/info/attributes
. Questo file viene utilizzato per sovrascrivere le impostazioni nell'albero. Sovrascriverà le <dir>/.gitattributes
direttive.
Con "combinazione", intendo "aggregare" più driver di unione.
Nick Green cerca, nei commenti , di combinare effettivamente i driver di unione: vedere " Unisci i pom tramite il driver git di python ".
Tuttavia, come menzionato nella sua altra domanda , funziona solo in caso di conflitti (modifica simultanea in entrambi i rami).