Git kullanarak tüm dosya üzerinde 'onlarınkini kabul' veya 'benimkini kabul et' için basit bir araç


399

Görsel birleştirme aracı istemiyorum ve ayrıca çakışan dosyayı vi yapmak ve manuel olarak HEAD (benim) ve içe aktarılan değişiklik (onların) arasında seçim yapmak istemiyorum. Çoğu zaman ya tüm değişikliklerini ya da benimkini istiyorum. Genelde bunun nedeni, benim değişikliğimin bunu yukarı çekmesi ve bana bir çekmeyle geri dönmesidir, ancak çeşitli yerlerde biraz değiştirilebilir.

Çatışma belirteçlerinden kurtulacak ve seçimime bağlı olarak hepsini bir şekilde seçecek bir komut satırı aracı var mı? Ya da her birini yapmak için kendime takma ad verebileceğim bir git komutları kümesi.

# accept mine
alias am="some_sequence;of;commands"
alias at="some_other_sequence;of;commands"

Bunu yapmak oldukça sinir bozucu. 'Benimkini kabul et' için denedim:

randy@sabotage ~/linus $ git merge test-branch
Auto-merging Makefile
CONFLICT (content): Merge conflict in Makefile
Automatic merge failed; fix conflicts and then commit the result.

randy@sabotage ~/linus $ git checkout Makefile 
error: path 'Makefile' is unmerged

andy@sabotage ~/linus $ git reset --hard HEAD Makefile 
fatal: Cannot do hard reset with paths.

Bu değişiklik işaretlerinden nasıl kurtulmam gerekiyor?

Yapabilirim:

git reset HEAD Makefile; rm Makefile; git checkout Makefile

Ama bu oldukça yuvarlak görünüyor, daha iyi bir yol olmalı. Ve bu noktada, git birleşmenin olduğunu düşünüp düşünmediğinden emin değilim, bu yüzden bunun bile işe yaradığını düşünmüyorum.

Diğer yöne gitmek, 'onlarınkini kabul etmek' yapmak da aynı derecede dağınık. Bunu anlamanın tek yolu:

git show test-branch:Makefile > Makefile; git add Makefile;

Bu da bana Çatışmalar: Makefile içinde iki kez berbat bir taahhüt mesajı verir.

Birisi yukarıdaki iki eylemin nasıl daha basit bir şekilde yapılacağını gösterebilir mi? Teşekkürler


4
Sana üç yıl + git komut satırı kullanıcısı olarak vermek zorundayım Bunu hafızadan yapmak çok gülünç buluyorum. Gerçekten varsayılan olarak yerleşik olmalıdır.
Mauvis Ledford

Yanıtlar:


602

Çözüm çok basit. git checkout <filename>dosyayı dizinden teslim etmeye çalışır ve bu nedenle birleştirme işleminde başarısız olur.

Yapmanız gereken şey (yani bir taahhütte bulunmak ):

Kendi sürümünüzü kontrol etmek için aşağıdakilerden birini kullanabilirsiniz :

git checkout HEAD -- <filename>

veya

git checkout --ours -- <filename>

veya

git show :2:<filename> > <filename> # (stage 2 is ours)

Diğer sürüme göz atmak için şunlardan birini kullanabilirsiniz :

git checkout test-branch -- <filename>

veya

git checkout --theirs -- <filename>

veya

git show :3:<filename> > <filename> # (stage 3 is theirs)

Çözülmüş olarak işaretlemek için 'add' komutunu da çalıştırmanız gerekir:

git add <filename>

31
Bunu biraz garip buldum --oursve --theirsbu komutu denerken sezgisel olarak düşündüğümün tam tersi anlamına geliyor ...
Joshua Muheim

6
Kullanırken dikkatli olun git show- bu yeni satır normalizasyonunu atlar.
Chronial

2
Bu, birkaç dosya için güzel, ancak çakışan çok sayıda dosyanız varsa (bir yorumdaki tarih değiştiğinden!), Bunu nasıl yapıyorsunuz?
JhovaniC

4
@Santhos: --Git tarafından revizyonları (şube adları vb.) Yol adlarından (dosya adları, dizinler) ayırmak için kullanılır. Git'in bir adın dal adı mı yoksa dosya adı mı olduğuna karar verememesi önemlidir. Bu, seçenekleri bağımsız değişkenlerden (dosya adları) ayırmak için çift tire kullanma POSIX (veya GNU) kuralını izler.
Jakub Narębski

3
@Sammaron @Joshua Muheim; theirs/ oursBir Rebase operasyonu bağlamında çatışmaları çözmek eğer takas olarak görülebilir. Rebase hedef dalı kontrol ederek çalıştığı ve kiraz toplama işlemi sizin "dalınızdan" hedefe doğru ilerlediğinden, gelen değişiklik ("onların") "dalınızdan" ve mevcut dal hedef daldır ("bizim" ).
RJFalconer

93

Bunu dene:

Değişikliklerini kabul etmek için: git merge --strategy-option theirs

Sizinkini kabul etmek için: git merge --strategy-option ours


5
Bunun, TÜM çakışan dosyalar için değişikliklerinizi koruyacağını unutmayın; bu nedenle, beklenmedik bir çakışma olursa tehlikeli olabilir.
John

3
Ve bunu kiraz toplama ve rebase gibi birleştirme-y komutları için kullanabilirsiniz.
idbrii

50

Jakub'ın cevabına dayanarak, kolaylık sağlamak için aşağıdaki git takma adlarını yapılandırabilirsiniz:

accept-ours = "!f() { git checkout --ours -- \"${@:-.}\"; git add -u \"${@:-.}\"; }; f"
accept-theirs = "!f() { git checkout --theirs -- \"${@:-.}\"; git add -u \"${@:-.}\"; }; f"

İsteğe bağlı olarak, çözümlenecek bir veya daha fazla dosya yolunu alırlar ve hiçbiri verilmemişse, geçerli dizinin altındaki her şeyi çözmeyi varsayılan olarak kullanırlar.

Bunları [alias]bölümünüze ekleyin ~/.gitconfigveya çalıştırın

git config --global alias.accept-ours '!f() { git checkout --ours -- "${@:-.}"; git add -u "${@:-.}"; }; f'
git config --global alias.accept-theirs '!f() { git checkout --theirs -- "${@:-.}"; git add -u "${@:-.}"; }; f'

1
Benim için çalışmıyor ... Bunlar bash veya başka bir kabuk için mi?
user456584

Bunlar git takma adlarıdır, bunları [alias]bölümünüze ekleyin ~.gitconfigveya kullanın git config --global accept-ours "...". Cevabımı düzenledim.
kynan

2
Bu takma adın beni ne kadar zaman kazandığına dair hiçbir fikrin yok. Başparmak havaya!
Adam Parkin

1
@hakre Takma adı belirttiğinizden emin olun, aksi takdirde kabuğunuz onu yorumlamaya çalışır. Veya sadece elle düzenleyin ~/.gitconfig.
kynan

1
Varsayılan değerler için kabuk sözdizimi:!f() { git checkout --ours -- "${@:-.}" git add -u "${@:-.}; }; f
jthill

17

Kynan'ın cevabına dayanarak, dosya adlarındaki boşlukları ve ilk tireları işleyebilecekleri şekilde değiştirilmiş aynı takma adlar şunlardır:

accept-ours = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --ours -- \"$@\"; git add -u -- \"$@\"; }; f"
accept-theirs = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --theirs -- \"$@\"; git add -u -- \"$@\"; }; f"

0

İleride bunları çözmek istiyoruz ve geçebilir yolu zamanın bildiğinde çatışmaları çözmek için ideal bir durumdur -Xoursveya -Xtheirsözyinelemeli birleştirme strateji seçeneği. Bunun dışında üç senaryo görebiliyorum:

  1. Dosyanın tek bir sürümünü saklamak istiyorsunuz (aksi takdirde çakışan ve çakışmayan dosyalar birbiriyle senkronize olmayabileceğinden, bu muhtemelen yalnızca birleştirilemeyen ikili dosyalarda kullanılmalıdır).
  2. Tüm çatışmalara belirli bir yönde karar vermek istiyorsunuz.
  3. Bazı çakışmaları manuel olarak çözmeniz ve ardından kalanların tümünü belirli bir yönde çözmeniz gerekir.

Bu üç senaryoyu ele almak için .gitconfigdosyanıza (veya eşdeğeri) aşağıdaki satırları ekleyebilirsiniz :

[merge]
  conflictstyle = diff3
[mergetool.getours]
  cmd = git-checkout --ours ${MERGED}
  trustExitCode = true
[mergetool.mergeours]
  cmd = git-merge-file --ours ${LOCAL} ${BASE} ${REMOTE} -p > ${MERGED}
  trustExitCode = true
[mergetool.keepours]
  cmd = sed -I '' -e '/^<<<<<<</d' -e '/^|||||||/,/^>>>>>>>/d' ${MERGED}
  trustExitCode = true
[mergetool.gettheirs]
  cmd = git-checkout --theirs ${MERGED}
  trustExitCode = true
[mergetool.mergetheirs]
  cmd = git-merge-file --theirs ${LOCAL} ${BASE} ${REMOTE} -p > ${MERGED}
  trustExitCode = true
[mergetool.keeptheirs]
  cmd = sed -I '' -e '/^<<<<<<</,/^=======/d' -e '/^>>>>>>>/d' ${MERGED}
  trustExitCode = true

get(ours|theirs)TAraca dosyanın ilgili sürümünü tutar ve değişikliklerin diğer sürümden (hiçbir birleştirme oluşur böylece) tüm uzağa atar.

merge(ours|theirs)Aracı verilen yönde çatışmaları çözmek için seçerek, üç yollu yerel, tabanından birleştirme ve dosyanın uzak sürümlerini yeniden yapar. Bunun bazı uyarıları vardır: özellikle: birleştirme komutuna iletilen fark seçeneklerini (algoritma ve boşluk işleme gibi) yoksayar; birleştirmeyi orijinal dosyalardan temiz bir şekilde yapar (bu nedenle, dosyadaki manuel değişiklikler atılır veya iyi veya kötü olabilir); ve dosyada olması gereken fark işaretleri tarafından karıştırılamaması avantajına sahiptir.

keep(ours|theirs)Araç sadece normal ifade bunları tespit, fark belirteçleri ve kapalı bölümlerini düzenler. Bunun avantajı, merge komutundaki diff seçeneklerini koruma ve bazı çakışmaları elle çözmenize ve geri kalanını otomatik olarak çözmenize izin vermesidir. Dezavantajı, dosyada başka çakışma belirteçleri varsa kafasının karışmasıdır.

Bunların tümü , sağlanmadığı takdirde tüm çakışan dosyaları işlediği git mergetool -t (get|merge|keep)(ours|theirs) [<filename>]yerde çalıştırılarak kullanılır <filename>.

Genel olarak konuşursak, normal ifadeyi karıştırmak için farklı işaretler olmadığını varsayarsak keep*, komutun varyantları en güçlü olanlardır. mergetool.keepBackupSeçeneği unset veya true olarak bırakırsanız, birleştirme işleminden sonra *.origdosyayı birleştirme sonucuna göre mantıklı olup olmadığını kontrol etmek için dağıtabilirsiniz. Örnek olarak, mergetooltaahhütte bulunmadan önce değişiklikleri incelemek için aşağıdakilerden sonra çalışıyorum :

for f in `find . -name '*.orig'`; do vimdiff $f ${f%.orig}; done

Not : Eğer merge.conflictstyledeğil diff3o /^|||||||/içinde desen sedkural olmalıdır /^=======/yerine.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.