Apa perbedaan antara KEPALA, pohon kerja dan indeks, di Git?

488

Dapatkah seseorang memberi tahu saya perbedaan antara KEPALA, pohon kerja dan indeks, di Git?

Dari apa yang saya mengerti, mereka semua adalah nama untuk cabang yang berbeda. Apakah asumsi saya benar?


Edit

aku menemukan ini

Repositori git tunggal dapat melacak sejumlah cabang yang berubah-ubah, tetapi pohon kerja Anda hanya dikaitkan dengan salah satu dari mereka (cabang "saat ini" atau "diperiksa"), dan HEAD menunjuk ke cabang itu.

Apakah ini berarti bahwa KEPALA dan pohon yang bekerja selalu sama?

Joyce Babu
sumber
26
Sehubungan dengan hasil edit Anda: sama sekali tidak. HEADadalah komit di ujung cabang saat ini. Jika Anda baru saja memeriksa cabang, yaitu tidak memiliki file yang dimodifikasi, maka kontennya cocok dengan pohon kerja. Segera setelah Anda memodifikasi apa pun, itu tidak lagi cocok.
Cascabel
6
Saya pikir Anda harus membaca ini: think-like-a-git.net
Andrzej Duś
5
Saya juga akan menambahkan Staging Areake daftar itu. Apa HEAD, Working Tree, IndexdanStaging Area
Hijau
2
Kalimat terakhir dari @ Jefromi akan lebih jelas sebagai:> Begitu Anda memodifikasi apa pun, pohon kerja tidak lagi cocok dengan komit HEAD
starscream_disco_party
3
Untuk setiap bacaan ini di masa depan, cara terbaik untuk benar-benar memahami beberapa jawaban ini adalah dengan melihat dan merasakan dan mengonseptualisasikan secara visual apa yang sedang terjadi: ini adalah alat terbaik untuk mempelajari git: onlywei.github.io/explain-git-with -d3 / # fetchrebase
BKSpurgeon

Jawaban:

579

Beberapa referensi bagus tentang topik-topik itu:

teks alternatif

Saya menggunakan indeks sebagai pos pemeriksaan .

Ketika saya akan membuat perubahan yang mungkin serba salah - ketika saya ingin menjelajahi beberapa arah yang saya tidak yakin apakah saya dapat menindaklanjuti atau bahkan apakah itu ide yang baik, seperti refactoring yang menuntut secara konseptual atau mengubah suatu tipe representasi - Saya memeriksa pos kerja saya ke dalam indeks. Jika ini adalah perubahan pertama yang saya buat sejak komit terakhir saya, maka saya dapat menggunakan repositori lokal sebagai pos pemeriksaan, tetapi seringkali saya memiliki satu perubahan konseptual yang saya terapkan sebagai serangkaian langkah kecil. Saya ingin memeriksa titik setelah setiap langkah, tetapi simpan komit sampai saya kembali bekerja, kode diuji.

Catatan:

  1. yang ruang kerja adalah pohon direktori (sumber) file yang Anda lihat dan edit.

  2. The Indeks adalah satu, besar, file biner dalam <baseOfRepo>/.git/index, yang berisi daftar semua file di cabang saat ini, mereka sha1 checksum, perangko waktu dan nama file - tidak direktori lain dengan salinan file di dalamnya.

  3. The repositori lokal adalah direktori tersembunyi ( .git) termasuk objectsdirektori yang berisi semua versi setiap file dalam repo (cabang lokal dan salinan dari cabang remote) sebagai terkompresi "gumpalan" file.

Jangan menganggap empat 'disk' yang diwakili dalam gambar di atas sebagai salinan terpisah dari file repo.

teks alternatif

Mereka pada dasarnya bernama referensi untuk komitmen Git. Ada dua jenis ref utama: tag dan head.

  • Tag adalah referensi tetap yang menandai titik tertentu dalam sejarah, misalnya v2.6.29.
  • Sebaliknya, kepala selalu tergerak untuk mencerminkan posisi pengembangan proyek saat ini.

teks alternatif

(catatan: seperti dikomentari oleh Timo Huovinen , panah-panah itu tidak sesuai dengan komit, itu adalah urutan alur kerja , pada dasarnya menunjukkan panah sebagai di 1 -> 2 -> 3 -> 4mana 1komit pertama dan 4yang terakhir)

Sekarang kita tahu apa yang terjadi di proyek.
Tetapi untuk mengetahui apa yang terjadi di sini, saat ini ada referensi khusus yang disebut HEAD. Ini melayani dua tujuan utama:

  • itu memberitahu Git yang berkomitmen untuk mengambil file dari saat Anda checkout, dan
  • itu memberi tahu Git di mana harus meletakkan komit baru ketika Anda melakukan.

Ketika Anda menjalankannya git checkout refmenunjuk HEADke referensi yang Anda tunjuk dan mengekstrak file dari itu. Ketika Anda menjalankannya git commitmenciptakan objek komit baru, yang menjadi anak saat ini HEAD. Biasanya HEADmenunjuk ke salah satu kepala, jadi semuanya bekerja dengan baik.

teks alternatif

VONC
sumber
20
Setelah membaca tentang git berkali-kali, saya tidak pernah memahaminya sepenuhnya. Saya benar-benar frustrasi dan ingin menggunakan kata itu; Tapi saya di komunitas! Anda telah menyebut kepala tetapi pada gambar di atas selalu ada satu KEPALA tempat r ** f kepala yang tersisa? "Biasanya HEAD menunjuk ke salah satu kepala, jadi semuanya baik-baik saja." Saya mohon Anda untuk menjelaskan ini, pernyataan Ur.
Necktwi
12
@neckTwi KEPALA adalah komit yang sedang Anda kerjakan ( stackoverflow.com/a/964927/6309 ). Biasanya adalah salah satu dari "kepala cabang" (salah satu komit yang dirujuk oleh cabang, mewakili ujung cabang tersebut). Tetapi Anda dapat checkout (dan mengerjakan) komitmen apa pun. Jika Anda checkout komit yang bukan salah satu dari (cabang) kepala, Anda berada dalam mode "HEAD terpisah": stackoverflow.com/a/3965714/6309
VonC
1
@Imray Saya setuju, tapi itulah bagaimana saya menemukan foto-foto itu 5 tahun yang lalu ( hades.name/blog/2010/01/28/… )
VonC
11
Mengenai indeks, saya pikir hal yang paling berguna yang dapat dikatakan adalah "Indeks hanyalah nama lain untuk area pementasan," seperti kata @ ashraf-alam. Saya merasa seperti sebagian besar waktu dalam diskusi itu disebut sebagai area pementasan, itulah sebabnya saya tidak secara otomatis membuat koneksi bahwa itu adalah hal yang sama dengan indeks.
Pete
1
@ Tolong saya setuju. Untuk lebih lanjut tentang perbedaan antara cache dan indeks, lihat jawaban saya yang lain stackoverflow.com/a/6718135/6309
VonC
137

Perbedaan antara KEPALA (cabang saat ini atau keadaan terakhir yang dilakukan di cabang saat ini), indeks (alias. Area pentahapan) dan pohon kerja (keadaan file dalam checkout) dijelaskan di bagian "Tiga Negara" pada "Dasar-Dasar 1,3 Git " bab buku Pro Git oleh Scott Chacon (berlisensi Creative Commons).

Berikut gambar yang menggambarkannya dari bab ini:

Operasi Lokal - direktori kerja vs. area pementasan (indeks) vs repositori git (HEAD)

Pada gambar di atas "direktori kerja" sama dengan "pohon kerja", "area pementasan" adalah nama alternatif untuk git "indeks", dan HEAD menunjuk ke cabang yang saat ini diperiksa, yang ujungnya menunjuk komit terakhir di " direktori git (repositori) "

Perhatikan bahwa git commit -aakan melakukan perubahan dan komit dalam satu langkah.

Jakub Narębski
sumber
1
"Sebuah gambar bernilai ribuan kata". Terima kasih Jakub .. Dan terima kasih untuk tautannya.
Joyce Babu
5
Catatan: working treetampaknya lebih disukai untuk working directorysaat ini. Lihat github.com/git/git/commit/…
VonC
3
Gambar ini tidak persis akurat karena Staging Area terkandung dalam satu file yang disebut "indeks" - dan file indeks tersebut berada di root direktori .git. Jadi, jika Anda mendefinisikan repo sebagai direktori .git, area pementasan secara teknis berada di dalam repo. Kolom ketiga akan lebih baik diberi label "HEAD's Root tree object" untuk menunjukkan bahwa file yang diperiksa keluar dari objek komit dan yang melakukan penulisan pohon baru ke objek komit - kedua objek komit ditunjuk oleh HEAD.
Jazimov
@Jazimov Anda mungkin benar, tetapi ketika ia menulis, ia telah mengambil gambar itu dari buku Pro Git yang terkenal, dan ia telah menyediakan tautan. Jadi, jika gambar bisa diperbaiki atau bahkan salah, seseorang harus memberi tahu penulis buku itu ... Secara umum, saya akan bersedia melakukan itu, tetapi jujur ​​saja, saya masih pemula git dan belum mengerti apa yang kamu katakan, jadi aku jelas orang yang salah dalam hal itu.
Binarus
@Binarus: Bahaya dalam reproduksi grosir gambar seperti ini adalah bahwa ia berfungsi untuk menyebarkan "kesalahan representasi" yang dibuat oleh satu penulis / buku. Saya pikir ini adalah kasus interpretasi literal versus fungsional di sini: Dalam arti literal, indeks sebenarnya terkandung dalam repo jika Anda mendefinisikan repo sebagai segala sesuatu di bawah folder .git. Namun, dalam arti fungsional, indeks membantu Git mempertahankan DAG dalam repo dan dapat dianggap sebagai makhluk eksternal.
Jazimov
64

Pohon kerja Anda adalah apa yang sebenarnya ada di file yang sedang Anda kerjakan.

HEADadalah pointer ke cabang atau komit yang terakhir Anda periksa, dan yang akan menjadi induk dari komit baru jika Anda membuatnya. Misalnya, jika Anda berada di mastercabang, maka HEADakan menunjuk ke master, dan ketika Anda komit, komit baru itu akan menjadi turunan dari revisi yang mastermenunjuk, dan masterakan diperbarui untuk menunjuk ke komit baru.

The Indeks adalah area pementasan di mana baru komit siap. Pada dasarnya, isi indeks adalah apa yang akan masuk ke dalam komit baru (meskipun jika Anda melakukannya git commit -a, ini akan secara otomatis menambahkan semua perubahan ke file yang Git tahu tentang indeks sebelum melakukan, sehingga akan melakukan isi saat ini dari pohon kerja Anda ). git addakan menambah atau memperbarui file dari pohon kerja ke dalam indeks Anda.

Brian Campbell
sumber
Terima kasih banyak untuk penjelasannya Brian. Jadi, pohon yang bekerja berisi semua perubahan yang tidak dikomit. Jika saya mengkomit perubahan saya dengan git commit -a, maka pada waktu itu Pohon dan Indeks Kerja saya akan sama. Ketika saya mendorong ke repo pusat saya, ketiganya akan sama. Apakah saya benar?
Joyce Babu
3
@Vinod Cukup banyak. Anda dapat memiliki file di pohon kerja Anda yang tidak diketahui Git, dan itu tidak akan dilakukan dengan git commit -a(Anda perlu menambahkannya git add), jadi pohon kerja Anda mungkin memiliki file tambahan yang indeks Anda, repo lokal Anda, atau repo jarak jauh Anda tidak punya.
Brian Campbell
2
@Vinod: Pohon dan indeks kerja dapat menjadi sama tanpa melakukan (git add memperbarui indeks dari pohon kerja, dan git checkout <path> memperbarui pohon kerja dari indeks). HEADmerujuk ke komit terbaru, jadi ketika Anda komit, Anda memperbarui HEADke komit baru Anda, yang cocok dengan indeks. Mendorong tidak ada hubungannya dengan itu - itu membuat cabang di cabang pertandingan jarak jauh di repo lokal Anda.
Cascabel
45

Pohon yang bekerja

Pohon kerja Anda adalah file yang sedang Anda kerjakan.

Indeks git

  • "Indeks" git adalah tempat Anda meletakkan file yang ingin Anda komit ke repositori git.

  • Indeks ini juga dikenal sebagai cache yang , Cache direktori , tembolok direktori saat ini , area pementasan , dipentaskan file .

  • Sebelum Anda "mengkomit" (checkin) file ke repositori git, Anda harus terlebih dahulu menempatkan file dalam "indeks" git.

  • Indeks bukan direktori kerja: Anda dapat mengetik perintah seperti git status, dan git akan memberi tahu Anda file apa di direktori kerja Anda yang telah ditambahkan ke indeks git (misalnya, dengan menggunakan git add filenameperintah).

  • Indeks bukan repositori git: file dalam indeks git adalah file yang git akan komit ke repositori git jika Anda menggunakan perintah git commit.

Ashraf Alam
sumber
1
Perhatikan bahwa Git 2.5 akan membawa banyak pohon yang berfungsi ( stackoverflow.com/a/30185564/6309 ). +1
VonC
3
Saya tidak yakin bahwa "Indeks Bukan Direktori Kerja" adalah 100% benar. Seharusnya "Indeks Bukan Direktori Kerja, tetapi termasuk seluruh direktori kerja + perubahan yang ingin Anda komit selanjutnya". Bukti? buka repositori git, reset --hard HEADuntuk memastikan bahwa indeks Anda == pohon kerja Anda. an then: mkdir history && git checkout-index --prefix history/ -aHasilnya adalah duplikasi seluruh pohon kerja Anda di history/direktori Anda . Ergo git index> = direktori kerja git
Adam Kurkiewicz
3
Indeks bukan direktori kerja dan tidak harus menyertakan direktori kerja. Index hanyalah sebuah file dalam repositori git yang menyimpan info apa yang ingin Anda komit.
Boon
3
"The" index "menyimpan snapshot dari isi dari pohon yang bekerja, dan snapshot inilah yang diambil sebagai isi dari commit selanjutnya. Dengan demikian setelah membuat perubahan apa pun pada direktori yang berfungsi, dan sebelum menjalankan perintah commit, Anda harus menggunakan perintah add untuk menambahkan file baru atau yang dimodifikasi ke indeks "( git-scm.com/docs/git-add )
anth
3
@AdamKurkiewicz: buktinya gagal jika Anda pertama kali echo untracked-data > untracked-file, sebelum atau setelah langkah git reset --HARDdan git checkout-index. Anda akan menemukan bahwa file yang tidak dilacak tidak ada dalam historydirektori. Anda juga dapat memodifikasi indeks dan pohon-kerja secara independen, meskipun memodifikasi indeks tanpa terlebih dahulu menyentuh pohon-pekerjaan itu sulit (harus menggunakan git update-index --index-info).
torek