Bagaimana pengaturan Origin / HEAD?

144

Saya memiliki cabang yang dibentuk untuk melacak referensi yang berasal. git checkout <branchname>beralih ke cabang itu, dan surat git statuswasiat menunjukkan kepada saya seberapa jauh ke depan atau di belakang cabang saya dari asal, tapi saya terkejut bahwa origin/HEADmasih menunjuk origin/master, dan tidakorigin/<branchname>

Jadi pertanyaan saya adalah, dalam kondisi apa asal / HEAD dipindahkan?

EDIT:

Saya menghargai jawaban tentang bagaimana memindahkan asal / KEPALA, tapi saya tertarik dengan apa yang "organik" memindahkannya, di luar saya secara eksplisit mengatakannya untuk melakukannya.

Sebagai contoh, ketika saya beralih cabang, git membuat titik HEAD di cabang yang saya periksa, jadi saya terkejut bahwa asal / HEAD tidak bergerak dengan cara yang sama.

Ecoffey
sumber
Perhatikan bahwa pertanyaan ini adalah tentang referensi simbolis lokal tentang remote refs/origin/HEAD. Ini bukan tentang bagaimana referensi simbolis repositori sendiri HEADakan ditetapkan.
clacke

Jawaban:

173

Perhatikan dulu bahwa pertanyaan Anda menunjukkan sedikit kesalahpahaman. origin / HEAD mewakili cabang default pada remote , yaitu HEAD yang ada di repositori jauh yang Anda panggil asal. Saat Anda mengganti cabang di repo Anda, Anda tidak memengaruhi itu. Hal yang sama berlaku untuk cabang yang jauh; Anda mungkin memiliki masterdan origin/masterdalam repo Anda, di mana origin/mastermerupakan salinan lokal mastercabang di repositori jarak jauh.

KEPALA asal hanya akan berubah jika Anda atau orang lain benar-benar mengubahnya di repositori jarak jauh , yang pada dasarnya seharusnya tidak pernah terjadi - Anda ingin cabang default repo publik tetap konstan, pada cabang stabil (mungkin master). origin / HEAD adalah ref lokal yang mewakili salinan HEAD lokal dalam repositori jarak jauh. (Nama lengkapnya adalah ref / remote / origin / HEAD.)

Saya pikir jawaban di atas menjawab apa yang sebenarnya ingin Anda ketahui, tetapi untuk terus maju dan menjawab pertanyaan yang Anda tanyakan secara eksplisit ... asal / KEPALA diatur secara otomatis ketika Anda mengkloning repositori, dan hanya itu. Anehnya, itu tidak diatur oleh perintah seperti git remote update- Saya percaya satu-satunya cara itu akan berubah adalah jika Anda mengubahnya secara manual. (Dengan perubahan yang saya maksud arahkan ke cabang yang berbeda; jelas komit itu menunjuk ke perubahan jika cabang itu berubah, yang mungkin terjadi saat mengambil / menarik / memperbarui jarak jauh.)


Sunting : Masalah yang dibahas di bawah ini diperbaiki di Git 1.8.4.3 ; lihat pembaruan ini .


Ada peringatan kecil. KEPALA adalah ref simbolik, menunjuk ke cabang bukannya langsung ke komit, tetapi protokol transfer jarak jauh git hanya melaporkan komit untuk ref. Jadi Git tahu SHA1 dari commit yang ditunjuk oleh HEAD dan semua referensi lainnya; kemudian harus menyimpulkan nilai KEPALA dengan menemukan cabang yang menunjuk ke komit yang sama. Ini berarti bahwa jika dua cabang kebetulan menunjuk ke sana, itu ambigu. (Saya percaya itu mengambil master jika memungkinkan, kemudian kembali ke alfabet pertama.) Anda akan melihat ini dilaporkan dalam output dari git remote show origin:

$ git remote show origin
* remote origin
  Fetch URL: ...
  Push  URL: ...
  HEAD branch (remote HEAD is ambiguous, may be one of the following):
    foo
    master

Anehnya, walaupun gagasan HEAD yang dicetak dengan cara ini akan berubah jika segalanya berubah pada remote (mis. Jika foo dihapus), itu sebenarnya tidak memperbarui refs/remotes/origin/HEAD. Ini dapat menyebabkan situasi yang sangat aneh. Katakan bahwa dalam contoh di atas asal / KEPALA sebenarnya menunjuk ke foo, dan cabang foo asal itu kemudian dihapus. Kami kemudian dapat melakukan ini:

$ git remote show origin
...
HEAD branch: master
$ git symbolic-ref refs/remotes/origin/HEAD
refs/remotes/origin/foo
$ git remote update --prune origin
Fetching origin
 x [deleted]         (none)     -> origin/foo
   (refs/remotes/origin/HEAD has become dangling)

Jadi meskipun remote show tahu HEAD adalah master, ia tidak memperbarui apa pun. Cabang basi foo dipangkas dengan benar, dan KEPALA menjadi menggantung (menunjuk ke cabang tidak ada), dan itu masih tidak memperbaruinya untuk menunjuk ke master. Jika Anda ingin memperbaiki ini, gunakan git remote set-head origin -a, yang secara otomatis menentukan HEAD asal seperti di atas, dan kemudian benar-benar menetapkan asal / HEAD untuk menunjuk ke cabang jarak jauh yang sesuai.

Cascabel
sumber
@ jefromi Jawaban yang luar biasa! Hanya sebuah komentar: Anda menulis bahwa KEPALA adalah ref simbolik, menunjuk ke cabang bukannya langsung ke komit [...] , tetapi mungkin layak disebut "keadaan KEPALA terpisah", untuk kelengkapan.
jub0bs
2
@Jubobs, terima kasih! Jika jawaban saya perlu diperbarui, silakan mengeditnya saja - tentu saja ini akan menghemat waktu orang untuk membaca ringkasan singkat tentang cara kerja sebenarnya, daripada harus memilah-milah apa yang benar dua tahun lalu dan apa yang benar sekarang .
Cascabel
telah membaca ini setidaknya 5 kali dan masih tidak mengerti sedikitpun
krb686
7
git remote set-head origin -amelakukan pekerjaan untuk saya
Shujito
75

Ini adalah pengaturan Anda sebagai pemilik repo lokal Anda. Ubah seperti ini:

git remote set-head origin some_branch

Dan asal / KEPALA akan menunjuk ke cabang Anda, bukan master. Ini kemudian akan berlaku untuk repo Anda saja dan tidak untuk orang lain. Secara default, ini akan menunjuk ke master, kecuali ada sesuatu yang telah dikonfigurasi pada repo jarak jauh.

Entri manual untuk set-head jarak jauh menyediakan beberapa informasi bagus tentang ini.

Sunting: untuk menekankan: tanpa Anda menyuruhnya, satu-satunya cara ia akan "pindah" akan menjadi kasus seperti mengganti nama cabang master , yang saya pikir tidak dianggap "organik". Jadi, saya katakan secara organik itu tidak bergerak.

eis
sumber
1
Penekanan edit tidak sepenuhnya benar di sini. Itu juga dapat berubah jika Anda mengkloning dari salinan lokal yang tidak ada di cabang master.
mphair
Saya tidak menganggap klon "bergerak", tapi saya kira kita bisa tidak setuju tentang itu :)
eis
24

Apa yang bergerak asal / KEPALA "organik"?

  • git clone menyetelnya sekali ke tempat asal HEAD
    • ini berfungsi sebagai cabang default untuk checkout setelah kloning dengan git clone

Mewakili apa KEPALA asal?

  • pada repositori telanjang (sering repositori “di server”) ini berfungsi sebagai penanda untuk cabang default, karena git clonemenggunakannya sedemikian rupa
  • pada repositori non-telanjang (lokal atau jauh), ini mencerminkan checkout repositori saat ini

Apa yang mengatur asal / KEPALA?

  • git clone mengambil dan mengaturnya
  • masuk akal jika git fetchmemperbaruinya seperti referensi lain, tetapi tidak
  • git remote set-head origin -a mengambil dan mengaturnya
    • berguna untuk memperbarui pengetahuan lokal tentang apa yang dianggap remote sebagai "cabang default"

Hal sepele

  • origin/HEAD juga dapat diatur ke nilai lain apa pun tanpa menghubungi remote: git remote set-head origin <branch>
    • Saya tidak melihat use case untuk ini, kecuali untuk pengujian
  • sayangnya tidak ada yang dapat mengatur KEPALA di remote
  • git versi lama tidak tahu yang menunjuk ke HEAD cabang mana pada remote, hanya komit yang hash akhirnya miliki: jadi semoga saja mengambil nama cabang yang menunjuk ke hash yang sama
Robert Siemer
sumber
Saya kehilangan referensi origin/HEADdan solusi Anda membantu. Terima kasih!
java_dude
Saya tidak setuju dengan git fetchmemperbaruinya, karena memungkinkan untuk mengkonfigurasi pintasan (lokal). Mengutip dokumen: "Memiliki cabang default untuk remote tidak diperlukan, tetapi memungkinkan nama remote ditentukan sebagai pengganti cabang tertentu". Akan aneh jika perubahan jarak jauh akan memperbarui pintasan yang dikonfigurasi secara lokal.
Micha Wiedenmann
@MichaWiedenmann Mengapa itu menjadi pintasan yang dikonfigurasi secara lokal? Untuk pintasan yang dikonfigurasi secara lokal origin/HEADadalah nama yang buruk. Dan itu git clonemenggunakan nama jarak jauh sebagai default untuk "cabang yang dikonfigurasikan secara lokal" juga bertentangan dengan itu. Pada repositori non-telanjang, bahkan tidak masuk akal untuk menggunakan remote saat ini HEAD.
Robert Siemer
10

Penafian : ini adalah pembaruan untuk jawaban Jefromi , yang saya tulis untuk menghemat waktu yang penasaran.

Saya mencoba mereplikasi (dalam Git 2.0.1) dengan sia-sia remote HEAD is ambiguouspesan yang Jefromi sebutkan dalam jawabannya; jadi saya melakukan sedikit penggalian (dengan mengkloning https://github.com/git/git dan mencari log). Dulu itu

Determining HEAD is ambiguous since it is done by comparing SHA1s.

In the case of multiple matches we return refs/heads/master if it
matches, else we return the first match we encounter. builtin-remote
needs all matches returned to it, so add a flag for it to request such.

(Commit 4229f1fa325870d6b24fe2a4c7d2ed5f14c6f771, tanggal 27 Feb 2009, ditemukan bersama git log --reverse --grep="HEAD is ambiguous")

Namun, ambiguitas yang dipermasalahkan telah diangkat :

One long-standing flaw in the pack transfer protocol used by "git
clone" was that there was no way to tell the other end which branch
"HEAD" points at, and the receiving end needed to guess.  A new
capability has been defined in the pack protocol to convey this
information so that cloning from a repository with more than one
branches pointing at the same commit where the HEAD is at now
reliably sets the initial branch in the resulting repository.

(Berkomitmen 9196a2f8bd46d36a285bdfa03b4540ed3f01f671, tertanggal 8 November 2013, ditemukan dengan git log --grep="ambiguous" --grep="HEAD" --all-match)

Edit (terima kasih kepada torek ):

$ git name-rev --name-only 9196a2f8bd46d36a285bdfa03b4540ed3f01f671
tags/v1.8.4.3~3

Ini berarti bahwa, jika Anda menggunakan Git v1.8.4.3 atau lebih baru , Anda seharusnya tidak mengalami masalah ambigu-remote-HEAD.

jub0bs
sumber
1
Berdasarkan tag di sumber git, perbaikan ini berlaku untuk git versi 1.8.4.3 dan yang lebih baru.
torek
@RobertSiemer Saya tidak yakin, tapi saya pikir begitu, ya.
jub0bs
8

Ingat ada dua repo git independen yang sedang kita bicarakan. Repo lokal Anda dengan kode Anda dan kendali jarak jauh berjalan di tempat lain.

Anda benar, ketika Anda mengubah cabang, KEPALA menunjuk ke cabang Anda saat ini. Semua ini terjadi pada git repo lokal Anda. Bukan repo jarak jauh, yang bisa dimiliki oleh pengembang lain, atau duduk di bagian di kantor Anda, atau github, atau direktori lain di sistem file, atau dll ...

Komputer Anda (repo lokal) tidak memiliki urusan mengubah pointer HEAD pada repo git jarak jauh. Itu bisa dimiliki oleh pengembang yang berbeda misalnya.

Satu hal lagi, apa yang komputer Anda sebut sebagai asal / XXX adalah pemahaman komputer Anda tentang keadaan remote pada saat pengambilan terakhir.

Jadi apa yang "organik" akan memperbarui asal / KEPALA? Ini akan menjadi aktivitas pada repo git jarak jauh. Bukan repo lokal Anda.

Orang-orang menyebutkan

git simbolis-ref HEAD ref / head / my_other_branch

Biasanya, itu digunakan ketika ada repo git pusat bersama pada server untuk digunakan oleh tim pengembangan. Itu akan menjadi perintah yang dijalankan di komputer jarak jauh. Anda akan melihat ini sebagai aktivitas pada repo git jarak jauh.

Pablo Maurin
sumber
1
Maaf, jika saya sedikit berulang. Saya hanya ingin menunjukkan fakta bahwa git adalah sistem kontrol versi terdistribusi, dan karenanya kedua repo itu independen.
Pablo Maurin
3

Jalankan perintah berikut dari git CLI:

# move to the wanted commit
git reset --hard <commit-hash> 

# update remote
git push --force origin <branch-name> 
Yakir GIladi Edry
sumber
1
Hebat, itu yang membantu saya!
Shay Zambrovski