Untuk memperluas jawaban Ben Jackson , yang bagus, mari kita lihat pertanyaan aslinya dengan saksama. (Lihat jawabannya untuk pertanyaan tipe mengapa repot ; ini lebih tentang apa yang sedang terjadi .)
Saya baru mengenal kontrol versi dan saya memahami bahwa "melakukan" pada dasarnya adalah membuat cadangan sambil memperbarui versi 'terkini' dari apa yang Anda kerjakan.
Ini tidak cukup benar. Cadangan dan dan kontrol versi tentu saja terkait — seberapa kuatnya bergantung pada beberapa hal yang sampai batas tertentu merupakan masalah opini — tetapi tentu ada beberapa perbedaan, jika hanya dalam maksud: Cadangan biasanya dirancang untuk pemulihan bencana (mesin gagal, api menghancurkan seluruh gedung termasuk semua media penyimpanan, dll.). Kontrol versi biasanya dirancang untuk interaksi yang lebih mendetail dan menawarkan fitur yang tidak dapat dilakukan backup. Cadangan biasanya disimpan untuk beberapa waktu, kemudian dibuang sebagai "terlalu lama": yang terpenting adalah cadangan yang lebih baru. Kontrol versi biasanya menyimpan setiap versi yang dikomit selamanya.
Apa yang saya tidak mengerti adalah apa pementasan adalah dari perspektif praktis. Apakah pementasan adalah sesuatu yang hanya ada dalam nama atau apakah itu memiliki tujuan? Ketika Anda berkomitmen, bagaimanapun juga itu akan melakukan segalanya, bukan?
Iya dan tidak. Desain Git di sini agak aneh. Ada sistem kontrol versi yang tidak memerlukan langkah penahapan terpisah. Misalnya, Mercurial, yang sangat mirip dengan Git dalam hal penggunaan, tidak memerlukan hg addlangkah terpisah , di luar langkah pertama yang memperkenalkan file baru. Dengan Mercurial, Anda menggunakan hgperintah yang memilih beberapa komit, lalu Anda melakukan pekerjaan Anda, lalu Anda menjalankan hg commit, dan selesai. Dengan Git, Anda menggunakan git checkout, 1 lalu Anda melakukan pekerjaan Anda, lalu Anda jalankan git add, dan kemudian git commit. Mengapa perlu git addlangkah ekstra ?
Rahasianya di sini adalah apa yang disebut Git, dengan berbagai cara, indeks , atau area pementasan , atau kadang-kadang — jarang sekali saat ini — cache . Ini semua adalah nama untuk hal yang sama.
Sunting: Saya pikir saya mungkin membingungkan terminologi. Apakah file 'bertahap' sama dengan file 'terlacak'?
Tidak, tapi ini saling terkait. Sebuah dilacak file yang ada dalam indeks Git ini. Untuk memahami indeks dengan benar, sebaiknya mulai dengan memahami komit.
Sejak Git versi 2.23, Anda dapat menggunakan git switchbukan git checkout. Untuk kasus khusus ini, kedua perintah ini melakukan hal yang persis sama. Perintah baru ada karena git checkoutterlalu banyak diisi; mereka dibagi menjadi dua perintah terpisah, git switchdan git restore, untuk membuatnya lebih mudah dan lebih aman menggunakan Git.
Komit
Di Git, komit menyimpan cuplikan lengkap dari setiap file yang diketahui Git. (File mana yang diketahui Git? Kita akan melihatnya di bagian selanjutnya.) Snapshot ini disimpan dalam bentuk khusus, read-only, Git-only, terkompresi dan de-duplikasi, yang secara umum hanya Git sendiri yang dapat membaca . (Ada lebih banyak hal di setiap komit daripada hanya snapshot ini, tetapi hanya itu yang akan kita bahas di sini.)
De-duplikasi membantu dengan ruang: kami biasanya hanya mengubah beberapa file, lalu membuat komit baru. Jadi sebagian besar file dalam komit sebagian besar sama dengan file di komit sebelumnya. Dengan menggunakan kembali file tersebut secara langsung, Git menghemat banyak ruang: jika kita hanya menyentuh satu file, komit baru hanya membutuhkan ruang untuk satu salinan baru. Bahkan kemudian dikompresi — terkadang sangat terkompresi, meskipun ini benar-benar terjadi kemudian — sehingga .gitdirektori sebenarnya bisa lebih kecil dari file yang ada di dalamnya, setelah diperluas ke file normal sehari-hari. De-duplikasi aman karena file yang dikomit akan dibekukan sepanjang waktu. Tidak ada yang bisa mengubahnya, jadi aman untuk komitmen bergantung pada salinan satu sama lain.
Karena file yang disimpan dalam format khusus Git yang dibekukan untuk sepanjang masa ini, Git harus mengembangkan setiap file menjadi salinan biasa sehari-hari. Salinan biasa ini bukanlah salinan Git : ini adalah salinan Anda , lakukan sesuka Anda. Git hanya akan menuliskannya ketika Anda menyuruhnya, sehingga Anda memiliki salinan untuk dikerjakan. Salinan yang dapat digunakan ini ada di pohon kerja atau pohon kerja Anda .
Artinya adalah ketika Anda memeriksa beberapa komit tertentu, otomatis ada dua salinan dari setiap file:
Git memiliki salinan Git-ified yang dibekukan untuk semua waktu dalam komit saat ini . Anda tidak dapat mengubah salinan ini (meskipun Anda tentu saja dapat memilih komit yang berbeda, atau membuat komit baru).
Anda memiliki, di pohon kerja Anda, salinan format normal. Anda dapat melakukan apa pun yang Anda inginkan, menggunakan perintah apa pun di komputer Anda.
Sistem kontrol versi lain (termasuk Mercurial seperti yang disebutkan di atas) berhenti di sini, dengan dua salinan ini. Anda cukup mengubah salinan pohon kerja Anda, lalu komit. Git ... tidak.
Indeks
Di antara dua salinan ini, Git menyimpan salinan ketiga 2 dari setiap file. Salinan ketiga ini dalam format beku , tetapi tidak seperti salinan beku dalam komit, Anda dapat mengubahnya. Untuk mengubahnya, Anda menggunakan git add.
The git addberarti perintah membuat salinan indeks file sesuai dengan copy pekerjaan-pohon . Artinya, Anda memberi tahu Git: Ganti salinan beku-format, de-duplikat yang ada di indeks sekarang, dengan mengompresi salinan work-tree saya yang telah diperbarui, menghapus duplikatnya, dan menyiapkannya untuk dibekukan menjadi komit baru. Jika Anda tidak menggunakan git add, indeks masih menyimpan salinan format beku dari komit saat ini.
Ketika Anda menjalankan git commit, Git paket up apa yang ada di indeks saat itu untuk digunakan sebagai snapshot baru. Karena sudah dalam format beku, dan sudah diduplikasi sebelumnya, Git tidak perlu melakukan banyak pekerjaan ekstra.
Ini juga menjelaskan tentang file yang tidak terlacak . File yang tidak terlacak adalah file yang ada di pohon kerja Anda tetapi tidak ada dalam indeks Git sekarang . Tidak peduli bagaimana file itu berakhir dalam keadaan ini. Mungkin Anda menyalinnya dari tempat lain di komputer Anda, ke pohon kerja Anda. Mungkin Anda membuatnya segar di sini. Mungkin ada adalah salinan dalam indeks Git, tapi Anda dihapus copy bahwa dengan git rm --cached. Dengan satu atau lain cara, ada salinannya di sini di pohon kerja Anda, tetapi tidak ada salinannya di indeks Git. Jika Anda membuat komit baru sekarang, file itu tidak akan ada di komit baru.
Perhatikan bahwa git checkoutawalnya mengisi indeks Git dari komit yang Anda periksa. Jadi indeks mulai cocok dengan komit. Git juga mengisi pohon kerja Anda dari sumber yang sama ini. Jadi, awalnya, ketiganya cocok. Ketika Anda mengubah file di pohon kerja Anda dan git addmereka, sekarang indeks dan pohon kerja Anda cocok. Kemudian Anda menjalankan git commitdan Git membuat komit baru dari indeks, dan sekarang ketiganya cocok lagi.
Karena Git membuat komit baru dari indeks, kita dapat menjelaskannya sebagai berikut : Indeks Git memegang komit berikutnya yang Anda rencanakan. Ini mengabaikan peran yang diperluas yang diambil oleh indeks Git selama penggabungan yang berkonflik, tetapi kami ingin mengabaikannya untuk saat ini. :-)
Hanya itu saja — tetapi masih cukup rumit! Ini sangat rumit karena tidak ada cara mudah untuk melihat dengan tepat apa yang ada di indeks Git. 3 Tapi ada adalah perintah Git yang memberitahu Anda apa yang terjadi, dengan cara yang cukup berguna, dan perintah yang git status.
2 Secara teknis, ini sebenarnya bukan salinan sama sekali. Sebagai gantinya, ini adalah referensi ke file Git-ified, pra-duplikat dan semuanya. Ada lebih banyak hal di sini juga, seperti mode, nama file, nomor pementasan, dan beberapa data cache untuk membuat Git bekerja dengan cepat. Tetapi kecuali Anda mulai bekerja dengan beberapa perintah tingkat rendah Git — git ls-files --stagedan git update-indexkhususnya — Anda bisa menganggapnya sebagai salinan.
3 The git ls-files --stageperintah akan menampilkan nama dan nomor pementasan setiap file dalam indeks Git, tapi biasanya ini tidak pula sangat berguna.
git status
The git statusperintah benar-benar bekerja dengan menjalankan dua terpisah git diffperintah untuk Anda (dan juga melakukan beberapa hal yang berguna lainnya, seperti memberitahu Anda yang cabang Anda berada di).
Yang pertama git diffmembandingkan komit saat ini — yang, ingat, dibekukan sepanjang waktu — dengan apa pun yang ada di indeks Git. Untuk file yang sama , Git tidak akan mengatakan apa-apa. Untuk file yang berbeda , Git akan memberitahu Anda bahwa file ini dalam staging untuk komit . Ini termasuk semua file baru — jika komit tidak ada sub.pydi dalamnya, tetapi indeks ada di dalamnya, maka file ini ditambahkan — dan semua file yang dihapus, yang (dan sedang) di komit tetapi tidak ada sub.pydi dalamnya indeks lagi ( git rm, mungkin).
Yang kedua git diffmembandingkan semua file di indeks Git dengan file di pohon kerja Anda. Untuk file yang sama , Git tidak mengatakan apa-apa. Untuk file yang berbeda , Git akan memberitahu Anda bahwa file ini tidak dipentaskan untuk komit . Tidak seperti diff pertama, daftar khusus ini tidak menyertakan file yang semuanya baru: jika file tersebut untrackedada di work-tree Anda, tetapi tidak ada di indeks Git, Git hanya menambahkannya ke daftar file yang tidak terlacak . 4
Pada akhirnya, setelah akumulasi file-file yang tidak terlacak dalam daftar, git statusakan mengumumkan mereka nama-nama file juga, tapi ada pengecualian khusus: jika nama file terdaftar dalam .gitignoreberkas, yang menekan daftar terakhir ini. Perhatikan bahwa mencantumkan file terlacak — yang ada di indeks Git — .gitignoretidak berpengaruh di sini : file tersebut ada dalam indeks, sehingga dibandingkan, dan dikomit, meskipun terdaftar di .gitignore. File abaikan hanya menyembunyikan keluhan "file tidak terlacak". 5
4 Bila menggunakan versi pendek dari git status- git status -s-the file tidak terlacak tidak sebagai dipisahkan-out, tetapi prinsipnya adalah sama. Mengumpulkan file seperti ini juga memungkinkan git statusmeringkas banyak nama file yang tidak terlacak dengan hanya mencetak nama direktori, terkadang. Untuk mendapatkan daftar lengkapnya, gunakan git status -uallatau git status -u.
5 Mendaftar file juga membuat secara massal menambahkan banyak operasi file seperti git add .atau git add *melewati file yang tidak terlacak. Bagian ini menjadi sedikit lebih rumit, karena Anda dapat menggunakan git add --forceuntuk menambahkan file yang biasanya akan dilewati. Ada beberapa kasus khusus yang biasanya kecil, yang semuanya bertambah seperti ini: file tersebut .gitignoremungkin dipanggil dengan lebih tepat .git-do-not-complain-about-these-untracked-files-and-do-not-auto-add-thematau sesuatu yang sama beratnya. Tapi itu terlalu konyol, jadi .gitignorememang begitu .
git add -u,, git commit -adll
Ada beberapa pintasan praktis yang perlu diketahui di sini:
git add .akan menambahkan semua file yang diperbarui di direktori saat ini dan setiap sub-direktori. Hal ini berlaku .gitignore, jadi jika file yang saat ini tidak terlacak tidak dikeluhkan oleh git status, itu tidak akan ditambahkan secara otomatis.
git add -uakan otomatis menambahkan semua file yang diperbarui di mana saja di pohon kerja Anda . 6 Ini hanya mempengaruhi file yang dilacak . Perhatikan bahwa jika Anda telah menghapus salinan pohon kerja, ini juga akan menghapus salinan indeks ( git addlakukan ini sebagai bagian dari membuat indeks cocok dengan pohon kerja ).
git add -Aseperti berlari git add .dari tingkat teratas pohon kerja Anda (tapi lihat catatan kaki 6).
Selain itu, Anda dapat berlari git commit -a, yang kira-kira setara dengan 7 untuk berlari git add -ulalu git commit. Artinya, ini memberi Anda perilaku yang sama yang nyaman di Mercurial.
Saya biasanya menyarankan untuk tidak mengikuti git commit -apola: Saya menemukan bahwa lebih baik untuk git statussering menggunakan , melihat lebih dekat pada output , dan jika statusnya tidak seperti yang Anda harapkan, cari tahu mengapa demikian. Menggunakan git commit -a, terlalu mudah untuk secara tidak sengaja mengubah file dan melakukan perubahan yang tidak ingin Anda lakukan. Tapi ini sebagian besar masalah selera / pendapat.
6 Jika versi Git Anda mendahului Git 2.0, berhati-hatilah di sini: git add -uhanya berfungsi pada direktori dan sub-direktori saat ini, jadi Anda harus naik ke level teratas dari pohon kerja Anda terlebih dahulu. The git add -Apilihan memiliki masalah serupa.
7 Saya katakan kira-kira setara karena git commit -asebenarnya bekerja dengan membuat indeks tambahan, dan menggunakan indeks lain itu untuk melakukan komit. Jika komit berhasil , Anda mendapatkan efek yang sama seperti melakukan git add -u && git commit. Jika komit tidak berfungsi — jika Anda membuat Git melewati komit dengan salah satu dari banyak cara yang dapat Anda lakukan — maka tidak ada file yang di- git addberi setelahnya, karena Git membuang indeks tambahan sementara dan kembali menggunakan indeks utama .
Ada komplikasi tambahan yang datang jika Anda menggunakan di git commit --onlysini. Dalam kasus ini, Git membuat indeks ketiga , dan segalanya menjadi sangat rumit, terutama jika Anda menggunakan hook pra-komit. Ini adalah alasan lain untuk menggunakan git addoperasi terpisah .