2009-05-30 6 views
82

Git havuzunda biriyle birlikte çalıştığımı ve herhangi bir harici değişikliği kabul etmek istemediğim belirli bir dosya olduğunu varsayalım.Git'e her zaman belirli bir dosyadaki çakışan birleştirmeler için yerel sürümümü seçmesini söylerim?

Yerel repo'umu, her çekişimde çakışan bir birleşimden şikayet etmemek için kurmamın bir yolu var mı? Bu dosyayı birleştirirken her zaman yerel sürümümü seçmek isterim.

+1

Sadece .gitattributes aracılığıyla basit bir çözüm ve bir çok temel "sürücü birleştirme" – VonC

+10

TD ekledi. ours.driver true ' –

+0

@CiroSantilli: Linux'ta bir çekicilik gibi çalışır. Bu sürücü Git'e dahil edilebilecek kadar basit ... – krlmlr

cevap

120

bir yapılandırma dosyasının belirli örneğinde, ben Ron's answer kabul edeceğini:
bir yapılandırma Aygıtı çalışma "özel" olması gerektiğini (dolayısıyla "göz ardı" "Bir .gitignore dosyasında bildirilen" gibi).
Bir yapılandırma dosyasını simgeleþtirilmiþ değerler içinde ile şablonu olabilir ve bir komut dosyası dönüştüren bir özel (ve göz ardı) yapılandırma dosyası içine config.template dosyası.


Ancak, daha geniş daha genel soru nedir yanıtını bulamadığınız belirli sözler, sorunuzu yani (!):

nasıl hep çatışmalı için benim yerel sürümünü seçmek için git diyeceğiz belirli bir dosya üzerinde birleştirir?

(dosyanın herhangi bir dosya veya grup için) birleştirme Bu tür bir çatışma olduğunda her zaman bir dosyanın 'bizimki' veya 'onların' sürümü kopyalar olduğu bir "kopya birleştirme" dir.

(Brian Vandenberg notları in the comments, 'ours' ve rebase 'theirs' Burada Onlar bir için ters olan
bir birleştirme işlemi için kullanılır gibidir: Bir rebase kullanır bkz "Why is the meaning of “ours” and “theirs” reversed with git-svn". "git rebase, keeping track of 'local' and 'remote'") 'bir dosyaya' genel olarak (bir dosya için

kötü bir örnektir, çünkü), bir 'yapılandırma' dosyasının konuşan değil, size ulaşmak istiyorum birleştirme yoluyla çağrılan özel bir senaryo ile.
Git bu komut dosyasını arayacaktır çünkü bir tanımlayacaktır; bu, özel birleştirme sürücüsünü tanımlayan.

"Özel birleştirme sürücüsü" bu durumda, geçerli sürümü değiştirmeyecek ve böylece her zaman yerel sürümünüzü seçmenize izin veren çok basit bir komut dosyasıdır.

Şimdi
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/ 

, en hem çatışmaları sahip olacak iki dosya, yapalım: basit senaryoda, sadece DOS oturumu Windows üzerinde bir msysgit 1.6.3, o


edelim testi ama farklı bir şekilde birleştirilecek.

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 

Biz iki farklı git dallarında hem bu dosyaların içeriğinde bir "çatışma" tanıtacak:

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 

Şimdi, "myBranch" üzerine "hisBranch" birleştirmeye çalışalım, birlikte:

    çakışan için
  • manuel çözünürlük dirWithCopyMerge\b.txt için hariç
  • birleştirir Burada her zaman benim b.txt sürümünü tutmak istiyorum. Birleştirme 'MyBranch' oluşur yana

, bunu geri dönün ve birleştirme davranışını özelleştirmek olacaktır 'gitattributes' direktifleri katacak.

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 

Biz (yalnızca birleştirme irade ortaya dalında tanımlamıştır: myBranch) dirWithCopyMerge dizinde tanımlanan bir .gitattributes dosyası var ve şimdi bir birleştirme sürücüsü içeren .git\config dosyası var. Henüz zaten birleştirme keepMine.sh tanımlamak ve başlatmak yoksa

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

, burada ne elde ediyoruz. gayet

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 birleştirilecek hazırdır ve (birleştirme sürücü icabına gerekiyordu çünkü
  • b.txt, hala bakir çatışmaları vardır nedeniyle dizinindeki .gitattributes dosyasındaki yönerge.

her yerde %PATH% bir keepMine.sh tanımlayın: lrkwz tarafından commented gibi

(. Veya $PATH bizim Unix arkadaş için ben tabii her ikisini de bir VirtualBox oturumda bir Ubuntu seans) ve açıklanan Customizing Git - Git Attributes'un "Merge Strategies" bölümü, kabuk komut dosyasını true kabuk komutunu kullanarak değiştirebilirsiniz.

git config merge.keepMine.driver true 

Ancak genel durumda, bir komut dosyası tanımlayabilirsiniz:

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 

(yani tek bir basit birleştirme sürücü vardı;) (bu durumda bile daha basit, diğer sürümünü kullanmaya devam etmek istiyorsa sadece exit 0 satırdan önce ekleyin (true)
kullanın:.
cp -f $3 $2
İşte bu.Sadece için

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. 

birleştirme başarısız ... : Sürücü uzağa Şimdi herhangi bir yerel değişim)

basan, diğer dalı gelen versiyonunu tutacak birleştirme, en başından itibaren birleştirme yeniden denemek izin .txt.
Düzenleme a.txt ve gelen çizgiyi terk edin 'hisBranch', o zaman:

git add -A 
git commit -m "resolve a.txt by accepting hisBranch version" 
[myBranch 77bc81f] resolve a.txt by accepting hisBranch version 

en o b.txt birleştirme bunlar olurken korunmuştur kontrol edelim son temsil ediyor taahhüt

type dirWithCopyMerge\b.txt 
b 
myLineForB 

tam birleştirme:

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

(merge ile başlayan çizgi kanıtlamak etmez)

birbiri üzerine geçerli olacaktır:

  • (söz konusu yolun aynı dizinde) <dir>/.gitattributes incelemek:

    , olur Git gibi, sürücü birleştirme tanımlamak birleştirmek ve/veya üzerine yazabilirsiniz düşünün zaten

  • Nihayet $GIT_DIR/info/attributes inceler kümesi değilse
  • dizinleri
  • yılında .gitattributes Sonra sadece direktifleri ayarlayacaktır, (üst dizinde olan) .gitattributes inceler. Bu dosya ağaç içi ayarlarını geçersiz kılmak için kullanılır. <dir>/.gitattributes direktiflerinin üzerine yazacaktır.

"Birleştirme" ile, "birleştirme" çoklu birleştirme sürücüsünü kastediyorum. Aslında birleştirme sürücülerini birleştirmek için
Nick Green, in the comments, deneyin: "Merge pom's via python git driver".
Ancak, his other question'da belirtildiği gibi, yalnızca çakışma durumunda çalışır (her iki dalda eşzamanlı değişiklik).

+1

Detaylı cevap için teşekkür ederiz! Sürüm kontrolü yapılandırma dosyalarına bir anlam ifade etmediğini anlıyorum, ancak basit bir motive edici örnek peşindeydim. Gerçekten de, beni ilgilendiren daha geniş bir soru. Daha önce git birleştirme sürücülerini hiç duymamıştım, bu yüzden beni aydınlattığın için teşekkür ederim. – saffsd

+0

@Brian: Düzenleme için teşekkürler :) – VonC

+0

Özel birleştirme sürücüsünün uygulaması örneği: http: // stackoverflow.com/questions/2250040/using-github-to-host-public-git-depoları-yaparken-o-hassas-veri-o-hassas-veri – VonC

0

Hiçbir zaman üzerine yazılmasını istemediğimiz çoklu yapılandırma dosyalarımız var. Ancak .gitignore ve .gitattributes bizim durumumuzda işe yaramadı. Çözümümüz, yapılandırma dosyalarını bir yapılandırma şubesinde saklamaktı. Ardından, git birleştirmesi sırasında dosyaların değiştirilmesine izin verin, ancak birleştirme işleminin hemen ardından "git checkout dalını" kullanın. her birleştirme işleminden sonra yapılandırma dosyalarımızı configs dalından kopyalamak için. `Echo '/ yol/dosya birleştirme = bizimki' >> .gitattributes && git config --global birleştirme: LR; Detailed stackoverflow answer here

İlgili konular