W konkretnym przypadku pliku konfiguracyjnego zgodziłbym się z odpowiedzią Rona :
konfiguracja powinna być „prywatna” dla twojego obszaru roboczego (stąd „ignorowana”, jak w przypadku „zadeklarowanej w .gitignore
pliku”).
Możesz mieć szablon pliku konfiguracyjnego z tokenizowanymi wartościami i skrypt przekształcający ten config.template
plik w prywatny (i ignorowany) plik konfiguracyjny.
Jednak ta konkretna uwaga nie odpowiada na szersze, bardziej ogólne pytanie, tj. Twoje pytanie (!):
Jak powiedzieć gitowi, aby zawsze wybierał moją wersję lokalną do scalania w konflikcie w określonym pliku? (dla dowolnego pliku lub grupy plików)
Ten rodzaj scalania to „scalanie kopii”, w którym zawsze kopiujesz „naszą” lub „ich” wersję pliku, gdy wystąpi konflikt.
(jak zauważa Brian Vandenberg w komentarzach , „ ours
” i „ theirs
” są tutaj używane do scalania .
Są one odwrócone w przypadku rebase : patrz „ Why is the meaning of “ours” and “theirs” reversed with git-svn
”, który używa rebase, ” git rebase
, śledzenie„ lokalnego ”i„ zdalnego ” " )
W przypadku „pliku” (ogólnie pliku, nie mówiąc o pliku „konfiguracyjnym”, ponieważ jest to zły przykład), można to osiągnąć za pomocą niestandardowego skryptu wywoływanego przez scalanie.
Git wywoła ten skrypt, ponieważ będziesz musiał zdefiniować wartość gitattributes , która definiuje niestandardowy sterownik scalania .
„Niestandardowy sterownik scalania” jest w tym przypadku bardzo prostym skryptem, który zasadniczo zachowuje niezmienioną wersję bieżącej wersji, dzięki czemu można zawsze wybrać lokalną wersję.
Tj., Jak zauważył przez Ciro Santilli :
echo 'path/to/file merge=ours' >> .gitattributes
git config --global merge.ours.driver true
Przetestujmy to w prostym scenariuszu, z msysgit 1.6.3 w systemie Windows, w zwykłej sesji 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/
Teraz stwórzmy dwa pliki, które będą miały konflikty, ale które zostaną scalone w inny sposób.
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
Wprowadzimy „konflikt” w zawartości obu tych plików w dwóch różnych gałęziach 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
Teraz spróbujmy połączyć „hisBranch” z „myBranch” z:
- ręczne rozwiązywanie konfliktów połączeń
- z wyjątkiem sytuacji, w
dirWithCopyMerge\b.txt
których zawsze chcę zachować moją wersję b.txt
.
Ponieważ scalanie następuje w „ MyBranch
”, wrócimy do niego i dodamy gitattributes
dyrektywy „ ”, które dostosują zachowanie scalania.
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
Mamy .gitattributes
plik zdefiniowany w dirWithCopyMerge
katalogu (zdefiniowany tylko w gałęzi, w której nastąpi scalenie:) myBranch
i mamy .git\config
plik, który zawiera teraz sterownik scalania.
[merge "keepMine"]
name = always keep mine during merge
driver = keepMine.sh %O %A %B
Jeśli jeszcze nie zdefiniowałeś keepMine.sh i mimo to uruchomisz scalanie, oto co otrzymasz.
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
W porządku:
a.txt
jest gotowy do połączenia i ma w sobie konflikt
b.txt
jest nadal nietknięty, ponieważ sterownik merge ma się tym zająć (ze względu na dyrektywę w .gitattributes
pliku w jego katalogu).
Zdefiniuj keepMine.sh
dowolne miejsce w swoim %PATH%
(lub $PATH
dla naszego znajomego Uniksa. Oczywiście robię oba: mam sesję Ubuntu w sesji VirtualBox)
Jak skomentował przez lrkwz i opisane w „ Merge Strategies sekcji” z Dostosowywanie Git - Git Atrybuty można zastąpić skrypt z poleceniem powłoki true
.
git config merge.keepMine.driver true
Ale w ogólnym przypadku możesz zdefiniować plik skryptu:
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
(to był jeden prosty kierowca seryjnej;) (jeszcze prostsze w tym przypadku należy użyć true
)
(Jeśli chcesz zachować drugą wersję, wystarczy dodać przed exit 0
linią:
cp -f $3 $2
.
To wszystko scalić kierowca wynos zachować wersję pochodzących z drugiej. oddział, nadpisując wszelkie zmiany lokalne)
Teraz spróbujmy ponownie scalić od początku:
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.
Scalanie kończy się niepowodzeniem ... tylko dla pliku.txt .
Edytuj plik a.txt i opuść linię z „hisBranch”, a następnie:
git add -A
git commit -m "resolve a.txt by accepting hisBranch version"
[myBranch 77bc81f] resolve a.txt by accepting hisBranch version
Sprawdźmy, czy plik b.txt został zachowany podczas tego scalania
type dirWithCopyMerge\b.txt
b
myLineForB
Ostatnie zatwierdzenie reprezentuje pełne scalenie:
git show -v 77bc81f5e
commit 77bc81f5ed585f90fc1ca5e2e1ddef24a6913a1d
Merge: ec202aa 658c31c
git merge hisBranch
Already up-to-date.
(Wiersz zaczynający się od Merge to potwierdza)
Weź pod uwagę, że możesz zdefiniować, połączyć i / lub nadpisać sterownik scalający, tak jak Git:
- zbadać
<dir>/.gitattributes
(który znajduje się w tym samym katalogu, co dana ścieżka): będzie miał pierwszeństwo przed innymi .gitattributes
w katalogach
- Następnie sprawdza
.gitattributes
(który znajduje się w katalogu nadrzędnym), ustawi dyrektywy tylko wtedy, gdy nie zostały jeszcze ustawione
- Wreszcie bada
$GIT_DIR/info/attributes
. Ten plik jest używany do nadpisywania ustawień w drzewie. Zastąpi <dir>/.gitattributes
dyrektywy.
Przez „łączenie” rozumiem „zagregowany” sterownik wielokrotnego scalania.
Nick Green próbuje w komentarzach faktycznie połączyć sterowniki scalające: zobacz „ Łączenie pom za pomocą sterownika Python git ”.
Jednak, jak wspomniał w innym pytaniu , działa tylko w przypadku konfliktów (równoczesna modyfikacja w obu gałęziach).