Git
Chapters ▾ 2nd Edition

7.9 Git Araçları - Rerere

Rerere

git rerere işlevselliği biraz gizli bir özelliktir. Adı, "kaydedilen çözümü yeniden kullan" anlamına gelir ve adından da anlaşılacağı gibi, bir hunk çakışmasını nasıl çözdüğünüzü Git’e hatırlatmanıza olanak tanır, böylece bir sonraki sefer aynı çakışmayı gördüğünde, Git otomatik olarak çözebilir.

Bu işlevselliğin gerçekten kullanışlı olabileceği birkaç senaryo bulunmaktadır. Dokümentasyonda belirtilen örneklerden biri, uzun ömürlü bir konu dalını temiz bir şekilde birleştirilmesini istediğiniz, ancak katkı geçmişinizi karmaşıklaştıracak bir dizi ara birleştirme katkısı görmek istemediğiniz durumdur. rerere etkinleştirildiğinde, ara sıra birleştirme deneyebilir, çakışmaları çözebilir ve ardından birleştirmeyi geri alabilirsiniz. Bu işlemi sürekli olarak yaparsanız, rerere her şeyi otomatik olarak sizin için yapabileceği için son birleştirmenin kolay olması beklenir.

Bu aynı taktik, her seferinde aynı yeniden temelleme çakışmalarıyla uğraşmak zorunda kalmadan, bir dalı yeniden temellenmiş tutmak istediğiniz de de kullanılabilir. Ya da bir daldan birleştirdiğiniz ve bir sürü çakışmayı düzelttiğiniz bir dalı alıp yeniden temellemeye karar verirseniz — muhtemelen tüm aynı çakışmaları tekrar düzeltmenize gerek kalmaz.

rerere'nin başka bir uygulaması, Git projesinin kendisinde sıklıkla olduğu gibi, zaman zaman birbirine dönüşen birçok konu dalını birleştirerek test edilebilir bir baş yapı oluşturmanızdır. Testler başarısız olursa, birleştirmeleri geri alabilir ve çatışmaları tekrar çözmeden, başarısızlığa sebep olan konu dalını çıkararak testleri yeniden yürütebilirsiniz.

rerere işlevselliğini etkinleştirmek için, yalnızca şu yapılandırma ayarını çalıştırmanız yeterlidir:

$ git config --global rerere.enabled true

Ayrıca, belirli bir repoda .git/rr-cache dizinini oluşturarak da etkinleştirebilirsiniz, ancak yapılandırma ayarı daha açıklayıcıdır ve bu özelliği sizin için genel olarak etkinleştirir.

Şimdi basit bir örnek görelim, önceki örneğimize benzer. Diyelim ki hello.rb adında şöyle bir dosyamız var:

#! /usr/bin/env ruby

def hello
  puts 'hello world'
end

Aynı daha önce yaptığımız gibi bir dalda "hello" kelimesini "hola" olarak değiştirirken, diğer bir dalda "world" kelimesini "mundo" olarak değiştiriyoruz, yine önceki gibi.

rerere1

İki dalı birleştirdiğimizde, birleştirme çakışması alacağız:

$ git merge i18n-world
Auto-merging hello.rb
CONFLICT (content): Merge conflict in hello.rb
Recorded preimage for 'hello.rb'
Automatic merge failed; fix conflicts and then commit the result.

Orada Recorded preimage for FILE yeni satırını fark etmişsinizdir. Yoksa, bu normal birleştirme çakışmasıyla tamamen aynı görünmeliydi. Bu noktada, rerere bize birkaç bilgi verir. Normalde, şu anda nelerin çakıştığını görmek için git status komutunu çalıştırabilirsiniz:

$ git status
# On branch master
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add <file>..." to mark resolution)
#
#	both modified:      hello.rb
#

Ancak, git rerere komutunun önişlem durumunu kaydettiği şeyleri git rerere status ile görebilirsiniz:

$ git rerere status
hello.rb

Ve git rerere diff komutu, çözümün mevcut durumunu gösterecektir (çözümlemeye başladığınız şeyi ve onun son halini).

$ git rerere diff
--- a/hello.rb
+++ b/hello.rb
@@ -1,11 +1,11 @@
 #! /usr/bin/env ruby

 def hello
-<<<<<<<
-  puts 'hello mundo'
-=======
+<<<<<<< HEAD
   puts 'hola world'
->>>>>>>
+=======
+  puts 'hello mundo'
+>>>>>>> i18n-world
 end

Ayrıca (bunun rerere ile ilgisi yoktur), git ls-files -u komutunu kullanarak, çakışan dosyaları, önceki, sol ve sağ sürümleri görebilirsiniz:

$ git ls-files -u
100644 39804c942a9c1f2c03dc7c5ebcd7f3e3a6b97519 1	hello.rb
100644 a440db6e8d1fd76ad438a49025a9ad9ce746f581 2	hello.rb
100644 54336ba847c3758ab604876419607e9443848474 3	hello.rb

Şimdi bunu sadece puts 'hola mundo' olarak çözebilir ve git rerere diff komutunu tekrar çalıştırarak rerere’nin ne hatırlayacağını görebilirsiniz:

$ git rerere diff
--- a/hello.rb
+++ b/hello.rb
@@ -1,11 +1,7 @@
 #! /usr/bin/env ruby

 def hello
-<<<<<<<
-  puts 'hello mundo'
-=======
-  puts 'hola world'
->>>>>>>
+  puts 'hola mundo'
 end

Bu temelde, Git bir hello.rb dosyasında bir hunk çakışması gördüğünde, bir tarafta ``hello mundo`` ve diğer tarafta ``hola world`` olan durumda, onu ``hola mundo`` olarak çözecektir.

Artık bunu çözülmüş olarak işaretleyebilir ve katkı olarak işleyebiliriz:

$ git add hello.rb
$ git commit
Recorded resolution for 'hello.rb'.
[master 68e16e5] Merge branch 'i18n'

Görebileceğiniz gibi, "Recorded resolution for FILE" (Dosya için çözüm kaydedildi) ifadesini gösteriyor.

rerere2

Şimdi, o birleştirmeyi geri alalım ve ardından onu master dalımızın üzerine yeniden temelleyelim. Reset Komutunun Gizemleri bölümünde gördüğümüz gibi, git reset komutunu kullanarak dalımızı geri alabiliriz.

$ git reset --hard HEAD^
HEAD is now at ad63f15 i18n the hello

Birleştirmemiz geri alındı. Şimdi konu dalını yeniden temelleyelim.

$ git checkout i18n-world
Switched to branch 'i18n-world'

$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: i18n one word
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging hello.rb
CONFLICT (content): Merge conflict in hello.rb
Resolved 'hello.rb' using previous resolution.
Failed to merge in the changes.
Patch failed at 0001 i18n one word

Şimdi, beklendiği gibi aynı birleştirme çakışmasını aldık, ancak Resolved FILE using previous resolution (Önceki çözüm kullanılarak DOSYA çözüldü) satırına bakın. Dosyaya baktığımızda, zaten çözüldüğünü ve içinde birleştirme çatışma işaretçilerinin olmadığını göreceğiz.

#! /usr/bin/env ruby

def hello
  puts 'hola mundo'
end

Ayrıca, git diff komutu, size çakışmanın nasıl otomatik olarak yeniden çözüldüğünü gösterecektir:

$ git diff
diff --cc hello.rb
index a440db6,54336ba..0000000
--- a/hello.rb
+++ b/hello.rb
@@@ -1,7 -1,7 +1,7 @@@
  #! /usr/bin/env ruby

  def hello
-   puts 'hola world'
 -  puts 'hello mundo'
++  puts 'hola mundo'
  end
rerere3

Ayrıca, git checkout kullanarak çakışan dosya durumunu yeniden oluşturabilirsiniz:

$ git checkout --conflict=merge hello.rb
$ cat hello.rb
#! /usr/bin/env ruby

def hello
<<<<<<< ours
  puts 'hola world'
=======
  puts 'hello mundo'
>>>>>>> theirs
end

İleri Seviye Birleştirme bölümünde bunun bir örneğini gördük. Ancak şimdilik, sadece git rerere komutunu yeniden çalıştırarak tekrar çözeceğiz:

$ git rerere
Resolved 'hello.rb' using previous resolution.
$ cat hello.rb
#! /usr/bin/env ruby

def hello
  puts 'hola mundo'
end

rerere önbelleğindeki çözümü kullanarak dosyayı otomatik olarak çözdük. Şimdi izleme alabilir ve yeniden temellemeyi tamamlamak için devam edebilirsiniz.

$ git add hello.rb
$ git rebase --continue
Applying: i18n one word

Dolayısıyla, birçok yeniden birleştirme yaparsanız veya bir konu dalınızı bir sürü birleştirmenin ardından güncel tutmak istiyorsanız, veya sık sık yeniden temelleme yapıyorsanız, rerere 'yi açarak işlerinizi biraz olsun kolaylaştırabilirsiniz.

scroll-to-top