Definisi "hilir" dan "hulu"

902

Saya mulai bermain dengan Git dan menemukan istilah "hulu" dan "hilir". Saya telah melihat ini sebelumnya tetapi tidak pernah mengerti mereka sepenuhnya. Apa arti istilah-istilah ini dalam konteks SCM ( perangkat Manajemen Konfigurasi Perangkat Lunak ) dan kode sumber?

brendan
sumber
13
Ada dua konteks berbeda untuk hulu / hilir di git: remote, dan waktu / sejarah. Hulu / hilir sehubungan dengan remote adalah, repo hilir akan menarik dari repo hulu (perubahan akan mengalir ke hilir secara alami). Hulu / hilir sehubungan dengan waktu / sejarah dapat membingungkan, karena hulu dalam waktu berarti hilir dalam sejarah, dan sebaliknya (terminologi silsilah bekerja jauh lebih baik di sini - orang tua / leluhur / anak / keturunan).
charlesreid1
6
Terkait: Apa artinya 'hulu'? di OS
kenorb
5
Terkait: Perbedaan antara asal dan hulu di gitHub
RBT

Jawaban:

703

Dalam hal kontrol sumber, Anda " hilir " ketika Anda menyalin (mengkloning, checkout, dll) dari repositori. Informasi mengalir "hilir" kepada Anda.

Ketika Anda membuat perubahan, Anda biasanya ingin mengirimnya kembali " upstream " sehingga mereka membuatnya ke dalam repositori itu sehingga semua orang yang menarik dari sumber yang sama bekerja dengan semua perubahan yang sama. Ini sebagian besar merupakan masalah sosial tentang bagaimana setiap orang dapat mengoordinasikan pekerjaan mereka daripada persyaratan teknis pengendalian sumber. Anda ingin memasukkan perubahan ke proyek utama sehingga Anda tidak melacak garis perkembangan yang berbeda.

Terkadang Anda akan membaca tentang manajer paket atau rilis (orang-orang, bukan alat) yang berbicara tentang mengirim perubahan ke "upstream". Itu biasanya berarti mereka harus menyesuaikan sumber asli sehingga mereka dapat membuat paket untuk sistem mereka. Mereka tidak ingin terus melakukan perubahan itu, jadi jika mereka mengirimnya "upstream" ke sumber aslinya, mereka tidak harus berurusan dengan masalah yang sama di rilis berikutnya.

brian d foy
sumber
116
"Unduh" dan "unggah" adalah kata kerja. "Hulu" dan "hilir" menggambarkan posisi relatif.
brian d foy
2
Saya akan mengatakan hulu dan hilir adalah kata sifat
Crt
8
Mereka adalah kata sifat ketika mereka digunakan sebagai pengubah, tetapi istilah-istilah itu sering digunakan sebagai kata benda.
brian d foy
2
@MycrofD kata-kata dapat digunakan sebagai kata sifat dan kata benda tergantung pada konteksnya
reggaeguitar
1
Ini lebih merupakan masalah sosial daripada persyaratan teknis . Lalu mengapa ada opsi -useperti git push --set-upstream origin masterjika itu bukan persyaratan teknis ? Kita bisa push -u originatau tidak push origin, jadi itu adalah persyaratan teknologi. Tapi apa bedanya?
Hijau
249

Ketika Anda membaca di git taghalaman manual :

Salah satu aspek penting dari git adalah didistribusikan, dan didistribusikan sebagian besar berarti tidak ada "hulu" atau "hilir" yang melekat dalam sistem.

, itu hanya berarti tidak ada repo hulu mutlak atau repo hilir.
Gagasan itu selalu relatif antara dua repo dan tergantung pada cara data mengalir:

Jika "yourRepo" telah menyatakan "otherRepo" sebagai remote, maka :

  • Anda menarik dari hulu "otherRepo" ( "otherRepo" adalah "hulu dari Anda", dan Anda "downstream untuk otherRepo").
  • Anda mendorong ke hulu ("otherRepo" masih "hulu", di mana informasi sekarang kembali ke).

Perhatikan "dari" dan "untuk": Anda tidak hanya "hilir", Anda "hilir dari / untuk ", karenanya aspek relatif.


Putar DVCS (Sistem Kontrol Versi Terdistribusi) adalah: Anda tidak tahu apa sebenarnya hilir, di samping repo Anda sendiri relatif terhadap repo jarak jauh yang telah Anda nyatakan.

  • Anda tahu apa itu hulu (repo yang Anda tarik atau dorong)
  • Anda tidak tahu apa yang hilir terbuat dari (repo lain menarik dari atau mendorong ke repo Anda ).

Pada dasarnya:

Dalam istilah " aliran data ", repo Anda berada di bagian bawah ("hilir") dari aliran yang berasal dari repo hulu ("tarik dari") dan kembali ke repo hulu (yang sama atau yang lain) ("push to" ).


Anda dapat melihat ilustrasi di git-rebasehalaman manual dengan paragraf "PEMULIHAN DARI REBASE UPSTREAM":

Itu berarti Anda menarik dari repo "hulu" di mana rebase terjadi , dan Anda (repo "hilir") terjebak dengan konsekuensinya (banyak duplikat komit, karena cabang rebased upstream menciptakan kembali komitmen dari cabang yang sama dengan Anda miliki secara lokal).

Itu buruk karena untuk satu repo "hulu", mungkin ada banyak repo hilir (yaitu repo menarik dari yang hulu, dengan cabang rebased), semuanya memiliki potensi untuk berurusan dengan komitmen duplikat.

Sekali lagi, dengan analogi "aliran data", dalam DVCS, satu perintah buruk "hulu" dapat memiliki " efek riak " di hilir.


Catatan: ini tidak terbatas pada data.
Ini juga berlaku untuk parameter , karena perintah git (seperti yang "porselen") sering memanggil secara internal perintah git lain (yang "pipa ledeng"). Lihat rev-parsehalaman manual :

Banyak perintah porselen git mengambil campuran flag (yaitu parameter yang dimulai dengan tanda hubung ' -') dan parameter yang dimaksudkan untuk git rev-listperintah dasar yang mereka gunakan secara internal dan flag dan parameter untuk perintah lain yang mereka gunakan di hilirgit rev-list . Perintah ini digunakan untuk membedakan keduanya.

VONC
sumber
15
Anda menarik dari hulu, dan Anda mendorong ke hulu. mendorong ke hilir terdengar sangat salah bagi saya
knittl
1
@ Knittl: Anda benar. Saya telah menulis ulang jawaban saya untuk lebih menggambarkan peran repo "hulu" relatif terhadap repo lokal Anda (dan "hilir").
VonC
85

Pelacakan Hulu (terkait dengan)

Istilah hulu juga memiliki beberapa makna yang tidak ambigu karena terkait dengan perangkat GIT, terutama terkait dengan pelacakan

Sebagai contoh :

   $git rev-list --count --left-right "@{upstream}"...HEAD
   >4   12

akan mencetak (nilai cache terakhir) jumlah komit di belakang (kiri) dan depan (kanan) dari cabang kerja Anda saat ini, relatif terhadap ( jika ada ) yang sedang melacak cabang jarak jauh untuk cabang lokal ini. Jika tidak, pesan kesalahan akan dicetak:

    >error: No upstream branch found for ''
  • Seperti yang telah dikatakan, Anda mungkin memiliki sejumlah remote untuk satu repositori lokal, misalnya, jika Anda mengambil repositori dari github, kemudian mengeluarkan 'permintaan tarik', Anda pasti memiliki setidaknya dua: origin(repo bercabang Anda di github) dan upstream(repo pada github yang Anda gunakan sebelumnya). Itu hanya nama yang bisa dipertukarkan, hanya url 'git @ ...' yang mengidentifikasi mereka.

Anda .git/configmembaca:

   [remote "origin"]
       fetch = +refs/heads/*:refs/remotes/origin/*
       url = [email protected]:myusername/reponame.git
   [remote "upstream"]
       fetch = +refs/heads/*:refs/remotes/upstream/*
       url = [email protected]:authorname/reponame.git
  • Di sisi lain, makna @ {upstream} untuk GIT adalah unik:

itu adalah 'cabang' (jika ada) pada 'kata jarak jauh' , yang melacak 'cabang saat ini' di 'repositori lokal' Anda .

Ini adalah cabang yang Anda ambil / tarik dari setiap kali Anda mengeluarkan polos git fetch/ git pull, tanpa argumen.

Katakanlah ingin menetapkan asal / master cabang jarak jauh menjadi cabang pelacakan untuk cabang master lokal yang telah Anda periksa. Hanya masalah:

   $ git branch --set-upstream  master origin/master
   > Branch master set up to track remote branch master from origin.

Ini menambahkan 2 parameter dalam .git/config:

   [branch "master"]
       remote = origin
       merge = refs/heads/master

sekarang coba (asalkan 'upstream' remote memiliki cabang 'dev')

   $ git branch --set-upstream  master upstream/dev
   > Branch master set up to track remote branch dev from upstream.

.git/config sekarang terbaca:

   [branch "master"]
       remote = upstream
       merge = refs/heads/dev

git-push(1)Halaman Manual :

   -u
   --set-upstream

Untuk setiap cabang yang up to date atau berhasil didorong, tambahkan referensi upstream (pelacakan) , digunakan oleh argumen-less git-pull (1) dan perintah lainnya. Untuk informasi lebih lanjut, lihat branch.<name>.mergedi git-config (1).

git-config(1)Halaman Manual :

   branch.<name>.merge

Mendefinisikan, bersama dengan branch.<name>.remote, cabang hulu untuk cabang yang diberikan. Ia memberitahu git fetch / git pull / git rebase cabang mana yang akan digabung dan juga dapat mempengaruhi git push (lihat push.default). \ (...)

   branch.<name>.remote

Ketika di cabang <nama>, ia memberitahu git fetch dan git push yang mengambil remote / push to. Ini default ke asal jika tidak ada remote yang dikonfigurasi. asal juga digunakan jika Anda tidak berada di cabang apa pun.

Hulu dan Dorong (Gotcha)

lihat git-config(1)Halaman Manual

   git config --global push.default upstream
   git config --global push.default tracking  (deprecated)

Ini untuk mencegah dorongan yang tidak disengaja ke cabang yang belum siap untuk didorong.

Peter Host
sumber
4
Kutipan git branch --helpmulai 2018:As this option had confusing syntax, it is no longer supported. Please use --track or --set-upstream-to instead.
zezollo
59

Itu sedikit terminologi informal.

Sejauh menyangkut Git, setiap repositori lainnya hanyalah sebuah remote.

Secara umum, hulu adalah tempat Anda dikloning (asal). Downstream adalah proyek apa pun yang mengintegrasikan pekerjaan Anda dengan pekerjaan lain.

Ketentuan tidak terbatas pada repositori Git.

Sebagai contoh, Ubuntu adalah turunan Debian, jadi Debian adalah hulu untuk Ubuntu.

Hasen
sumber
51

Hulu Disebut Berbahaya

Sayangnya, ada penggunaan lain dari "upstream" yang tidak dijawab oleh jawaban lain, yaitu untuk merujuk pada hubungan orang tua-anak dari komitmen dalam repo. Scott Chacon dalam buku Pro Git sangat rentan terhadap hal ini, dan hasilnya sangat disayangkan. Jangan meniru cara bicara ini.

Sebagai contoh, ia mengatakan penggabungan yang menghasilkan fast-forward bahwa ini terjadi karena

komit yang ditunjuk oleh cabang tempat Anda bergabung langsung ke hulu dari komit yang Anda ikuti

Dia ingin mengatakan bahwa komit B adalah satu-satunya anak dari satu-satunya anak ... dari satu-satunya anak komit A, jadi untuk menggabungkan B menjadi A, cukup memindahkan ref A untuk menunjuk ke komit B. Mengapa arah ini harus disebut "hulu" daripada "hilir", atau mengapa geometri dari grafik garis lurus murni harus dijelaskan "langsung ke hulu", sama sekali tidak jelas dan mungkin sewenang-wenang. (Halaman manual untuk git-mergemelakukan pekerjaan yang jauh lebih baik dalam menjelaskan hubungan ini ketika dikatakan bahwa "kepala cabang saat ini adalah leluhur dari komit bernama." Itulah yang harus dikatakan oleh Chacon.)

Memang, Chacon sendiri kelihatannya menggunakan "hilir" di kemudian hari untuk mengartikan hal yang persis sama, ketika ia berbicara tentang menulis ulang semua komitmen anak dari komit yang dihapus:

Anda harus menulis ulang semua komit di hilir dari 6df76 untuk sepenuhnya menghapus file ini dari riwayat Git Anda

Pada dasarnya dia tampaknya tidak memiliki ide yang jelas apa yang dia maksud dengan "hulu" dan "hilir" ketika merujuk pada sejarah komitmen dari waktu ke waktu. Penggunaan ini bersifat informal, kemudian, dan tidak dianjurkan, karena hanya membingungkan.

Sangat jelas bahwa setiap komit (kecuali satu) memiliki setidaknya satu orang tua, dan orang tua dari orang tua adalah leluhur; dan di arah lain, komit memiliki anak dan keturunan. Itu terminologi yang diterima, dan menjelaskan arah grafik dengan jelas, jadi itulah cara untuk berbicara ketika Anda ingin menggambarkan bagaimana komit berhubungan satu sama lain dalam geometri grafik repo. Jangan gunakan "hulu" atau "hilir" secara longgar dalam situasi ini.

[Catatan tambahan: Saya telah memikirkan tentang hubungan antara kalimat Chacon pertama yang saya kutip di atas dan git-mergehalaman manual, dan terpikir oleh saya bahwa yang pertama mungkin didasarkan pada kesalahpahaman yang terakhir. Halaman manual memang menggambarkan situasi di mana penggunaan "hulu" sah: penerusan cepat sering terjadi ketika "Anda melacak repositori hulu, Anda tidak melakukan perubahan lokal, dan sekarang Anda ingin memperbarui ke yang lebih baru revisi hulu. " Jadi mungkin Chacon menggunakan "hulu" karena dia melihatnya di halaman manual. Tetapi di halaman manual ada repositori jarak jauh; tidak ada repositori jarak jauh dalam contoh fast-forwarding Chacon yang dikutip, hanya beberapa cabang yang dibuat secara lokal.]

matt
sumber
14
Halaman manual git-rebase juga mengalami kelebihan ini: komit yang diperiksa sebelum rebasing disebut "upstream". Ini, juga, mungkin telah mempengaruhi penggunaan Chacon.
outis
@outis aneh - dalam dokumentasi html git, cabang diperiksa sebelum rebasing disebut sebagai <branch>.
Jesper Matthiesen
Poin yang bagus. Akan sangat membantu untuk mengumpulkan "git-terminologi" yang umum di suatu tempat. Khusus untuk pemula (atau ppl yang berkontribusi ke git). Akan menghemat waktu saya terbiasa dengan kata-kata dari halaman git man.
SebNag
@Berkat sesuatu seperti ini? linuxacademy.com/blog/linux/git-terms-explained
reggaeguitar
1
Datang ke sini dari git-rebasedokumen karena saya benar-benar bingung mengapa komit ref akan disebut "upstream" di sana (pada kenyataannya, saya meragukan diri saya sendiri karena saya belum melihat terminologi ini sebelumnya). Terima kasih @outis & @matt untuk membereskan semuanya!
Borek Bernard
0

Secara umum;

  • hulu menuju sumber
  • hilir menuju wastafel atau tujuan

Ini berlaku untuk semua sistem mirip pohon, termasuk sistem kendali sumber.

Stefan
sumber