Чому я повинен "git push --set-upstream origin <branch>"?


146

Я створив місцеве відділення для тестування Solaris та Sun Studio. Потім я штовхнув гілку вгору за течією. Після внесення змін та спроби змінити їх:

$ 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

Чому я повинен зробити для цього щось особливе?

Чи є якийсь розумний випадок використання, коли хтось створив би <branch>, натисніть <branch>на віддалений, а потім заявити про зобов’язання <branch>не слід <branch>?


Я дотримувався цього питання та відповіді на "Переповнення стека:" Перемістіть нову локальну гілку до віддаленого сховища Git і відстежте її також . Я здогадуюсь, що це ще один приклад неповної або неправильно прийнятої відповіді. Або ще один його примірник, коли Git приймає просте завдання і ускладнює його.


Ось перегляд на іншій машині. Гілка чітко існує, тому її створили і просунули:

$ 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
Дякую @Alexi На жаль, цитований дуб не пояснює смішний випадок використання, який представлений за замовчуванням. (Це не риторичні питання. Я щиро зацікавлений в причині дизайну UX).
jww

1
Зауважте, що це налаштовується. Якщо ви це зробите git config --add push.default current, то git push автоматично створить гілку у віддаленому репо, якщо це необхідно.
Гогович

Відповіді:


271

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


Відповідь на поставлене вами запитання - яке я перефразую трохи як "чи я повинен встановити висхідний потік" - це: ні, вам взагалі не потрібно встановлювати вище.

Якщо у вас немає поточної версії для поточної гілки, Git змінює свою поведінку на git pushта інші команди.

Повна сюжетна історія тут довга і нудна і входить в історію до версії 1.5 Git. Щоб скоротити його цілком багато, git pushбуло реалізовано погано. 1 Станом на Git версії 2.0, Git тепер має ручку конфігурації, push.defaultяку тепер написано за замовчуванням simple. Для декількох версій Git до та після 2.0, кожного разу, коли ви бігали git push, Git видає багато шуму, намагаючись переконати вас налаштуватись push.defaultлише git pushна заткнення.

Ви не згадуєте, яку версію Git використовуєте, а також не конфігурували push.default, тому ми мусимо здогадатися. Я припускаю, що ви використовуєте Git версії 2-точка-то, і що ви встановили push.defaultдля , simpleщоб змусити його замовкнути. Саме ця версія Git у вас є, і що, якщо все, що ви push.defaultвстановили, має значення через цю довгу і нудну історію, але, врешті-решт, той факт, що ви отримуєте ще одну скаргу від Git, означає, що ваш Git є налаштований, щоб уникнути однієї з помилок минулого.

Що таке вище за течією?

Верхній потік - це просто інша назва гілки, зазвичай це відділення дистанційного відстеження, пов'язане з (звичайною, локальною) гілкою.

Кожна гілка має можливість встановити один (1) набір потоку. Тобто кожна гілка або має висхідну, або не має висхідної. Жодна гілка не може мати більше одного вище за течією.

Верхній потік повинен , але не повинен бути дійсною гілкою (незалежно від віддаленого відстеження або локального ). Тобто, якщо нинішня гілка Вorigin/Bmaster має верхню частину U , повинна працювати. Якщо він не працює - якщо він скаржиться на те, що U не існує, - більшість Git діє так, ніби вихідний потік взагалі не встановлений. Декілька команд, як-от , показуватимуть налаштування верхнього потоку, але позначають його як "пропало".git rev-parse U git branch -vv

Що хорошого вгору за течією?

Якщо ваш параметр push.defaultвстановлений на simpleабо upstream, налаштування верхнього потоку змушує git pushвикористовуватись без додаткових аргументів, просто працювати.

Це все - це все, для чого це потрібно git push. Але це досить важливо, оскільки git pushце одне з місць, коли простий друк викликає великі головні болі.

Якщо ти push.default встановлений в положення nothing, matchingабо current, встановивши вгору по течії взагалі нічого не робить все для git push.

(Все це припускає, що версія Git принаймні 2.0.)

Вгору за течією впливає git fetch

Якщо ви git fetchне працюєте без додаткових аргументів, Git з'ясовує якого віддаленого підключитися, проконсультувавшись із поточною гілкою вище за течією. Якщо висхідний потік є гілкою віддаленого відстеження, Git отримує з цього віддаленого. (Якщо вхідний потік не встановлений або є локальною гілкою, Git намагається отримати origin.)

Вгору за течією впливає git merge і git rebaseтеж

Якщо ти біжиш git merge або git rebaseне маєте додаткових аргументів, Git використовує поточну гілку потоку. Так це скорочує використання цих двох команд.

Вгору за течією впливає git pull

Ніколи не слід використовувати 2git pull , але якщо ви це зробите, git pullвикористовуйте налаштування верхнього потоку, щоб визначити, з якого віддаленого для отримання, а потім з якої гілки об'єднатись або перезавантажитись. Тобто git pullробить те саме, що і git fetchтому, що воно фактично працює, git fetch і потім робить те саме, що git mergeабо git rebase, тому що воно працює git merge або git rebase.

(Зазвичай ви повинні просто виконати ці два кроки вручну, принаймні, поки ви не знаєте Git достатньо добре, що коли не вдасться жоден крок, який, в кінцевому підсумку, ви визнаєте, що пішло не так і знаєте, що з цим робити.)

Вгору за течією впливає git status

Це насправді може бути найважливішим. Після того, як у вас буде встановлений вихідний потік, ви git statusможете повідомити про різницю між вашою поточною філією та її верхнім потоком у перерахунку на коміти.

Якщо, як у звичайному випадку, ви знаходитесь на гілці Bз встановленим вище потоком , і ви запускаєте , ви відразу побачите, чи є у вас коміти, на які ви можете натиснути, та / або зобов’язуєтесь ви можете об'єднатись або перезавантажитись.origin/Bgit status

Це тому, що git statusпрацює:

  • git rev-list --count @{u}..HEAD: скільки комісій у вас немає, на Bякі немає ?origin/B
  • git rev-list --count HEAD..@{u}: скільки комісій у вас немає, на які немає ?origin/BB

Налаштування вище за течією дає вам усе це.

Як це masterвже встановлено набір вище?

Коли ви вперше клонуєте з якогось віддаленого пристрою, використовуючи:

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

або аналогічний, останній крок Git робить це, по суті, git checkout master. Це перевірка з вашого місцевого відділення master-тільки НЕ мають місцеве відділенняmaster .

З іншого боку, у вас дійсно є пульт дистанційного спостереження філії по імені origin/master, тому що ви просто клонувати його.

Git передбачає , що ви повинні мати в виду: «змусити мене новий локальний , masterщо вказує на те передай як віддалений-трекінг origin/master, і, в той час як ви на нього, встановити вгору по течії для masterдо origin/master

Це трапляється для кожної галузі, git checkoutякої ви ще не маєте. Git створює гілку і змушує її "відстежувати" (мати як висхідний потік) відповідну гілку віддаленого відстеження.

Але це не працює для нових галузей, тобто, філій, які не мають віддаленого відстеження галузі до сих пір .

Якщо ви створили нову гілку:

$ git checkout -b solaris

є, поки що, немає origin/solaris. Ваш локальний solaris не може відслідковувати відділення віддаленого відстеження, origin/solarisоскільки його немає.

Під час першого натискання нової гілки:

$ git push origin solaris

що створює solaris на origin, і , отже , також створює origin/solarisв вашому власному репозиторії Git. Але вже пізно: у вас вже є локальний solaris, у якого немає потоку . 3

Чи не повинен Git просто встановити це, як зараз, як висхідний потік автоматично?

Ймовірно. Дивіться «реалізовані погано» і виноска 1. Це важко змінити в даний час : Є мільйони 4 сценаріїв , які використовують Git і деякі цілком можуть залежати від його поточного поведінки. Зміна поведінки вимагає нового основного випуску, nag-ware, щоб змусити вас встановити якесь поле конфігурації тощо. Коротше кажучи, Гіт є жертвою власного успіху: які б помилки в ньому не було, сьогодні можна виправити лише якщо зміни є переважно невидимими, явно-набагато кращими, або робляться повільно з часом.

Справа в тому, що це не сьогодні, якщо ви не використовуєте --set-upstreamабо -uпід час використання git push. Ось що вам повідомляє повідомлення.

Вам не потрібно робити це так. Ну, як ми зазначали вище, вам зовсім не потрібно це робити, але скажімо, що ви хочете вище за течією. Ви вже створили відділення solarisза originдопомогою попереднього натискання, і як git branchпоказує результат, ви вже є origin/solaris у вашому локальному сховищі.

Ви просто не встановлюєте його як вихідний потік для solaris.

Щоб встановити його зараз, а не під час першого натискання, використовуйте git branch --set-upstream-to. --set-upstream-toСуб-команда бере ім'я будь-якого існуючого філії, наприклад origin/solaris, і встановлює вгору по течії поточної гілки до цієї іншої галузі.

Це все - це все, що він робить, - але це все, що було зазначено вище. Це означає, що ви можете просто бігти git fetch, потім озирнутися, потім запустити git mergeабо, git rebaseяк годиться, потім зробити нові зобов’язання та запустити git push, не купуючи додаткових метушні.


1 Щоб бути справедливим, не було ясно тоді , що первісна реалізація була схильна до помилок. Це стало зрозуміло лише тоді, коли кожен новий користувач щоразу робив однакові помилки. Зараз це "менш бідно", що не можна сказати "чудово".

2 "Ніколи" трохи не сильний, але я вважаю, що новачки в Git розуміють речі набагато краще, коли я відокремлюю кроки, особливо коли я можу показати їм, що git fetchнасправді зробив, і вони зможуть побачити, що git mergeчи git rebaseробити далі.

3 Якщо ви запускаєте перше git push як git push -u origin solaris—еее, якщо ви додасте -uпрапор — Git встановить origin/solarisяк верхній потік для вашої поточної гілки, якщо (і лише якщо) натискання буде успішним. Тож вам слід подати -uз першого поштовху. Насправді, ви можете поставити його в будь-який наступний натиск, і він встановить або змінить вгору по течії в цій точці. Але я думаю git branch --set-upstream-to, що простіше, якщо ти забув.

4 Виміряний методом Остін держав / д-р Злого методом просто сказати «один МІЛЛЛ-ЮН».


2
Якщо загальний випадок - {створити гілку / push гілку / використовувати гілку}, то чи не слід результат " Перемістити нову локальну гілку" у віддалене сховище Git і відстежити, що це теж щось, що насправді працює? І якщо хтось хоче {створити гілку / push гілку / не використовувати гілку}, то чи не повинні вони робити щось особливе, наприклад --set-upstream /dev/null? Чому тягар покладається на загальну справу? Я дійсно не розумію деяких цих інженерних та зручних зручностей.
jww

1
@VonC: Добре, що це точка git push -u, але це дійсно здається , що git push -uповинно бути за замовчуванням, або , по крайней мере , за замовчуванням , якщо там немає вгору по течії ще й має бути , git push --no-set-upstreamколи немає в даний час вгору по течії , і ви хочете зберегти саме так (з незрозумілої причини :-)).
торек

2
"Ви постійно запитуєте подібні запитання, тому що, я думаю, ви списали Git як" справді неприємний "." Будь ласка, тримайте подібні міркування для себе. Я натрапив на це питання, тому що я також постійно задаю собі подібні запитання. Я не найкращий у світі дизайнер UX, але навіть я усвідомлюю, що поведінка за замовчуванням у цьому конкретному сценарії може бути кращою.
Стівен Бикс

4
@torek - Дякую Ваша відповідь була інакше фантастичною; добре продуманий, добре структурований і надзвичайно інформативний. :-)
Стівен Бикс

6
Зауважте, що це налаштовується. Якщо ви це зробите git config --add push.default current, то git push автоматично створить гілку у віддаленому репо, якщо це необхідно.
Гогович

31

Різниця між тим
git push origin <branch>
і
git push --set-upstream origin <branch>
полягає в тому, що вони обидва добре просуваються до віддаленого сховища, але коли ви витягуєте, то помічаєте різницю.

Якщо ви робите:
git push origin <branch>
підтягуючи, ви повинні:
git pull origin <branch>

Але якщо ви це робите:
git push --set-upstream origin <branch>
тоді, підтягуючи, вам потрібно лише зробити:
git pull

Таким чином, додавання в дозволі --set-upstreamдозволяє не вказувати, яку галузь ви хочете витягнути з кожного разу, що ви робите git pull.


різниця між двома версіями "git push", які я не знаю, чому я б хотів / потребував їх використовувати. Безглуздо!
Френк Пук

17

В основному повна команда - це як git push <remote> <local_ref>:<remote_ref>. Якщо ви працюєте просто git push, git не знає, що саме робити, якщо ви не зробили якусь конфігурацію, яка допомагає git приймати рішення. У git repo ми можемо налаштувати декілька віддалених. Також ми можемо підштовхнути локальний номер до будь-якого віддаленого списку. Повна команда - це найпростіший спосіб зробити поштовх. Якщо ви хочете ввести менше слів, вам слід спочатку налаштувати, наприклад, --set-upstream.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.