Neden "git push --set-upstream origin <branch>" yapmam gerekiyor?


147

Solaris ve Sun Studio'yu test etmek için yerel bir şube oluşturdum. Daha sonra dalı yukarı doğru ittim. Bir değişiklik yaptıktan ve değişiklikleri zorlamaya çalıştıktan sonra:

$ git commit blake2.cpp -m "Add workaround for missing _mm_set_epi64x"
[solaris 7ad22ff] Add workaround for missing _mm_set_epi64x
 1 file changed, 5 insertions(+)
$ git push
fatal: The current branch solaris has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin solaris

Bunun için neden özel bir şey yapmam gerekiyor?

Birinin yaratacağı <branch>, uzaklara iteceği <branch>ve sonra bir taahhütte <branch>bulunulmaması gereken herhangi bir makul kullanım durumu var mı <branch>?


Stack Overflow'da bu soruyu ve cevabı takip ettim: Yeni bir yerel şubeyi uzak bir Git deposuna gönderin ve onu da izleyin . Sanırım eksik veya yanlış kabul edilmiş bir cevabın başka bir örneği. Ya da basit bir görevi alıp zorlaştıran başka bir Git örneğidir.


İşte farklı bir makinenin görüntüsü. Şube açıkça var, bu yüzden yaratıldı ve itildi:

$ git branch -a
  alignas
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/alignas
  remotes/origin/arm-neon
  remotes/origin/det-sig
  remotes/origin/master
  remotes/origin/solaris


2
Teşekkürler @Alexi. Maalesef, alıntılanan kopya, varsayılan olarak temsil edilen saçma kullanım durumunu açıklamıyor. (Bunlar retorik sorular değil. UX tasarımının nedeniyle gerçekten ilgileniyorum).
jww

1
Bunun yapılandırılabilir olduğunu unutmayın. Bunu yaparsanız git config --add push.default currentgit push, gerekirse uzak depoda şubeyi otomatik olarak oluşturacaktır.
Gogowitsch

Yanıtlar:


271

TL; DR: git branch --set-upstream-to origin/solaris


İstediğin-sorusuna bu mu "Ben bir kaynak tarafı ayarlamak zorunda" gibi biraz başka bir şekilde ifade edeceğiz cevabı: hayır, yok olması hiç bir kaynak tarafı ayarlamak için.

Bununla birlikte, geçerli dal için yukarı akışınız yoksa, Git davranışını git pushve diğer komutları da değiştirir.

Buradaki itme hikayesinin tamamı uzun ve sıkıcıdır ve geçmişte Git sürüm 1.5 öncesine kadar uzanır. Bir çok kısaltmak için git pushkötü uygulandı. 1 Git sürüm 2.0'dan itibaren Git'in push.defaultartık varsayılan olarak yazılmış bir yapılandırma düğmesi vardır simple. Git'in 2.0'dan önceki ve sonraki çeşitli sürümleri için, her koştuğunuzda git push, Git sizi push.defaultsadece susmak için ayarlamaya ikna etmeye çalışırken çok fazla gürültü çıkarırdı git push.

Hangi Git sürümünü çalıştırdığınızı veya yapılandırıp yapılandırmadığınızı belirtmiyorsunuz push.default, bu yüzden tahmin etmeliyiz. Benim tahminim Git sürüm 2-nokta-birşey kullanıyor ve bu ayarladığınız olmasıdır push.defaultiçin simpleo sus ulaşmak için. Kesinlikle Git hangi sürümü varsa ve var da ne ol eğer push.defaultayarlı, yaptığı henüz Git başka şikayet senin Git belirtir nedeniyle bu uzun ve sıkıcı tarihe, madde, ama sonunda, aslında sen alıyoruz olduğunu Geçmişteki hatalardan birini önlemek için yapılandırılmış.

Yukarı akış nedir?

Bir yukarı akış , bir (normal, yerel) şube ile ilişkilendirilmiş, genellikle uzaktan izleme dalı olan başka bir dal adıdır.

Her şubenin bir (1) yukarı akış setine sahip olma seçeneği vardır. Yani, her şubenin bir yukarı akışı vardır veya bir yukarı akışı yoktur. Hiçbir şubede birden fazla yukarı akış olamaz.

Memba gerektiğini , ancak olmak zorunda değildir, geçerli bir dal (gibi uzaktan izleme olsun ya da benzeri lokal ). Geçerli dalı ise kendisine, B memba sahiptir U , gerektiği çalışır. Çalışmazsa - U'nun var olmadığından şikayet ederse - o zaman Git'in çoğu yukarı akış hiç ayarlanmamış gibi davranır. Gibi birkaç komut, yukarı akış ayarını gösterecek, ancak "gitti" olarak işaretleyecektir.origin/Bmastergit rev-parse U git branch -vv

Yukarı akış ne kadar iyi?

Your veya push.defaultolarak ayarlandıysa , upstream ayarı hiçbir ek argüman olmadan kullanılacaktır, sadece çalışacaktır.simpleupstreamgit push

İşte bu - tüm yaptığı bu git push. Ancak bu oldukça önemlidir, çünkü git pushbasit bir yazım hatasının büyük baş ağrısına neden olduğu yerlerden biridir.

Eğer senin push.defaultiçin ayarlanır nothing, matchingveya current, bir kaynak tarafı ayarı tümü için de hiçbir şey yapmaz git push.

(Tüm bunlar Git sürümünüzün en az 2.0 olduğunu varsayar.)

Yukarı akış etkiler git fetch

git fetchHiçbir ek argüman olmadan çalıştırırsanız Git , geçerli dalın yukarı akışına danışarak hangi uzaktan kumandadan alınacağını belirler . Yukarı akış bir uzaktan izleme dalı ise, Git bu uzaktan kumandadan alır. (Yukarı akış ayarlanmamışsa veya yerel bir dalsa, Git getirmeyi dener origin.)

Yukarı akış etkiler git mergeve git rebasede

Ek bağımsız değişken çalıştırırsanız git mergeveya çalıştırmazsanız git rebase, Git geçerli dalın yukarı akışını kullanır. Yani bu iki komutun kullanımını kısaltır.

Yukarı akış etkiler git pull

Yine de asla 2 kullanmamalısınız git pull, ancak yaparsanız, git pullhangi uzaktan kumandadan alınacağını ve sonra hangi dalın birleştirileceğini veya yeniden bağlanacağını belirlemek için yukarı akış ayarını kullanır. Olduğunu, git pullaynı işlevi git fetchaslında -çünkü çalışır git fetch -ve daha sonra aynı şeyi yapar git mergeveya git rebaseaslında, çünkü ishal git merge veya git rebase.

(Genellikle bu iki adımı manuel olarak yapmalısınız, en azından Git'i yeterince iyi tanıyıncaya kadar, her iki adım da başarısız olduğunda, ki sonunda, neyin yanlış gittiğini anlar ve bu konuda ne yapacağınızı bilirsiniz.)

Yukarı akış etkiler git status

Bu aslında en önemlisi olabilir. Bir upstream setiniz olduğunda, git statusmevcut şubeniz ve upstream arasındaki farkı taahhütler açısından raporlayabilirsiniz.

, Normal durumda, sen dal üzerinde olan Bkendi memba set ile ve çalıştırmak size itebilir kaydedilmesini olup olmadığını hemen göreceksiniz, ve / veya yönünde birleşmek veya Rebase olabilir kaydedilmesini.origin/Bgit status

Bunun nedeni şudur git status:

  • git rev-list --count @{u}..HEAD: üzerinde olmayan kaç Bkaydetmeniz var ?origin/B
  • git rev-list --count HEAD..@{u}: üzerinde olmayan kaç kaydetmeniz var ?origin/BB

Bir yukarı akış kurmak size tüm bunları verir.

Neden masterzaten bir yukarı akış seti var?

Bir uzaktan kumandadan ilk klonladığınızda, şunu kullanarak:

$ git clone git://some.host/path/to/repo.git

ya da benzeri, Git'in yaptığı son adım, esasen şudur git checkout master. Yerel şube dışarı Bu kontroller master-sadece sen yok olması yerel bir dalı master.

Öte yandan, sen do uzaktan izleme şube adında var origin/mastersadece bunu klonlanmış çünkü.

Git sen demek olması gerektiğini tahmin: "Beni yeni bir yerel yapmak masteraynı işaret olarak uzaktan izleme taahhüt olduğunu origin/master, ve eğer bunu yaparken, için ust baş ayarlamak masteriçin origin/master."

Bu , sahip olmadığınız her dal için olur git checkout. Git dalı yaratır ve ona karşılık gelen uzaktan izleme dalını "izler" (yukarı akış olarak sahip) yapar.

Ama bunun için işi değil yeni dallar, yani uzaktan izleme şube ile dalları henüz .

Eğer bir oluşturursanız yeni şube:

$ git checkout -b solaris

henüz yok origin/solaris. Yerel solaris kutu değil uzaktan izleme şube izlemek origin/solarismevcut değil çünkü.

Yeni şubeye ilk bastığınızda:

$ git push origin solaris

O oluşturur solaris üzerinde originve dolayısıyla da yaratır origin/solariskendi Git depo. Ama çok geç: Zaten bir yerel sahip solarisolduğu hiçbir kaynak tarafı vardır . 3

Git'in bunu otomatik olarak yukarı akış olarak ayarlaması gerekmez mi?

Muhtemelen. "Kötü uygulanmış" ve dipnot 1'e bakın. Şu anda değiştirmek zor : Git kullanan milyonlarca 4 betik var ve bazıları da mevcut davranışına bağlı olabilir. Davranışı değiştirmek için yeni bir ana sürüm gerekir, nag-ware sizi bazı yapılandırma alanları ayarlamaya zorlar ve benzeri. Kısacası Git, kendi başarısının kurbanıdır: Bugün içinde yaptığı hatalar ne olursa olsun, ancak değişim ya çoğunlukla görünmez, açıkça çok daha iyi ya da zaman içinde yavaş yapılırsa düzeltilebilir.

Gerçek şu ki, kullanmadığınız veya sırasında kullanmadığınız sürece bugün değil . Mesajın size söylediği bu.--set-upstream-ugit push

Bunu böyle yapmak zorunda değilsin. Yukarıda da belirttiğimiz gibi, bunu yapmak zorunda değilsiniz, ama diyelim ki bir yukarı akış istiyorsunuz . Daha önceki bir itme yoluyla solarisüzerinde zaten dal oluşturdunuz originve git branchçıktınızın gösterdiği gibi, zaten yerel deponuza sahipsiniz origin/solaris .

Sadece bunun için yukarı akış olarak ayarlamadınız solaris.

İlk itme sırasında değil, şimdi ayarlamak için kullanın git branch --set-upstream-to. --set-upstream-toAlt komut gibi, varolan herhangi şube adını alır origin/solarisve bu diğer dalına cari şubesinin kaynak tarafı ayarlar.

Hepsi bu — hepsi bu — ama yukarıda belirtilen tüm bu çıkarımlara sahip. Bu, sadece koşabileceğiniz git fetch, sonra etrafınıza bakabileceğiniz, sonra koşabileceğiniz git mergeveya git rebaseuygun şekilde koşabileceğiniz , sonra yeni taahhütler yapabileceğiniz ve git pushbir sürü ek karışıklık olmadan koşabileceğiniz anlamına gelir .


1 Dürüst olmak gerekirse, ilk uygulamanın hataya açık olduğu o zamanlar net değildi. Bu ancak her yeni kullanıcı her seferinde aynı hataları yaptığında netleşti. Şimdi "daha az fakir", bu "harika" demek değil.

2 "Asla" biraz güçlü, ama Git yeni başlayanlarının adımları ayırdığımda, özellikle de onlara git fetchgerçekte ne yaptığını gösterebildiğimde ve sonra ne yapacağını git mergeveya ne git rebaseyapacaklarını görebildiklerinde , her şeyi çok daha iyi anladıklarını görüyorum .

3 İlk git push olarak çalıştırırsanız git push -u origin solaris—yani, -ubayrağı eklerseniz — Git origin/solaris, itme başarılı olursa (ve ancak) geçerli dalınız için yukarı akış olarak ayarlanır . Böylece tedarik etmelidir -uüzerinde ilk itme. Aslında, daha sonraki herhangi bir itmede tedarik edebilirsiniz ve bu noktada yukarı akışı ayarlayacak veya değiştirecektir . Ama git branch --set-upstream-tounuttuysan daha kolay olduğunu düşünüyorum .

4 Austin Powers / Dr Evil yöntemi ile basitçe "bir MILLLL-YUN" demekle ölçülmüştür.


2
Yaygın durum, {şube oluştur / dal gönder / şube kullan} ise, yeni bir yerel şubeyi uzak bir Git deposuna gönder ve onu da izlemenin gerçekten çalışan bir şey olması gerekmez mi? Ve eğer birisi {create branch / push branch / don't use branch} istiyorsa, o zaman özel bir şey yapmaları gerekmez --set-upstream /dev/nullmi? Yük neden ortak duruma itiliyor? Bu mühendislik ve kullanılabilirlik kararlarından bazılarını gerçekten anlamıyorum.
jww

1
@VonC: sağ, ana fikri git push -u, ama gerçekten gibi görünüyor git push -uvarsayılan olmalı veya varsayılan en azından hiçbir orada yönünde yukarısında ise henüz ve orada olmalı git push --no-set-upstreamşu anda bir yukarı akış olmadığında ve saklamak istediğiniz bu şekilde (anlaşılmaz sebep ne olursa olsun :-)).
torek

2
"Böyle sorular sormaya devam ediyorsun çünkü bence Git'i" gerçekten iğrenç "olarak yazmışsın." Lütfen bu tür spekülasyonları kendinize saklayın. Bu soruyla karşılaştım çünkü kendime bu tür sorular sormaya devam ediyorum. Dünyanın en iyi UX tasarımcısı değilim, ancak ben bile bu senaryodaki varsayılan davranışın daha iyi olabileceğini kabul ediyorum.
Steven Byks

4
@torek - Teşekkürler. Cevabınız başka türlü harikaydı; iyi düşünülmüş, iyi yapılandırılmış ve son derece bilgilendirici. :-)
Steven Byks

6
Bunun yapılandırılabilir olduğunu unutmayın. Bunu yaparsanız git config --add push.default currentgit push, gerekirse uzak depoda şubeyi otomatik olarak oluşturacaktır.
Gogowitsch

31

Aradaki fark
git push origin <branch>
ve arasındaki fark
git push --set-upstream origin <branch>
, her ikisinin de uzaktaki depoya gayet iyi bir şekilde itmesidir, ancak çektiğinizde farkı fark edersiniz.

Eğer yaparsanız:
git push origin <branch>
çekerken yapmanız gerekenler:
git pull origin <branch>

Ama yaparsanız:
git push --set-upstream origin <branch>
o zaman, çekerken yapmanız gereken tek şey:
git pull

Bu nedenle --set-upstream, yaptığınız her seferinde hangi dalı çekmek istediğinizi belirtmenize gerek kalmaz git pull.


"git push" nin iki versiyonu arasındaki farkı neden kullanmak istediğimi / kullanmak istediğimi bilmiyorum. Anlamsız!
Frank Puck

17

Temelde tam bir komut gibidir git push <remote> <local_ref>:<remote_ref>. Sadece git pushkoşarsanız, git'in bir karar vermesine yardımcı olacak bazı yapılandırmalar yapmadığınız sürece git tam olarak ne yapacağını bilemez. Bir git deposunda birden fazla uzaktan kumanda kurabiliriz. Ayrıca herhangi bir uzak referansa yerel bir ref gönderebiliriz. Tam komut, itme yapmanın en basit yoludur. Daha az kelime yazmak istiyorsanız, önce --set-upstream gibi yapılandırmanız gerekir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.