Apa arti FETCH_HEAD di Git?

221

git pull --help mengatakan:

Dalam mode standarnya, git pulladalah singkatan untuk git fetchdiikuti oleh git merge FETCH_HEAD.

Apa ini FETCH_HEADdan apa yang sebenarnya digabung selama git pull?

Misha Moroshko
sumber
3
Catatan: sejak git 1.8.4 (Agustus 2013), git fetch origin mastersebenarnya akan diperbarui origin/master, bukan hanya FETCH_HEAD. Lihat stackoverflow.com/a/20967347/6309
VonC
Untuk informasi lebih lanjut tentang git merge FETCH_HEAD(sejak Git 2.5, Q2 2015), lihat stackoverflow.com/a/30425991/6309
VonC

Jawaban:

218

FETCH_HEADadalah ref yang berumur pendek, untuk melacak apa yang baru saja diambil dari repositori jarak jauh. git pullpanggilan pertama git fetch, dalam kasus normal mengambil cabang dari remote; FETCH_HEADmenunjuk ke ujung cabang ini (ini menyimpan SHA1 dari komit, seperti halnya cabang). git pullkemudian memanggil git merge, menggabungkan FETCH_HEADke cabang saat ini.

Hasilnya persis seperti yang Anda harapkan: komit di ujung cabang jauh yang sesuai digabungkan ke dalam komit di ujung cabang Anda saat ini.

Ini seperti melakukan git fetchtanpa argumen (atau git remote update), memperbarui semua cabang jarak jauh Anda, kemudian menjalankan git merge origin/<branch>, tetapi menggunakan secara FETCH_HEADinternal sebagai gantinya untuk merujuk pada referensi tunggal apa pun yang diambil, alih-alih perlu menyebutkan beberapa hal.

Cascabel
sumber
9
@Jefromi: maaf, saya pikir Anda salah: sejauh yang saya mengerti, git fetchupdate (gabungan) semua data objek dari penyimpanan jauh, bukan hanya sebuah makan siang. Jadi saya tidak mengerti dari jawaban Anda bagaimana git memutuskan ke ujung cabang mana yang ditunjuk FETCH_HEAD. Saya juga tidak dapat menemukan FETCH_HEADdi dokumentasi git (definisi, bukan contoh). Keberadaan FETCH_HEADpenampilan bagi saya lebih seperti solusi, untuk membuat git pullpekerjaan entah bagaimana .
Alexey
14
Alexey: FETCH_HEADsesuai dengan ujung cabang jarak jauh yang ditentukan oleh branch.<BRANCH>.mergedalam konfigurasi repositori lokal. Jadi sementara fetchmemang mengambil semua data objek dari penyimpanan jarak jauh, FETCH_HEADdigunakan untuk menunjukkan ke mana cabang terpencil dilacak oleh cabang lokal telah maju. Jadi, jika Anda berada di mastercabang lokal dan menjalankan git fetch, dan branch.master.mergemenunjuk ke refs/heads/master, maka FETCH_HEADakan memiliki nilai yang sama origin/mastersegera setelah operasi pengambilan.
larsks
4
@alexy FETCH_HEAD dijelaskan dalam paragraf kedua dari deskripsi git fetch di halaman manualnya. Jawaban saya benar. Dan git fetch tanpa argumen memperbarui semua cabang jarak jauh untuk remote standar ... tapi ini jelas tidak sama dengan penggabungan.
Cascabel
4
Bagaimana FETCH_HEADjika Anda mengambil semua cabang jarak jauh melalui git fetch -a?
stigi
2
@stigi Ujung cabang pelacakan jarak jauh yang ditunjuk oleh cabang yang Anda periksa di dalam git config. Silakan lihat jawaban larsks di komentar di atas.
Ankur Agarwal
19

FETCH_HEAD adalah referensi ke ujung pengambilan terakhir, apakah pengambilan itu dimulai secara langsung menggunakan perintah pengambilan atau sebagai bagian dari tarikan. Nilai FETCH_HEAD saat ini disimpan di .gitfolder dalam file bernama, Anda dapat menebaknya FETCH_HEAD,.

Jadi jika saya mengeluarkan:

git fetch https://github.com/ryanmaxwell/Fragaria

FETCH_HEAD dapat berisi

3cfda7cfdcf9fb78b44d991f8470df56723658d3        https://github.com/ryanmaxwell/Fragaria

Jika saya memiliki repo jarak jauh yang dikonfigurasi sebagai cabang pelacakan jarak jauh maka saya dapat mengikuti pengambilan saya dengan gabungan cabang pelacakan. Jika tidak, saya bisa menggabungkan ujung pengambilan terakhir langsung menggunakan FETCH_HEAD.

git merge FETCH_HEAD
Jonathan Mitchell
sumber
1
Untuk menambah 5 sen saya. Yang membingungkan saya adalah, bahwa FETCH_HEAD saya ada di belakang komit terbaru, bahkan jika melakukan pengambilan baru yang mengembalikan "tidak ada perubahan" (dalam gerhana). Saya pikir alasannya adalah, bahwa semua perubahan sejak pengambilan terakhir saya adalah dari diri saya dan didorong ke server oleh saya. Jadi pengambilan berikutnya tidak ada hubungannya, dan bahkan tidak memperbarui FETCH_HEAD. Saya tidak yakin apakah ini merupakan kekurangan dari implementasi GIT atau Eclipse Git.
Torge
11

Seperti yang disebutkan dalam jawaban Jonathan , FETCH_HEAD terkait dengan file .git/FETCH_HEAD. Biasanya, file akan terlihat seperti ini:

71f026561ddb57063681109aadd0de5bac26ada9                        branch 'some-branch' of <remote URL>
669980e32769626587c5f3c45334fb81e5f44c34        not-for-merge   branch 'some-other-branch' of <remote URL>
b858c89278ab1469c71340eef8cf38cc4ef03fed        not-for-merge   branch 'yet-some-other-branch' of <remote URL>

Perhatikan bagaimana semua cabang kecuali satu ditandai not-for-merge. Yang aneh adalah cabang yang diperiksa sebelum pengambilan. Singkatnya: FETCH_HEAD pada dasarnya sesuai dengan versi jauh dari cabang yang saat ini diperiksa.

Carsten Führmann
sumber
9

Saya baru saja menemukan dan menggunakan FETCH_HEAD. Saya ingin salinan lokal beberapa perangkat lunak dari server dan saya lakukan

git fetch gitserver release_1

gitserveradalah nama mesin saya yang menyimpan repositori git. release_1adalah tag untuk versi perangkat lunak. Yang mengejutkan saya, release_1ternyata tidak ditemukan di mesin lokal saya. Saya harus mengetik

 git tag release_1 FETCH_HEAD 

untuk menyelesaikan salinan rantai komitmen yang ditandai (release_1) dari repositori jauh ke yang lokal. Fetch telah menemukan tag jarak jauh, menyalin komit ke mesin lokal saya, belum membuat tag lokal, tetapi telah menetapkan FETCH_HEADnilai komit, sehingga saya dapat menemukan dan menggunakannya. Saya kemudian digunakan FETCH_HEADuntuk membuat tag lokal yang cocok dengan tag pada remote. Itu adalah ilustrasi praktis tentang apa FETCH_HEADitu dan bagaimana itu dapat digunakan, dan mungkin berguna bagi orang lain yang bertanya-tanya mengapa git fetch tidak melakukan apa yang Anda harapkan secara naif.

Menurut pendapat saya sebaiknya dihindari untuk tujuan itu dan cara yang lebih baik untuk mencapai apa yang saya coba lakukan adalah

git fetch gitserver release_1:release_1

yaitu untuk mengambil release_1 dan menyebutnya release_1 secara lokal. (Ini adalah sumber: dest, lihat https://git-scm.com/book/en/v2/Git-Internals-The-Refspec ; kalau-kalau Anda ingin memberikan nama yang berbeda!)

Anda mungkin ingin menggunakan FETCH_HEADbeberapa kali: -

git fetch gitserver bugfix1234
git cherry-pick FETCH_HEAD

mungkin cara yang baik untuk menggunakan perbaikan bug nomor 1234 dari server Git Anda, dan meninggalkan pengumpulan sampah Git untuk membuang salinan dari server setelah perbaikannya telah dipilih ke cabang Anda saat ini. (Saya berasumsi bahwa ada komit tag yang bagus dan bersih yang berisi seluruh perbaikan bug di server!)

Ivan
sumber
Umpan balik yang menarik. +1
VonC
Terima kasih. Saya mengedit posting asli saya, yang ditulis ketika saya pertama kali menemukan FETCH_HEAD beberapa tahun yang lalu, karena tampaknya mendorong menyalin tag menggunakan FETCH_HEAD daripada sumber: sintaks dest untuk refspecs. Semoga sekarang saya telah memberikan contoh yang lebih baik tentang bagaimana FETCH_HEAD dapat digunakan.
Ivan
3

git pull adalah kombinasi dari pengambilan yang diikuti oleh gabungan. Ketika git fetch terjadi, ia mencatat komit head dari apa yang diambil di FETCH_HEAD (hanya sebuah file dengan nama itu di .git) Dan komit ini kemudian digabung ke direktori kerja Anda.

manojlds
sumber
3
@manjolds, apa yang Anda maksud dengan " komit dari apa yang diambilnya"? Git mengambil semuanya dengan mengambil.
Alexey
@Alexey dari manual git: git-scm.com/docs/git-fetch : Nama-nama referensi yang diambil, bersama dengan nama-nama objek yang mereka tuju, ditulis ke .git / FETCH_HEAD
PJ_Finnegan