İçeriğe geç
academia.sh

Ders 13 / 15

Devirme

Bir işlemenin etkisini tersine çeviren yeni işleme; tarihçeyi bozmadan geri alma, ağaç kimliğiyle doğrulama, işlemeden devirme ve devirmenin devrilmesi.

Yayın Güncelleme

Bu derste

  • Bir işlemenin etkisini tarihçeyi yeniden yazmadan geri alır
  • Devirme işlemesinin ürettiği ağacın hangi işlemeyle örtüştüğünü doğrular
  • Devirme ile sıfırlama arasında duruma göre seçim yapar
İçindekiler

Sıfırlama ve değiştirme, tarihçeyi yeniden yazarak çalışır; bu yüzden paylaşılmış işlemelerde kullanılamazlar. Paylaşılmış bir işleme hatalıysa geriye tek bir yol kalır: geçmişi olduğu gibi bırakıp, hatanın etkisini tersine çeviren yeni bir işleme yazmak. Bu işleme devirme (revert) denir.

Hata

Arama betiğinin çıktısı yalnızca Türkçe sütunla sınırlandırılmak istenir ve grep çıktısı bir süzgeçten geçirilir. Betikteki koşul satırı sed ile düzenlenir:

sed -i.bak "s/terimler.txt; then/terimler.txt | cut -d '|' -f 1; then/" ara.sh
rm ara.sh.bak

Düzenlemeden sonra koşul şu hâle gelir:

{/* run: skip */}

if ! grep -i -- "$1" terimler.txt | cut -d '|' -f 1; then
    echo "eşleşme yok: $1" >&2
    exit 2
fi

Değişiklik, tarihleri sabitlenmiş bir işlemeyle kaydedilir. Tarih değişkenleri açık oturumda tanımlıdır; yeni bir terminal açtıysanız yeniden yazın:

export GIT_AUTHOR_DATE="2024-03-11 09:30:00 +0300"
export GIT_COMMITTER_DATE="2024-03-11 09:30:00 +0300"
git commit -a -m "Arama çıktısını yalnızca Türkçe sütuna indir"
[main d245350] Arama çıktısını yalnızca Türkçe sütuna indir
 1 file changed, 1 insertion(+), 1 deletion(-)

Değişiklik istenen çıktıyı üretir ama gizli bir kusur taşır: kabuk, boru hattının çıkış kodunu son komuttan alır. cut her durumda başarıyla sonlandığı için grep eşleşme bulamadığında da koşul yanlış çıkar:

./ara.sh yokboyle
echo "çıkış kodu: $?"
çıkış kodu: 0

Betik hiçbir eşleşme bildirimi yazmadı ve sıfır çıkış koduyla sonlandı; oysa eşleşme yoktur ve çıkış kodu 2 olmalıdır. Kusur, çıktının kendisinde değil hata bildirimindedir; bu nedenle gözden kaçmaya elverişlidir.

İşleme paylaşılmıştır ve tarihçeden düşürülemez.

Devirme

export GIT_AUTHOR_DATE="2024-03-11 10:12:00 +0300"
export GIT_COMMITTER_DATE="2024-03-11 10:12:00 +0300"
git revert --no-edit HEAD
[main c497738] Revert "Arama çıktısını yalnızca Türkçe sütuna indir"
 Date: Mon Mar 11 10:12:00 2024 +0300
 1 file changed, 1 insertion(+), 1 deletion(-)

--no-edit, hazırlanan mesajı düzenleyici açmadan kabul eder. Betik yeniden doğru çalışır:

./ara.sh yokboyle
eşleşme yok: yokboyle
git log --oneline -n 4
c497738 Revert "Arama çıktısını yalnızca Türkçe sütuna indir"
d245350 Arama çıktısını yalnızca Türkçe sütuna indir
377b1f8 README'ye kullanım bölümü ekle
0e74ba9 Öbek ve dizi terimlerini ekle

Hatalı işleme tarihçede duruyor. Yanına, etkisini tersine çeviren bir işleme eklendi.

Devirme İşlemesinin İçeriği

git show HEAD
commit c49773829409f26d221a2bb5b46a58d8ca2c8327
Author: Deniz Kaya <[email protected]>
Date:   Mon Mar 11 10:12:00 2024 +0300

    Revert "Arama çıktısını yalnızca Türkçe sütuna indir"

    This reverts commit d2453504d3bed0b24e4bedfaac3c3b87c508b799.

diff --git a/ara.sh b/ara.sh
index 64b5b70..582ddde 100755
--- a/ara.sh
+++ b/ara.sh
@@ -6,7 +6,7 @@ if [ $# -ne 1 ]; then
     exit 1
 fi
 
-if ! grep -i -- "$1" terimler.txt | cut -d '|' -f 1; then
+if ! grep -i -- "$1" terimler.txt; then
     echo "eşleşme yok: $1" >&2
     exit 2
 fi

Fark, devrilen işlemenin farkının tersidir: silinen satır eklenmiş, eklenen satır silinmiştir. Otomatik oluşturulan mesaj, devrilen işlemenin tam kimliğini gövdeye yazar; bu satır sayesinde bir devirmenin neyi geri aldığı tarihçeden okunabilir.

Sonucun Doğrulanması

Devirmenin gerçekten önceki duruma döndürüp döndürmediği, ağaç kimlikleri karşılaştırılarak kesin olarak sınanır:

git log --format='%h %T %s' -n 4
c497738 961039799e5ee6f157229351478a98abb7652c82 Revert "Arama çıktısını yalnızca Türkçe sütuna indir"
d245350 0f2d862b8a585d8dfc9b1a0acbdb30a221233ade Arama çıktısını yalnızca Türkçe sütuna indir
377b1f8 961039799e5ee6f157229351478a98abb7652c82 README'ye kullanım bölümü ekle
0e74ba9 c6ec3cea3b8943f818cd8bb423c65f0cb5c553ea Öbek ve dizi terimlerini ekle

Devirme işlemesinin ağacı 9610397, hatalı işlemeden önceki 377b1f8 işlemesinin ağacıyla aynıdır. İki farklı işleme aynı ağacı gösteriyor: proje içeriği bayt düzeyinde eski hâline dönmüştür. İçerik adresli depolamanın verdiği bu eşitlik sınaması, farkları gözle karşılaştırmaya gerek bırakmaz.

Devirme Neden Tarihçeyi Bozmaz

Devirme yalnızca ekleme yapar: var olan hiçbir nesneye dokunmaz, hiçbir kimliği değiştirmez. Tarihçeyi daha önce almış kopyalar, ellerindeki zinciri korur ve üzerine tek bir yeni işleme alır. Sıfırlamada ortaya çıkan uyumsuzluk burada oluşmaz.

Bedeli, hatanın tarihçede görünür kalmasıdır. Bu bir kusur değil, çoğu zaman istenen davranıştır: hatalı bir değişikliğin ne zaman girdiği, ne zaman ve neden geri alındığı kaydedilmiş olur.

İşlemeden Devirmek

Devirmenin sonucu doğrudan işlenmeden incelenebilir:

git revert -n HEAD~3
git status --short
M  terimler.txt
git diff --staged
diff --git a/terimler.txt b/terimler.txt
index a5350ef..17af3b8 100644
--- a/terimler.txt
+++ b/terimler.txt
@@ -5,5 +5,3 @@ ağaç | tree
 karma tablosu | hash table
 bağlı liste | linked list
 küme | set
-öbek | heap
-dizi | array

-n seçeneği değişikliği hazırlık alanına koyar ama işlemez. Bu, birden çok işlemeyi tek bir devirme işlemesinde toplamak ya da sonucu işlemeden önce incelemek için kullanılır. İşlem git revert --abort ile iptal edilebilir:

git revert --abort

Komut hazırlık alanını ve çalışma dizinini devirme başlamadan önceki hâline döndürür.

Örnekte devrilen işleme, tarihçenin en son işlemesi değildi. Devirme herhangi bir işlemeye uygulanabilir; hesaplanan şey, o işlemenin farkının tersinin şu anki içeriğe uygulanmasıdır. Aradan geçen işlemeler aynı satırlara dokunmuşsa uygulama başarısız olur ve çakışma bildirilir. Çakışma çözümü Dallanma ve İşbirliği kursunun konusudur.

Devirmenin Devrilmesi

Devirme de bir işlemedir; devrilebilir. Bu, geri alınan bir değişikliği yeniden uygulamanın yoludur:

export GIT_AUTHOR_DATE="2024-03-11 15:00:00 +0300"
export GIT_COMMITTER_DATE="2024-03-11 15:00:00 +0300"
git revert --no-edit HEAD
[main 5bba728] Reapply "Arama çıktısını yalnızca Türkçe sütuna indir"
 Date: Mon Mar 11 15:00:00 2024 +0300
 1 file changed, 1 insertion(+), 1 deletion(-)

Mesaj bu kez Revert değil Reapply ile başlar: bir devirmenin devrilmesi, özünde yeniden uygulamadır.

git log --format='%h %T %s' -n 4
5bba728 0f2d862b8a585d8dfc9b1a0acbdb30a221233ade Reapply "Arama çıktısını yalnızca Türkçe sütuna indir"
c497738 961039799e5ee6f157229351478a98abb7652c82 Revert "Arama çıktısını yalnızca Türkçe sütuna indir"
d245350 0f2d862b8a585d8dfc9b1a0acbdb30a221233ade Arama çıktısını yalnızca Türkçe sütuna indir
377b1f8 961039799e5ee6f157229351478a98abb7652c82 README'ye kullanım bölümü ekle

Dört işleme, iki ağaç arasında dönüşümlü gidip geliyor. Örnek deponun tarihçesinde bu son adım tutulmamıştır — kusurlu değişiklik yeniden uygulanmamış, devirme yerinde bırakılmıştır. Örnek depoyu o durumda tutmak için son işleme geri sarılır:

git reset --hard HEAD~1
HEAD is now at c497738 Revert "Arama çıktısını yalnızca Türkçe sütuna indir"

Devirme mi, Sıfırlama mı

Ölçüt Devirme Sıfırlama
Tarihçe Korunur, yeni işleme eklenir Yeniden yazılır
Paylaşılmış işlemede Uygundur Uygun değildir
Hatanın görünürlüğü Kayıtta kalır Silinir
Uygulanabildiği işleme Herhangi biri Dal ucundan geriye doğru

Ölçüt tektir: işleme paylaşılmışsa devirme, paylaşılmamışsa her ikisi de kullanılabilir.

Özet

  • Devirme, bir işlemenin farkının tersini uygulayan yeni bir işleme oluşturur.
  • Tarihçe korunur; hiçbir nesne değişmez, yalnızca yeni bir işleme eklenir.
  • Devirme işlemesinin ağacı, devrilen işlemeden önceki ağaçla aynıdır; bu eşitlik doğrulama aracıdır.
  • -n seçeneği sonucu işlemeden hazırlık alanına koyar; --abort işlemi iptal eder.
  • Bir devirme de devrilebilir; sonuç, değişikliğin yeniden uygulanmasıdır.

Sonraki Adım

Buraya kadarki araçlar tamamlanmış değişikliklerle ilgiliydi. Peki yarım kalmış bir iş varken başka bir konuya geçmek gerekirse ne yapılır? İşlemek erken, geri almak ise kayıptır. Sonraki ders, yarım kalmış işi geçici olarak saklayan zulayı ve bu saklamanın nesne modelindeki karşılığını ele alacak.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ ↵ Esc gezin · aç · kapat