İyi olan Ben Jackson'ın cevabını genişletmek için gelin asıl soruya yakından bakalım. ( Tip soruları neden rahatsız ettiğine dair cevabına bakın ; bu daha çok neler olup bittiğiyle ilgili .)
Sürüm kontrolünde yeniyim ve "taahhüt etmenin" aslında üzerinde çalıştığınız şeyin yeni "mevcut" sürümünü güncellerken bir yedekleme oluşturmak olduğunu anlıyorum.
Bu tam olarak doğru değil. Yedeklemeler ve sürüm kontrolü kesinlikle birbiriyle ilişkilidir - bir dereceye kadar fikir meselesi olan bazı şeylere tam olarak ne kadar bağlıdır - ancak, yalnızca niyet açısından kesinlikle bazı farklılıklar vardır: Yedekler tipik olarak olağanüstü durumdan kurtarma için tasarlanmıştır (makine arızaları, yangın tahripleri tüm depolama ortamları dahil tüm bina, vb.). Sürüm kontrolü tipik olarak daha hassas etkileşimler için tasarlanmıştır ve yedeklemelerin yapmadığı özellikler sunar. Yedekler genellikle bir süre saklanır ve ardından "çok eski" olarak atılır: önemli olan tek şey daha yeni bir yedeklemedir. Sürüm kontrolü normalde her kaydedilmiş sürümü sonsuza kadar kaydeder.
Anlamadığım şey, sahnelemenin pratik açıdan ne olduğu. Sadece ismen var olan bir şeyi sahnelemek mi yoksa bir amaca mı hizmet ediyor? Taahhüt ettiğin zaman, her şeyi yine de yapacak, değil mi?
Evet ve hayır. Git'in buradaki tasarımı biraz tuhaf. Sürüm kontrol sistemleri var var yok ayrı bir evreleme adımı gerektirir. Örneğin, aksi takdirde kullanım açısından Git gibi bir çok şey var Mercurial, gelmez ayrı gerektiren hg addçok ilki bu tanıtır yepyeni bir dosya ötesinde, adım. Mercurial ile, hgbazı commit'i seçen komutu kullanırsınız , sonra işinizi yaparsınız, sonra koşarsınız hg commitve bitirdiniz. Git ile 1'i kullanırsın git checkout, sonra işini yaparsın, sonra koşarsın ve sonra . Neden ekstra adım?git addgit commitgit add
Buradaki sır, Git'in çeşitli şekillerde dizini veya hazırlık alanını veya bazen - bu günlerde nadiren - önbellek adını verdiği şeydir . Bunların hepsi aynı şeyin isimleri.
Düzenleme: Terminolojiyi karıştırdığımı düşünüyorum. "Hazırlanmış" bir dosya, "izlenen" bir dosya ile aynı şey midir?
Hayır, ama bunlar birbiriyle alakalı. Bir izlenen dosya seyahatseverlerin Git dizinine var biridir. Endeksi doğru bir şekilde anlamak için, taahhütleri anlamakla başlamak iyidir.
Git sürüm 2.23'ten beri, git switchyerine kullanabilirsiniz git checkout. Bu özel durum için, bu iki komut tamamen aynı şeyi yapar. Yeni komut var çünkü git checkoutçok fazla şeyle aşırı doldurulmuş; iki ayrı komutlar içine bölünmüş, var git switchve git restoreGit kullanımı daha kolay ve daha güvenli hale getirmek.
Kaydetme
Git'te bir işlem, Git'in bildiği her dosyanın tam bir anlık görüntüsünü kaydeder . (Git hangi dosyaları biliyor? Bunu sonraki bölümde göreceğiz.) Bu anlık görüntüler özel, salt okunur, yalnızca Git, sıkıştırılmış ve çoğaltılmış bir biçimde saklanır, genel olarak yalnızca Git'in okuyabilir . (Orada her fazla şeyler daha kesinleştirme var sadece bu anlık ama biz burada kapsayacak kadar.)
Tekilleştirme, alan konusunda yardımcı olur: normalde yalnızca birkaç dosyayı değiştiririz, ardından yeni bir işlem gerçekleştiririz. Yani çoğu bir dosyaların önceki tamamlama dosyaları işlemek büyük benzerlik gösteriyor. Bu dosyaları doğrudan yeniden kullanarak, Git çok fazla alan kazandırır: Yalnızca bir dosyaya dokunursak, yeni işleme yalnızca bir yeni kopya için yer kaplar . O zaman bile sıkıştırılır - bazen çok sıkıştırılır, ancak bu daha sonra olur - böylece bir .gitdizin, normal günlük dosyalara genişletildiğinde, içerdiği dosyalardan daha küçük olabilir. Tekilleştirme güvenlidir çünkü kaydedilen dosyalar her zaman dondurulur. Kimse değiştiremez, bu yüzden taahhütlerin birbirlerinin kopyalarına bağlı olması güvenlidir.
Saklanan dosyalar bu özel, tüm zamanlar için dondurulmuş, yalnızca Git biçiminde olduğundan, Git her dosyayı sıradan bir günlük kopyaya genişletmek zorundadır . Bu sıradan kopya Git'in kopyası değildir : istediğiniz gibi yapabileceğiniz sizin kopyanızdır. Git bunu söylediğinizde bunlara yazacaktır, böylece üzerinde çalışmanız gereken kopyalarınız olacaktır. Bu kullanılabilir kopyalar çalışma ağacınızda veya çalışma ağacınızda bulunur .
Bunun anlamı, belirli bir kaydı kontrol ettiğinizde , her dosyanın otomatik olarak iki kopyası vardır :
Git'in geçerli işlemede tüm zamanlar için dondurulmuş, Git uyumlu bir kopyası vardır . Bu kopyayı değiştiremezsiniz (elbette farklı bir kayıt seçebilir veya yeni bir kayıt yapabilirsiniz).
Çalışma ağacınızda normal formatta bir kopyanız var. Bilgisayarınızdaki komutlardan herhangi birini kullanarak bunun için istediğiniz her şeyi yapabilirsiniz.
Diğer sürüm kontrol sistemleri (yukarıda bahsedildiği üzere Mercurial dahil) bu iki kopya ile burada durmaktadır. Sadece çalışma ağacı kopyanızı değiştirirsiniz, sonra taahhüt edersiniz. Git ... yapmaz.
İçerik
Bu iki kopya arasında Git , her dosyanın üçüncü bir kopyasını 2 saklar . Bu üçüncü kopya dondurulmuş olduğu biçiminde , ancak taahhüt dondurulmuş kopya aksine, olabilir değiştirin. Değiştirmek için kullanırsınız git add.
git addKomut aracı dosyanın dizin kopyalama işi ağacı kopyasını maç yapmak . Yani Git'e şunu söylüyorsunuz: Güncellenmiş çalışma ağacı kopyamı sıkıştırarak, kopyasını kaldırarak ve yeni bir işlemde dondurulmaya hazır hale getirerek şimdi dizinde bulunan donmuş formatlı, kopyası kaldırılmış kopyayı değiştirin. Eğer varsa yok kullanmak git add, endeks hala akımından dondurulmuş formatlı kopyası taahhüt tutar.
Eğer çalıştırdığınızda git commit, Git endeksinde ne olursa olsun yukarı paketler sağa sonra yeni anlık olarak kullanılmak üzere. Zaten dondurulmuş formatta olduğu ve önceden kopyaları kaldırıldığı için Git'in çok fazla ek iş yapması gerekmez.
Bu aynı zamanda izlenmeyen dosyaların ne hakkında olduğunu da açıklar . Bir izlenmeyen dosyası çalışma ağacında ama bir dosya değil seyahatseverlerin Git dizininde şu anda . Dosyanın bu durumda nasıl sarıldığı önemli değil. Belki de bilgisayarınızda başka bir yerden çalışma ağacınıza kopyaladınız. Belki burada yeni yaratmışsınızdır. Belki orada oldu seyahatseverlerin Git dizinine bir kopyası, ancak birlikte bu kopyayı kaldırıldı git rm --cached. Öyle ya da böyle, burada çalışma ağacınızda bir kopya var, ancak Git'in dizininde bir kopya yok. Şimdi yeni bir kayıt yaparsanız, bu dosya yeni kayıtta olmayacaktır .
git checkoutBaşlangıçta , teslim aldığınız işlemden Git'in dizinini doldurduğunu unutmayın . Böylece dizin, commit ile eşleşmeye başlar. Git ayrıca çalışma ağacınızı bu aynı kaynaktan doldurur. Yani başlangıçta üçü de eşleşiyor. Çalışma ağacınızdaki dosyaları değiştirdiğinizde git add, şimdi dizin ve çalışma ağacınız eşleşiyor. Sonra çalıştırırsınız git commitve Git dizinden yeni bir işlem yapar ve şimdi üçü de yeniden eşleşir.
Git, dizinden yeni işlemeler yaptığı için işleri şu şekilde koyabiliriz: Git'in dizini, yapmayı planladığınız bir sonraki işlemi içerir . Bu, Git'in indeksinin çakışan bir birleştirme sırasında üstlendiği genişletilmiş rolü görmezden geliyor, ancak bunu şimdilik görmezden gelmek istiyoruz. :-)
Hepsi bu kadar - ama yine de oldukça karmaşık! Özellikle zor çünkü Git'in dizininde tam olarak ne olduğunu görmenin kolay bir yolu yok. 3 Ama olan oldukça kullanışlı bir şekilde devam ve bu komut videoyu gösteren bir Git komutu git status.
2 Teknik olarak, bu aslında bir kopya değil . Bunun yerine, Git-ified dosyasına, önceden çoğaltılmış dosyaya ve her şeye bir referanstır . Burada ayrıca kip, dosya adı, aşama numarası ve Git'in hızlı gitmesini sağlayacak bazı önbellek verileri gibi daha fazla şey var. Ancak Git'in bazı düşük seviyeli komutlarıyla çalışmaya başlamadığınız sürece - git ls-files --stageve git update-indexözellikle - bir kopya olarak düşünebilirsiniz.
3git ls-files --stage komut size seyahatseverlerin Git dizinine her dosya adlarını ve evreleme numaralarını gösterir, ancak genellikle bu çok yararlı zaten değildir.
git status
git statusKomut aslında iki ayrı çalıştırarak çalışır git diffsizin için komutlar (ve aynı zamanda sende hangi dal söylüyorum gibi bazı diğer yararlı şeyler yapıyor).
İlki git diff, her zaman donmuş olan mevcut commit'i Git'in indeksinde olanla karşılaştırır. Aynı olan dosyalar için Git hiçbir şey söylemeyecektir. Olan dosyalar için farklı , Git bu dosya olduğunu söyleyecektir taahhüt için sahnelenen . Bu yok işlerlerse dosyalar-yepyeni içerir sub.pyonun içinde, ancak endeks vermez var sub.pyonun içinde, o zaman bu dosya katma ve (ve vardır) herhangi kaldırılan dosyaları, işlemek ama olmayan içinde endeks artık ( git rm, belki).
İkincisi git diff, Git'in indeksindeki tüm dosyaları çalışma ağacınızdaki dosyalarla karşılaştırır. Aynı olan dosyalar için Git hiçbir şey söylemiyor. Olan dosyalar için farklı , Git bu dosya olduğunu söyleyecektir taahhüt için sahnelenen değil . İlk fark aksine, bu özel liste değil tüm yeni olan dosyaları içerir: Dosya varsa untrackedişinizi ağacının mevcut fakat değil seyahatseverlerin Git dizinine, Git sadece listesine ekler izlenmeyen dosyaları . 4
Sonunda, bu izlenmeyen dosyaları bir listede biriktirmiş olmak, bu dosyaların adlarını da git statusduyuracaktır , ancak özel bir istisna vardır: bir dosyanın adı bir dosyada listeleniyorsa , bu son listeyi bastırır. İzlenen bir dosyayı (Git'in dizininde bulunan) burada listelemenin hiçbir etkisi olmadığını unutmayın : dosya dizindedir, bu nedenle içinde listelense bile karşılaştırılır ve işlenir . Yok sayma dosyası yalnızca "izlenmeyen dosya" şikayetlerini bastırır. 5.gitignore.gitignore.gitignore
4git status - git status -s--' nin kısa versiyonunu kullanırken izlenmeyen dosyalar birbirinden ayrı değildir, ancak prensip aynıdır. Dosyaları bu şekilde biriktirmek git status, bazen sadece bir dizin adı yazdırarak bir grup izlenmemiş dosyanın adlarını özetlemeye de izin verir . Tam listeyi almak için git status -uallveya kullanın git status -u.
5 Bir dosyayı listelemek, en- masse'nin izlenmeyen dosya gibi birçok dosya işlemini eklemesinigit add . veya git add *bu dosyayı atlamasını sağlar. git add --forceNormalde atlanacak bir dosya eklemek için kullanabileceğiniz için bu kısım biraz daha karmaşık hale gelir . Diğer bazı normalde küçük özel durumlar vardır, bunların hepsi buna eklenir: dosya .gitignoredaha düzgün çağrılabilir .git-do-not-complain-about-these-untracked-files-and-do-not-auto-add-themveya eşit derecede hantal bir şey olabilir . Ama bu çok saçma, bu yüzden .gitignoreöyle.
git add -u, git commit -aVb
Burada bilmeniz gereken birkaç kullanışlı kısayol vardır:
git add .tüm güncellenmiş dosyaları geçerli dizine ve herhangi bir alt dizine ekler . Buna saygı duyulmaktadır .gitignore, bu nedenle, şu anda izlenmeyen bir dosya hakkında şikayet git statusedilmemişse, otomatik olarak eklenmeyecektir.
git add -utüm güncellenmiş dosyaları çalışma ağacınızın herhangi bir yerine otomatik olarak ekleyecektir . 6 Bu yalnızca izlenen dosyaları etkiler . Eğer ettik eğer Not kaldırıldı çalışma ağacı kopyasını bu (çok dizin kopyasını kaldıracaktır git addbu onun bir parçası olarak gelmez marka indeks çalışması ağacı maç şeyi).
git add -Agit add .çalışma ağacınızın en üst seviyesinden koşmak gibidir (ancak dipnot 6'ya bakın).
Bunların yanında, Çalıştırabileceğiniz git commit -akabaca eşdeğer olan 7 çalışan git add -uve daha sonra git commit. Yani, bu size Mercurial'da uygun olan davranışı getirir.
Genel olarak git commit -amodele karşı tavsiyede bulunuyorum : git statusSıklıkla kullanmanın daha iyi olduğunu görüyorum , çıktıya yakından bakın ve durum beklediğiniz gibi değilse, neden böyle olduğunu anlayın. Kullanarak git commit -a, yanlışlıkla bir dosyayı değiştirmek ve taahhüt etmek istemediğiniz bir değişikliği gerçekleştirmek çok kolaydır. Ancak bu çoğunlukla bir zevk / fikir meselesidir.
6 Git sürümünüz Git 2.0'dan önceyse, burada dikkatli olun: git add -uyalnızca geçerli dizin ve alt dizinlerde çalışır, bu nedenle önce çalışma ağacınızın en üst düzeyine tırmanmanız gerekir. git add -ASeçenek benzer bir sorun vardır.
7 Kabaca eşdeğer diyorum çünkü git commit -aaslında fazladan bir dizin oluşturarak ve bu diğer dizini commit yapmak için kullanarak çalışır. Kaydetme işe yararsa , yapmakla aynı etkiyi elde edersiniz git add -u && git commit. İşlersen değil yapmak eser varsa-Git o zaman o-hayır dosyalar vardır yapabileceğiniz birçok yollardan herhangi taahhüt atlamak git addGit geçici ekstra endeksi dışarı atar ve ana dizini kullanarak geri gider, çünkü sonradan -ed .
Burada kullanırsanız ortaya çıkan ek komplikasyonlar git commit --onlyvar. Bu durumda Git, üçüncü bir dizin oluşturur ve işler çok karmaşık hale gelir, özellikle de önceden kesinleştirme kancaları kullanırsanız. Bu, ayrı git addişlemler kullanmak için başka bir nedendir .