Git Geçmişine Bakmak: git log, git show, git blame ve Alias'lar
git log'un --oneline, --graph, --stat, -p, --format, --author, --since, --grep ve --follow seçenekleriyle geçmişte geziniyor, -S ile -G arasındaki farkı fiyatı değişen bir satırla görüyoruz. git show ile tek commit'e ve eski bir dosya hâline bakıyor, git blame -L ile satırların kaynağını buluyor, alias'larla uzun komutları kısaltıyoruz.
Sürüm notu: Bu yazıdaki komutlar Git 2.54 ile denenmiştir.
Önce Tahmin Et
Alan, src/books.js'teki "Neuromancer" satırında yalnızca fiyatı değiştirdi: 9.99 yerine 8.99. Sen de bir "Neuromancer" kelimesinin geçtiği her commit'i bulmak için git log -S Neuromancer çalıştırıyorsun. Alan'ın commit'i listede çıkar mı?
Cevap çoğu kişinin tahmin ettiği gibi değil. Bu yazıda git log'un en çok kullanılan seçeneklerini, git show'u, git blame'i ve uzun komutları kısaltan alias'ları göreceğiz. Videolardaki "log ve değişiklik takibi" bölümünün karşılığı bu yazı.
git log ve Repo'nun Yeni Hâli
Bir önceki yazıdan bu yana birkaç gün geçti. Alan da projeye katıldı ve ikisi beş commit daha attı. Alan'ın bu commit'leri nasıl paylaştığını remote yazısında göreceğiz; şimdilik geçmişin kendisi bize yeter. En sade hâliyle:
$ git log
commit 8b5e66cab4a4e5f59b2ee1de843c956b884b9397 (HEAD -> main)
Author: Alan Turing <alan@example.com>
Date: Thu Nov 12 10:00:00 2026 +0300
Lower the price of Neuromancer
commit db44b0610fb6e017a6e6d6760543cf7bd43081b2
Author: Ada Lovelace <ada@example.com>
Date: Wed Nov 11 10:00:00 2026 +0300
Document discounts in README
commit b9d0ac5b7070886495623546f55a902b66c8b3af
Author: Alan Turing <alan@example.com>
Date: Tue Nov 10 10:00:00 2026 +0300
Fix rounding in cartTotal
0.1 + 0.2 style float errors showed up as 22.490000000000002 in the UI.
...
Çıktıyı kısalttım, gerisi aynı biçimde en eski commit'e kadar gidiyor. En yeni commit en üstte. Her commit için tam hash, yazar, tarih ve girintili mesaj var. İlk satırdaki (HEAD -> main), şu an nerede olduğunu söylüyor. Terminalde çıktı ekrana sığmazsa Git onu bir pager'da, genellikle less'te açar. Ok tuşlarıyla gezinir, / ile arar, q ile çıkarsın. Çıktıyı doğrudan terminale basmak istersen git --no-pager log de.
Kısa, Görsel ve Ayrıntılı
Günlük işte uzun biçime nadiren bakarsın:
$ git log --oneline
8b5e66c (HEAD -> main) Lower the price of Neuromancer
db44b06 Document discounts in README
b9d0ac5 Fix rounding in cartTotal
e6396b8 Add The Hobbit to the book list
f1f6068 Add discount support to cart
e351c69 Normalize line endings
1634232 Rename LICENSE.txt to LICENSE
6d89b81 Ignore build output, logs and local settings
5517793 Add license and local settings
e3ef418 Add cart total
fae4454 Add shopping cart
29f27c8 Add README and book list
$ git log --oneline -3
8b5e66c (HEAD -> main) Lower the price of Neuromancer
db44b06 Document discounts in README
b9d0ac5 Fix rounding in cartTotal
--oneline her commit'i kısa hash ve özet satırı olarak tek satıra indirir. Bir önceki yazılarda özet satırını neden kısa ve anlamlı tutmamız gerektiğini konuştuk; işte sebebi. -3 gibi bir sayı yalnızca son N commit'i gösterir.
$ git log --oneline --graph --all
* 8b5e66c (HEAD -> main) Lower the price of Neuromancer
* db44b06 Document discounts in README
* b9d0ac5 Fix rounding in cartTotal
* e6396b8 Add The Hobbit to the book list
...
--graph commit'lerin solunda geçmişin şeklini çizer, --all yalnızca bulunduğun branch'i değil bütün branch'leri gösterir. Bizim geçmişimiz şimdilik dümdüz bir çizgi, çünkü henüz tek branch var. Branch ve merge yazılarında bu çizgi dallanmaya başlayacak ve bu komut en çok kullandığın komutlardan biri olacak.
Commit'in neyi değiştirdiğini görmek için iki seçenek var. --stat özet verir:
$ git log --stat -2
commit 8b5e66cab4a4e5f59b2ee1de843c956b884b9397 (HEAD -> main)
Author: Alan Turing <alan@example.com>
Date: Thu Nov 12 10:00:00 2026 +0300
Lower the price of Neuromancer
src/books.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
commit db44b0610fb6e017a6e6d6760543cf7bd43081b2
Author: Ada Lovelace <ada@example.com>
Date: Wed Nov 11 10:00:00 2026 +0300
Document discounts in README
README.md | 2 ++
1 file changed, 2 insertions(+)
-p (patch) ise değişikliğin kendisini diff olarak gösterir:
$ git log -p -1
commit 8b5e66cab4a4e5f59b2ee1de843c956b884b9397 (HEAD -> main)
Author: Alan Turing <alan@example.com>
Date: Thu Nov 12 10:00:00 2026 +0300
Lower the price of Neuromancer
diff --git a/src/books.js b/src/books.js
index 0dc2038..1097f9e 100644
--- a/src/books.js
+++ b/src/books.js
@@ -1,5 +1,5 @@
export const books = [
{ id: 1, title: "Dune", price: 12.5 },
- { id: 2, title: "Neuromancer", price: 9.99 },
+ { id: 2, title: "Neuromancer", price: 8.99 },
{ id: 3, title: "The Hobbit", price: 11 },
];
- ile başlayan satır çıkan, + ile başlayan satır giren hâl. Bir önceki yazıda söylediğimiz gibi bu diff saklanan bir şey değil; Git onu commit'in snapshot'ını parent'ınınkiyle karşılaştırıp o anda üretti. Diff'i okumayı ayrıntılı olarak bir sonraki yazıda konuşacağız.
Hazır biçimler yetmiyorsa --format ile kendi biçimini kurabilirsin:
$ git log --format="%h %ad %an %s" --date=short -4
8b5e66c 2026-11-12 Alan Turing Lower the price of Neuromancer
db44b06 2026-11-11 Ada Lovelace Document discounts in README
b9d0ac5 2026-11-10 Alan Turing Fix rounding in cartTotal
e6396b8 2026-11-09 Ada Lovelace Add The Hobbit to the book list
%h kısa hash, %ad yazar tarihi, %an yazar adı, %s özet satırı. --date=short tarihi yıl-ay-gün olarak yazar. Sürüm notu ya da haftalık rapor çıkarırken bu tür bir biçim çok işe yarar.
Filtrelemek: Yazar, Tarih, Mesaj ve Dosya
Geçmiş büyüdükçe asıl ihtiyacın aradığını bulmak olur:
$ git log --oneline --author=Alan
8b5e66c (HEAD -> main) Lower the price of Neuromancer
b9d0ac5 Fix rounding in cartTotal
f1f6068 Add discount support to cart
$ git log --oneline --since="2026-11-10 00:00" --until="2026-11-11 23:59"
db44b06 Document discounts in README
b9d0ac5 Fix rounding in cartTotal
$ git log --oneline --grep=cart
b9d0ac5 Fix rounding in cartTotal
f1f6068 Add discount support to cart
e3ef418 Add cart total
fae4454 Add shopping cart
--author yazar adında ya da e-postasında geçen metne bakar; Alan yazmak yeterli. --since ve --until tarih aralığı verir; "2 weeks ago" ya da "yesterday" gibi göreli ifadeleri de anlar. Saat vermezsen dikkat: --since=2026-11-10 dersen Git günün başını değil, komutu çalıştırdığın anın saatini kullanır. O gün sabah atılmış bir commit'in listeden düştüğünü görürsen sebebi bu. --grep commit mesajlarında arar ve büyük-küçük harfe duyarlıdır; -i eklersen duyarsız olur. Bu filtreleri birleştirebilirsin: git log --author=Alan --grep=cart ikisine de uyan commit'leri getirir.
Bir dosyanın geçmişini görmek için dosya yolunu --'den sonra verirsin:
$ git log --oneline -- src/books.js
8b5e66c (HEAD -> main) Lower the price of Neuromancer
e6396b8 Add The Hobbit to the book list
29f27c8 Add README and book list
$ git log --oneline -- LICENSE
1634232 Rename LICENSE.txt to LICENSE
$ git log --oneline --follow -- LICENSE
1634232 Rename LICENSE.txt to LICENSE
5517793 Add license and local settings
LICENSE için tek commit çıktı, çünkü dosya bu isimle o commit'te doğdu. --follow, bir önceki yazıda yaptığımız rename'i takip edip LICENSE.txt zamanına da iner. -- işareti Git'e "bundan sonrası dosya yolu" der; bir branch ile bir dosyanın adı aynı olduğunda karışıklığı önler.
Kodun İçinde Aramak: -S ve -G
--grep mesajlarda arar. Kodun kendisinde aramak için pickaxe denen -S var. Açılıştaki soruya bakalım:
$ git log --oneline -S Neuromancer
29f27c8 Add README and book list
$ git log --oneline -G Neuromancer
8b5e66c (HEAD -> main) Lower the price of Neuromancer
29f27c8 Add README and book list
$ git log --oneline -S applyDiscount
db44b06 Document discounts in README
f1f6068 Add discount support to cart
-S Neuromancer yalnızca ilk commit'i buldu; Alan'ın commit'i yok. Sebebi, -S'in o kelimenin dosyalardaki geçme sayısının değiştiği commit'leri araması. Alan'ın commit'inden önce de sonra da "Neuromancer" bir kez geçiyor; satır değişti ama sayı değişmedi. -S'in asıl sorusu "bu metin ne zaman eklendi ya da silindi?". -G ise diff'te eklenen ya da çıkan satırlardan biri verdiğin düzenli ifadeyle eşleşiyorsa commit'i gösterir; bu yüzden Alan'ın commit'ini de buldu.
Üçüncü örnek de öğretici. applyDiscount fonksiyonunun ne zaman eklendiğini arıyorduk ve iki commit çıktı: fonksiyonu ekleyen commit ve README'ye applyDiscount(100, 15) örneğini yazan commit. -S bütün dosyalarda arar. Yalnızca koda bakmak istersen sonuna -- src/ ekleyerek aramayı daraltırsın.
git show: Tek Bir Commit'e Yakından Bakmak
git log bir aralığı listeler, git show tek bir şeyi açar:
$ git show b9d0ac5
commit b9d0ac5b7070886495623546f55a902b66c8b3af
Author: Alan Turing <alan@example.com>
Date: Tue Nov 10 10:00:00 2026 +0300
Fix rounding in cartTotal
0.1 + 0.2 style float errors showed up as 22.490000000000002 in the UI.
diff --git a/src/cart.js b/src/cart.js
index d9a0b0f..c723fcd 100644
--- a/src/cart.js
+++ b/src/cart.js
@@ -6,7 +6,8 @@ export function addToCart(cart, bookId) {
}
export function cartTotal(cart) {
- return cart.reduce((sum, book) => sum + book.price, 0);
+ const total = cart.reduce((sum, book) => sum + book.price, 0);
+ return Math.round(total * 100) / 100;
}
export function applyDiscount(total, percent) {
Commit'in bilgileri, mesajı ve diff'i bir arada. Diff'teki @@ -6,7 +6,8 @@ satırının sonunda export function addToCart yazması, Git'in değişikliğin hangi fonksiyonun yakınında olduğunu sana ipucu olarak göstermesi. git show da git log'un seçeneklerini anlar ve yalnızca commit'leri değil, belirli bir commit'teki bir dosyayı da gösterebilir:
$ git show --stat HEAD~1
commit db44b0610fb6e017a6e6d6760543cf7bd43081b2
Author: Ada Lovelace <ada@example.com>
Date: Wed Nov 11 10:00:00 2026 +0300
Document discounts in README
README.md | 2 ++
1 file changed, 2 insertions(+)
$ git show HEAD~3:src/books.js
export const books = [
{ id: 1, title: "Dune", price: 12.5 },
{ id: 2, title: "Neuromancer", price: 9.99 },
{ id: 3, title: "The Hobbit", price: 11 },
];
HEAD~3:src/books.js, "HEAD'den üç commit önceki snapshot'taki src/books.js" demek. Neuromancer'ın eski fiyatı 9.99'u orada görüyoruz. Bir dosyanın eski hâline bakmak için hiçbir şeyi geri almana gerek yok; working tree'ye dokunmadan okursun.
git blame: Bu Satırı Kim, Ne Zaman Yazdı?
git blame bir dosyanın her satırının yanına, o satırı en son değiştiren commit'i yazar:
$ git blame src/cart.js
fae44540 (Ada Lovelace 2026-11-07 10:01:00 +0300 1) import { books } from "./books.js";
fae44540 (Ada Lovelace 2026-11-07 10:01:00 +0300 2)
fae44540 (Ada Lovelace 2026-11-07 10:01:00 +0300 3) export function addToCart(cart, bookId) {
fae44540 (Ada Lovelace 2026-11-07 10:01:00 +0300 4) const book = books.find((b) => b.id === bookId);
fae44540 (Ada Lovelace 2026-11-07 10:01:00 +0300 5) return book ? [...cart, book] : cart;
fae44540 (Ada Lovelace 2026-11-07 10:01:00 +0300 6) }
e3ef4186 (Ada Lovelace 2026-11-07 10:02:00 +0300 7)
e3ef4186 (Ada Lovelace 2026-11-07 10:02:00 +0300 8) export function cartTotal(cart) {
b9d0ac5b (Alan Turing 2026-11-10 10:00:00 +0300 9) const total = cart.reduce((sum, book) => sum + book.price, 0);
b9d0ac5b (Alan Turing 2026-11-10 10:00:00 +0300 10) return Math.round(total * 100) / 100;
e3ef4186 (Ada Lovelace 2026-11-07 10:02:00 +0300 11) }
f1f60685 (Alan Turing 2026-11-09 10:00:00 +0300 12)
f1f60685 (Alan Turing 2026-11-09 10:00:00 +0300 13) export function applyDiscount(total, percent) {
f1f60685 (Alan Turing 2026-11-09 10:00:00 +0300 14) return total - (total * percent) / 100;
f1f60685 (Alan Turing 2026-11-09 10:00:00 +0300 15) }
Her satırda commit'in kısa hash'i, yazar, tarih ve satır numarası var. Dosyanın üç farklı dönemi görünüyor: Ada'nın ilk sepet kodu, Ada'nın eklediği cartTotal ve Alan'ın yuvarlama düzeltmesiyle indirim fonksiyonu. 9 ve 10. satırlar Alan'ın, ama aynı fonksiyonun 8 ve 11. satırları hâlâ Ada'nın commit'inden. Büyük dosyalarda -L ile aralığı daraltırsın:
$ git blame -L 8,11 src/cart.js
e3ef4186 (Ada Lovelace 2026-11-07 10:02:00 +0300 8) export function cartTotal(cart) {
b9d0ac5b (Alan Turing 2026-11-10 10:00:00 +0300 9) const total = cart.reduce((sum, book) => sum + book.price, 0);
b9d0ac5b (Alan Turing 2026-11-10 10:00:00 +0300 10) return Math.round(total * 100) / 100;
e3ef4186 (Ada Lovelace 2026-11-07 10:02:00 +0300 11) }
$ git blame -L '/function applyDiscount/,+3' src/cart.js
f1f60685 (Alan Turing 2026-11-09 10:00:00 +0300 13) export function applyDiscount(total, percent) {
f1f60685 (Alan Turing 2026-11-09 10:00:00 +0300 14) return total - (total * percent) / 100;
f1f60685 (Alan Turing 2026-11-09 10:00:00 +0300 15) }
$ git blame -s -L 1,3 src/books.js
^29f27c8 1) export const books = [
^29f27c8 2) { id: 1, title: "Dune", price: 12.5 },
8b5e66ca 3) { id: 2, title: "Neuromancer", price: 8.99 },
-L satır numarası alabildiği gibi bir düzenli ifade de alabilir: '/function applyDiscount/,+3', "bu metnin geçtiği satırdan başlayarak üç satır" demek; dosyaya satır eklendikçe numaralar kaysa da çalışır. -s yazar ve tarihi gizleyip yalnızca hash'i bırakır. Hash'in önündeki ^ işareti, o satırın repo'nun ilk commit'inden beri hiç değişmediğini söylüyor.
İsmi biraz suçlayıcı olsa da git blame birini suçlamak için değil, bağlam bulmak içindir. Tipik akış şu: tuhaf bir satır görürsün, git blame ile commit'ini bulursun, git show ile o commit'in mesajını ve diğer değişikliklerini okursun. 9. satırın neden böyle yazıldığını b9d0ac5'in mesajındaki "22.490000000000002" açıklıyor. İyi commit mesajı yazmanın karşılığını en çok bu anda alırsın.
Alias'lar
Bu yazıdaki komutların bazıları uzun. Sık kullandıklarına kısa bir isim verebilirsin:
$ git config set --global alias.lg "log --oneline --graph --decorate --all"
$ git lg -3
* 8b5e66c (HEAD -> main) Lower the price of Neuromancer
* db44b06 Document discounts in README
* b9d0ac5 Fix rounding in cartTotal
# Klasik biçim de aynı işi yapar
$ git config --global alias.st "status -s"
# README.md'ye bir satır ekledikten sonra
$ git st
M README.md
git lg artık git log --oneline --graph --decorate --all demek; arkasına yazdığın -3 gibi seçenekler de alias'ın sonuna eklenir. Alias'lar diğer ayarlar gibi ~/.gitconfig'te [alias] bölümünde durur. Yeni biçimle yazılmış alias.lg ve eski biçimle yazılmış alias.st arasında hiçbir fark yok. Tanımladığın alias'ları listelemek için:
$ git config get --all --show-names --regexp "^alias\."
alias.lg log --oneline --graph --decorate --all
alias.st status -s
Alias'ı abartmamak lazım. Başka birinin makinesinde ya da bir CI sunucusunda senin alias'ların yoktur; komutların uzun hâlini de bilmeye devam et.
Sık Düşülen Tuzaklar
İlk tuzak, açılıştaki soru: -S'i metin arama sanmak. -S geçme sayısının değiştiği commit'leri bulur, satırın içeriğinin değiştiği commit'leri değil. "Bu satıra kim dokundu?" diye soruyorsan -G ya da git blame daha doğru araç.
İkincisi, --since'e saatsiz tarih vermek. Git eksik saati komutu çalıştırdığın andan tamamlar. Gün sınırı önemliyse saati de yaz: --since="2026-11-10 00:00".
Üçüncüsü, rename'den sonra git log -- dosya'nın geçmişin bir kısmını göstermesine şaşırmak. Rename edilmiş bir dosyanın bütün geçmişi için --follow ekle.
Dördüncüsü, git blame'in gösterdiği commit'i satırın "yazıldığı" commit sanmak. Blame, satırı en son değiştiren commit'i gösterir. Biri dosyanın girintisini düzelttiyse bütün satırlar onun adına görünür; böyle durumlarda -w boşluk değişikliklerini yok sayar.
Küçük Bir Deneme
★☆☆ Kendi repo'nda git log --oneline, git log --stat -2 ve git log -p -1 çıktılarını karşılaştır. Sonra yalnızca senin commit'lerini gösteren bir --author filtresi yaz.
★★☆ src/books.js'te bir kitabın fiyatını değiştirip commit'le. O kitabın adıyla önce -S, sonra -G kullanarak arama yap ve hangisinin senin commit'ini bulduğunu açıkla.
★★★ Kendine bir git hist alias'ı tanımla: kısa hash, yazar tarihi (--date=short), yazar adı ve özet satırını gösteren bir --format ile --graph kullansın. Sonra git blame ile src/cart.js'te bir satır seç, commit'ini bul ve git show ile o commit'in neden yapıldığını oku.
Bu yazıda geçmişteki değişikliklere baktık. Bir sonraki yazıda değişiklikleri karşılaştırmayı derinleştiriyoruz: git diff ile working tree, staging area ve commit'ler arasındaki farklar, --staged, iki commit arasında A..B ile A...B farkı, --stat, --word-diff, --name-only ve --merge-base.