Зачем вызывать git branch --unset-upstream для исправления?


161

Я больше новичок, когда дело доходит до продвинутых операций в git. Я веду свой блог, используя фреймворк для ведения блогов Octopress . Хотя Octopress не разрабатывается с 2011 года, он хорошо служит моей цели, и поэтому я пока не думал ничего менять.

К вашему сведению, мой блог размещен на Github Pages.

Сегодня, работая над новым постом, git statusпоказало следующее сообщение:

On branch source
Your branch is based on 'origin/master', but the upstream is gone.
  (use "git branch --unset-upstream" to fixup)

То же сообщение повторяется для всех последующих команд, таких как git add ., git commit -m 'message'и git push origin source.

  • Что означает сообщение?
  • Что-то сломано?
  • Если да, то что?
  • Нужно ли это исправить?

Если возможно, пожалуйста, укажите мне в pdf / веб-статью, где я могу прочитать об этом и понять это на будущее.

Больше деталей:

bash-3.2$ git branch -a
* source
  remotes/octopress/2.1
  remotes/octopress/HEAD -> octopress/master
  remotes/octopress/gh-pages
  remotes/octopress/linklog
  remotes/octopress/master
  remotes/octopress/refactor_with_tests
  remotes/octopress/rubygemcli
  remotes/octopress/site
  remotes/origin/source

Пожалуйста, дайте мне знать, если вам нужна дополнительная информация. Спасибо.

Ответы:


197

TL; версия DR: ветвь удаленного отслеживания origin/masterраньше существовала, но не существует, поэтому локальная ветвь sourceотслеживает то, чего не существует, что в лучшем случае подозрительно - это означает, что другая функция Git не может ничего сделать для вас - и Git предупреждает вас об этом. Вы прекрасно ладили, не имея функции «отслеживания вверх по течению», как задумано, так что решать, стоит ли что-то менять.

Для другого взгляда на настройки upstream см. Почему мне нужно «git push --set-upstream origin <branch>»?


Это предупреждение - новая вещь в Git, появившаяся сначала в Git 1.8.5. Примечания к выпуску содержат только один короткий пункт об этом:

  • «git branch -v -v» (и «git status») не делали различий между ветвью, которая не основана ни на какой другой ветке, ветвью, которая синхронизирована с ее восходящей веткой, и веткой, которая настроена с восходящей веткой ветвь, которая больше не существует.

Чтобы описать, что это значит, вам сначала нужно знать о «удаленных», «ветках удаленного отслеживания» и о том, как Git обрабатывает «отслеживание восходящего потока». ( Ветви удаленного отслеживания - ужасно некорректный термин - вместо этого я начал использовать имена удаленного отслеживания , что, я думаю, является небольшим улучшением. Ниже, однако, я буду использовать «ветку удаленного отслеживания» для согласованности с документацией Git. )

Каждый «удаленный» - это просто имя, как originили octopressв этом случае. Их целью является запись таких вещей, как полный URL-адрес тех мест, из которых вы git fetchили git pullобновляетесь. Когда вы используете 1 Git, он переходит на этот пульт (используя сохраненный URL) и переносит соответствующий набор обновлений. Он также записывает обновления, используя «удаленное отслеживание веток».git fetch remote,

«Ветвь удаленного отслеживания» (или имя удаленного отслеживания) - это просто запись имени ветви, которое последний раз видели на каком-то «удаленном». Каждый пульт является Git-репозиторием, поэтому у него есть ветки. Ветви на удаленном «источнике» записываются в вашем локальном хранилище под remotes/origin/. Текст , который вы показали , говорит , что есть филиал имени sourceна origin, и ветви по имени 2.1, linklogи так далее на octopress.

(Конечно, «нормальная» или «локальная» ветвь - это просто имя ветки, которое вы создали в своем собственном хранилище.)

Наконец, вы можете настроить (локальную) ветку, чтобы «отслеживать» «ветку удаленного отслеживания». Как только локальная ветвь Lнастроена на отслеживание ветки удаленного отслеживания R, Git будет вызывать Rее «восходящий поток» и сообщать вам, «находитесь ли вы впереди» и / или «позади» восходящего потока (с точки зрения принятия). Обычно (даже рекомендуется) для локальных филиалов и филиалов с удаленным отслеживанием использовать одно и то же имя (за исключением части с префиксом удаленного доступа), например sourceи origin/source, но это на самом деле не обязательно.

И в этом случае этого не происходит. У вас есть местное отделение, которое sourceотслеживает удаленное отслеживание origin/master.

Вам не нужно знать точную механику того, как Git устанавливает локальную ветку для отслеживания удаленной, но они актуальны ниже, поэтому я покажу, как это работает. Начнем с названия вашей местной ветки source. Есть две записи конфигурации, использующие это имя, пишется branch.source.remoteи branch.source.merge. Из вывода, который вы показали, ясно, что они оба установлены, так что вы увидите следующее, если выполните указанные команды:

$ git config --get branch.source.remote
origin
$ git config --get branch.source.merge
refs/heads/master

Собираем их вместе, 2 это говорит о том, что Git ваша ветка sourceотслеживает «удаленного отслеживания ветви», origin/master.

Но теперь посмотрим на вывод git branch -a, который показывает все локальные и удаленные имена веток в вашем хранилище. Имена удаленного отслеживания перечислены под remotes/... и нетremotes/origin/master . Предположительно, было когда-то, но теперь это ушло.

Git сообщает вам, что вы можете удалить информацию об отслеживании --unset-upstream. Это очистит branch.source.originи branch.source.merge, и, и остановит предупреждение.

Вполне вероятно, что вам нужно переключиться с отслеживания origin/masterна отслеживание чего-то другого: возможно origin/source, но, возможно, одного из octopress/названий.

Вы можете сделать это с git branch --set-upstream-to, 3 , например:

$ git branch --set-upstream-to=origin/source

(Предполагая, что вы все еще находитесь в "источнике" ветки, и это origin/sourceтот восходящий поток, который вы хотите - у меня нет никакого способа сказать, какой из них, если он есть, вы действительно хотите, хотя)

(Смотрите также Как сделать, чтобы существующая ветка Git отслеживала удаленную ветку? )

Я думаю, что вы получили здесь то, что, когда вы впервые сделали git clone, у клонированной вещи была ветвь master. У вас также была ветка master, которая была настроена на отслеживание origin/master(это нормальная стандартная настройка для git). Это означало, что у вас было branch.master.remoteи branch.master.mergeустановлено, чтобы originи refs/heads/master. Но затем ваш originпульт изменил свое имя с masterна source. Чтобы соответствовать, я думаю, вы также изменили свое местное имя с masterна source. Это изменило имена ваших настроек, с branch.master.remoteна branch.source.remoteи с branch.master.mergeна branch.source.merge... но оставило старые значения , так что branch.source.mergeтеперь было неправильно.

Именно в этот момент связь «вверх по течению» прервалась, но в версиях Git старше 1.8.5 Git никогда не замечал нарушенных настроек. Теперь, когда у вас есть 1.8.5, это указывает на это.


Это охватывает большинство вопросов, но не вопрос «нужно ли мне это исправить». Вполне вероятно, что вы уже много лет работаете над разрушением, например ( ). Если вы продолжите это делать, это продолжит работать над проблемой - так что нет, вам не нужно ее исправлять. Если хотите, вы можете использовать для удаления восходящего потока и прекращения жалоб, и не иметь пометки в местном отделении как имеющего какой-либо восходящий поток.git pull remote branchgit pull origin source--unset-upstreamsource

Смысл восходящего потока - сделать различные операции более удобными. Например, git fetchследует, git mergeчто обычно «делает правильные вещи», если восходящий поток настроен правильно, а git statusпосле git fetchсообщит вам, соответствует ли ваш репо восходящему, для этой ветви.

Если вы хотите удобство, переустановите апстрим.


1git pull использует git fetch, а с Git 1.8.4 это (наконец-то!) Также обновляет информацию об «ветке удаленного отслеживания». В более старых версиях Git обновления не записывались в ветки удаленного отслеживания с помощью git pullтолько git fetch. Поскольку ваш Git должен быть как минимум версии 1.8.5, это не проблема для вас.

2 Ну, это плюс строка конфигурации, которую я намеренно игнорирую remote.origin.fetch. Git должен сопоставить имя «слияния», чтобы выяснить, что полное локальное имя для удаленной ветки есть refs/remotes/origin/master. Отображение почти всегда работает так же, как это, так что это предсказуемо, что masterидет origin/master.

3 Или с git config. Если вы просто хотите установить апстрим к origin/sourceединственной части, которая должна быть изменена branch.source.merge, и git config branch.source.merge refs/heads/source сделает это. Но --set-upstream-toговорит, что вы хотите сделать, а не заставлять вас делать это вручную, так что это «лучший способ».


3
+1 для «Если вы хотите, вы можете использовать --unset-вверх по течению , чтобы местное отделение отмечены как не имеющие какой - либо вверх по течению на всех.»
Беатрис

157

Ответ Торека, вероятно, идеален, но я просто хотел, чтобы в отчете было упомянуто другое дело, отличное от описанного в исходном вопросе, но может появиться та же ошибка (так как это может помочь другим с подобной проблемой):

Я создал пустой (новый) репо git init --bareна одном из моих серверов. Затем я git cloneсделал это в локальной рабочей области на моем ПК.

После совершения одной версии в локальном репо я получил эту ошибку после вызова git status.

После ответа Торека я понимаю, что в результате первого коммита локального репозитория рабочего каталога была создана «главная» ветка. Но в удаленном репо (на сервере) ничего не было, поэтому даже не было ветки "master" (remotes / origin / master).

После запуска git push origin master из локального репо, в удаленном репо наконец появилась основная ветка. Это остановило ошибку от появления.

Итак, в заключение - такую ​​ошибку можно получить для нового нового удаленного репо с нулевым коммитом, поскольку у него нет ветки, включая «master».


6
Это в настоящее время номер 1 для этого сообщения об ошибке, On branch source Your branch is based on 'origin/master', but the upstream is gone. (use "git branch --unset-upstream" to fixup)и, хотя оно и субъективно, более вероятно, что оно будет вызвано клонированием пустого репозитория, настолько хорошего, что здесь есть альтернативный ответ.
Белла

2
Я думаю, поэтому всегда полезно инициализировать ваш новый репозиторий с помощью файла README.md, даже если это пустой файл
Ахмед Хуссейн,

8

Это может решить вашу проблему.

после внесения изменений вы можете зафиксировать его, а затем

git remote add origin https://(address of your repo) it can be https or ssh
then
git push -u origin master

надеюсь, что это работает для вас.

Спасибо


1
Это действительно помогло бы - причина подробно описана в моем ответе (Короче говоря, это создает недостающую главную ветку в удаленном репо).
ElazarR

7

Для меня .git/refs/origin/masterиспортился.

Я сделал следующее, что исправило проблему для меня.

rm .git/refs/remotes/origin/master
git fetch
git branch --set-upstream-to=origin/master

0

На самом деле Торек уже говорил вам, как использовать инструменты гораздо лучше, чем я мог бы сделать. Тем не менее, в этом случае я думаю, что важно указать на что-то своеобразное, если вы будете следовать инструкциям на http://octopress.org/docs/deploying/github/ . А именно, у вас будет несколько репозиториев github в вашей настройке. Сначала один со всем исходным кодом для вашего сайта, скажем, в каталоге $WEBSITE, а затем тот, в котором находятся только статические сгенерированные файлы $WEBSITE/_deploy. Самое смешное в настройке - это то, что .gitignoreв$WEBSITE так что эта настройка действительно работает.

Достаточно введения. В этом случае ошибка также может исходить из хранилища в _deploy.

cd _deploy

git branch -a
* master
remotes/origin/master
remotes/origin/source

У .git/configвас обычно нужно найти что-то вроде этого:

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
[remote "origin"]
    url = git@github.com:yourname/yourname.github.io.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
    remote = origin
    merge = refs/heads/master

Но в вашем случае у мастера ветки нет пульта.

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
[remote "origin"]
    url = git@github.com:yourname/yourname.github.io.git
    fetch = +refs/heads/*:refs/remotes/origin/*

Что вы можете решить с помощью:

cd _deploy
git branch --set-upstream-to=origin/master

Итак, все так, как сказал вам Торек, но, возможно, важно отметить, что это вполне может касаться _deployкаталога, а не корня вашего сайта.

PS: Возможно, стоит использовать оболочку, например, zshс gitплагином, чтобы не быть укушенным этой вещью в будущем. Это сразу покажет, что _deployкасается другого хранилища.


0

У меня был этот вопрос дважды, и он всегда был вызван повреждением файла кэша git в моей локальной ветке. Я исправил это, записав недостающий хеш коммита в этот файл. Я получил правильный хеш коммита с сервера и локально выполнил следующую команду:

cat .git/refs/remotes/origin/feature/mybranch \
echo 1edf9668426de67ab764af138a98342787dc87fe \
>> .git/refs/remotes/origin/feature/mybranch

0

Проблема: ваша ветка основана на 'origin / master', но восходящий поток исчез.

Решение: git branch --unset-upstream


3
Добро пожаловать в stackoverflow. Вопрос не в том, как исправить ошибку, он хочет знать, почему возникает эта ошибка и должен ли он что-то с этим делать. Пожалуйста, укажите это в своем ответе.
cronoik

0

удалите свою локальную ветку с помощью следующей команды

git branch -d branch_name

Вы могли бы также сделать

git branch -D branch_name 

который в основном вызывает удаление (даже если локальный не объединен с источником)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.