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

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

FYI, мой блог размещен на страницах Github.

Сегодня, работая над новым сообщением, 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/web, где я могу прочитать об этом и понять ее на будущее.

Подробнее:

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

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

Ответ 1

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 updates. Когда вы используете git fetch remote, 1 Git переходит на этот пульт (используя сохраненный URL) и выводит соответствующий набор обновлений. Он также записывает обновления, используя "удаленное отслеживание веток".

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

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

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

И в этом случае этого не происходит. У вас есть локальный 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 branch (например, git pull origin source). Если вы продолжите это делать, это продолжит работать над проблемой - так что нет, вам не нужно ее исправлять. При желании вы можете использовать --unset-upstream чтобы удалить --unset-upstream и остановить жалобы, а локальный source ответвления не будет помечен как имеющий --unset-upstream вообще.

Смысл восходящего потока состоит в том, чтобы сделать различные операции более удобными. Например, git fetch за которым следует git merge, как правило, "делают правильные вещи", если восходящий поток настроен правильно, и git status git fetch после 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. Если вы просто хотите установить upstream на origin/source единственная часть, которая должна быть изменена, это branch.source.merge, и git config branch.source.merge refs/heads/source сделает это. Но --set-upstream-to говорит, что вы хотите сделать, вместо того, чтобы заставлять вас делать это вручную, так что "лучший путь".

Ответ 2

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

Я создал пустое (новое) репо с помощью git init --bare на одном из моих серверов. Тогда у меня есть git clone d it в локальной рабочей области на моем ПК.

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

После ответа torek я понимаю, что произошло то, что первая фиксация в локальном рабочем каталоге репо создала ветвь "master". Но на удаленном репо (на сервере) ничего не было, поэтому не было даже "ведущей" (удаленной/исходной/основной) ветки.

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

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

Ответ 3

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

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

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

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

спасибо

Ответ 4

Для меня .git/refs/origin/master был поврежден.

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

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

Ответ 5

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

Достаточное введение. В этом случае ошибка может также возникнуть из репозитория в _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 = [email protected]: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 = [email protected]: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 относится к другому репозиторию.

Ответ 6

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

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

Ответ 7

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

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

Ответ 8

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

git branch -d branch_name

вы также можете сделать

git branch -D branch_name 

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