Git katmanı
Depo kontrolleri, commit listesi, diff'ler, blob okuma, geliştirici kimliklerinin birleştirilmesi
Tüm Git erişimi src/git/ içindedir. Her komut execFile("git", args, { cwd: root }) üzerinden çalışır. Arada bir kabuk (shell) yoktur; bu yüzden boşluk veya özel karakter içeren yollar güvenlidir. Windows'ta execFile, git → git.exe çözümlemesini yapar.
CleanLens'in çalıştırdığı komutlar
| Komut | Yer | Amaç |
|---|---|---|
git rev-parse --is-inside-work-tree | gitService.ts | Klasör bir depo mu? |
git rev-parse HEAD | gitService.ts | En az bir commit'i var mı? |
git log --no-merges --format=%aN|%aE|%aI | gitService.ts | Her commit'in yazar adı, e-postası, tarihi → geliştirici listesi |
git log --no-merges --format=%H␟%P␟%aN␟%aE␟%aI [--since=…] [-n N] | commitHistory.ts | Yeniden oynatılacak commit'ler |
git diff --no-color --unified=0 -w -M -C --diff-filter=ACDMRT <parent> <commit> | diffService.ts | Değişen dosyalar, satır aralıkları, blob kimlikleri — commit başına tek çağrı |
git cat-file --batch | diffService.ts | Bir commit'in ihtiyaç duyduğu tüm blob'ların içeriği — commit başına tek çağrı |
git show <sha> | diffService.ts | Toplu okuma başarısız olursa tek bir blob için yedek yol |
%aN ve %aE, .mailmap dosyasını uygular; bu yüzden depodaki bir .mailmap dosyası, kimlikleri Git düzeyinde düzeltmenin en basit yoludur.
gitService.ts
GitService üç metoda sahiptir:
isRepository()→ herhangi bir hatadafalse.hasCommits()→HEADçözümlenemezse (boş depo)false.listCommits()→ birleştirme olmayan tüm commit'ler içinRawCommit[](authorName,authorEmail,authorDate). Yalnızca geliştirici listesini ve etkinlik istatistiklerini oluşturmak için kullanılır.maxCommitsile sınırlı değildir.
commitHistory.ts — hangi commit'ler yeniden oynatılır
listCommitsDetailed(cwd, { maxCommits, since }):
- Her zaman
--no-merges. Birleştirme commit'leri kendilerine ait yeni kod eklemez; içerikleri birleştirilen commit'ler tarafından kapsanır. since→--since=<value>(Git'in kabul ettiği her değer:2026-01-01,"6 months ago", …).maxCommits > 0→-n <maxCommits>(en yeni N).0veyasinceolmadan ayarlanmamış → tüm geçmiş.- Sonuç en eskiden başlayacak şekilde ters çevrilir, böylece motor zamanda ileri doğru yürüyebilir.
- Her commit'in
parentslistesi vardır. Kök commit'in ebeveyni yoktur ve Git'in boş ağacıyla (4b825dc6…) karşılaştırılır.
Varsayılan pencere en yeni 500 commit'tir (analyzeRepository.ts içinde DEFAULT_MAX_COMMITS).
diffService.ts — bir commit'te ne değişti
commitChanges(parent, commit)
Tek bir git diff çalıştırır ve bunu CommitFileChange[] olarak ayrıştırır:
| Alan | Anlamı |
|---|---|
status | added, modified, deleted, renamed, copied |
path / oldPath | Sonraki / önceki yol (yeniden adlandırma ve kopyalamalar) |
blobBefore / blobAfter | Blob kimlikleri; dosya o tarafta yoksa null |
added | Commit'in eklediği veya değiştirdiği satır aralıkları (sonraki dosyada) |
removed | Commit'in sildiği veya değiştirdiği satır aralıkları (önceki dosyada) |
binary | İkili dosya — atlanır |
Bayraklar adalet için seçilmiştir:
--unified=0— bağlam satırı yok; böylece hunk başlıkları değişen aralıkları tam olarak verir.-w— boşlukları yok say. Yeniden biçimlendirme (girinti, satır sonu boşlukları) satır değişikliği sayılmaz, dolayısıyla sorumluluğu aktaramaz.-M -C— yeniden adlandırma ve kopyalamaları tespit et. Bir dosyayı taşımak, taşıyanı içeriğinin yazarı yapmaz.--diff-filter=ACDMRT— eklenen, kopyalanan, silinen, değiştirilen, yeniden adlandırılan, tipi değişen.
Ayrıştırıcı diff --git, new file mode, deleted file mode, rename from/to, copy from/to, index <a>..<b>, ---/+++ ve @@ hunk başlıklarını okur. Metni \r?\n ile böler; bu yüzden Windows Git'inin CRLF çıktısı doğru ayrıştırılır.
blobs(shas)
Birçok blob'u tek bir git cat-file --batch süreciyle okur: tüm kimlikleri stdin'e yazar ve ham baytlardan <sha> blob <size>\n<content>\n kayıtlarını ayrıştırır. Bir şey yanlış görünürse (eksik kayıt, hatalı boyut), sonucu atar ve her blob için git show <sha> yoluna döner. Bu yol daha yavaştır ama her zaman doğrudur.
Yardımcılar
rangeLineCount(ranges)— aralıklardaki toplam satır (analiz edilen satırlar için kullanılır).lineInRanges(line, ranges),spanOverlapsRanges(start, end, ranges)— atama güvenine karar vermek için kullanılır.
contributors.ts — geliştiriciler kimler
aggregateContributors(commits, { identities, mergeSameName }) commit'leri geliştiricilere dönüştürür.
1. adım — e-postaya göre gruplama
Her commit küçük harfe çevrilmiş e-postasına göre gruplanır. E-posta yapılandırmadaki developers listesinde varsa, bunun yerine o girdinin grubuna sabitlenir; böylece listelenen tüm e-postalar tek bir kişi olur.
CleanLens her grup için şunları izler: görülen adlar, e-postalar, aktif günler (commit içeren farklı UTC takvim günleri), ilk ve son commit tarihleri ve commit sayısı. Birincil ad, gruptaki en eski commit'teki addır.
2. adım — olası kopyaları birleştirme (varsayılan açık)
mergeSameNameAuthors false değilse, herhangi bir birleştirme anahtarını paylaşan gruplar birleştirilir (union-find):
| Anahtar | Neyden oluşturulur | Yakaladığı örnek |
|---|---|---|
exact: | Görünen ad; kırpılmış, küçük harfe çevrilmiş, boşlukları daraltılmış | İki farklı e-postada Ayman Khalil |
name: | Harf/rakam olmayan her şey silinmiş ve sondaki rakamlar atılmış ad; yalnızca ≥ 5 karakterse | MUSAALAHMED4 ↔ MUSAALAHMED ↔ musa alahmed |
mail: | E-posta tanıtıcısı: yerel kısımdaki son + işaretinden sonraki metin veya yerel kısmın tamamı; yalnızca ≥ 3 karakterse ve genel değilse | ayman@work.com ↔ ayman@gmail.com; 1234+ayman@users.noreply.github.com |
Yanlış birleştirmelere karşı korumalar:
- 5 karakterden kısa daraltılmış adlar yok sayılır (
user1/user2,AnasileAnas Daas). - Genel tanıtıcılar yok sayılır:
noreply,no-reply,git,github,gitlab,admin,dev,me,hello,info,contact,mail,email,user,users,name,test.
3. adım — etiket
- Yapılandırmadaki
displayNameher zaman kazanır. - Tek adı olan grup o adı kullanır.
- Farklı adları birleştiren grup hepsini, en eskisi önce olacak şekilde gösterir:
"Primary Name - Other Name".
Geliştiriciler commit sayısına göre sıralanır ve bu sırayla dev-1, dev-2, … kimliklerini alır. Kimlikler yalnızca tek bir rapor içinde sabittir.
blameService.ts (eski)
BlameService ve parsePorcelain(), git blame --line-porcelain -w -M çıktısını ayrıştırır. Önceki "HEAD blame" motoruna aittirler ve artık işlem hattında kullanılmazlar. Testler onları kapsadığı ve gelecekteki özellikler için yararlı oldukları için duruyorlar.
Bu katmanı özelleştirmek
- Kimlikleri birleştirmek → yapılandırmada
developersveya bir.mailmap(11 — Özelleştirme kılavuzu). - Yeniden oynatma penceresini değiştirmek →
analysis.maxCommits,analysis.since,--full-history. - Otomatik birleştirmeyi kapatmak →
mergeSameNameAuthors: false.