Почему git status показывает, что ветка актуальна, когда есть изменения в апстриме?

226

В отслеживаемой ветви есть изменения, расположенные вверх по течению, но когда я печатаю, git statusэто означает, что моя локальная ветвь обновлена. Это новое поведение, я изменил настройку конфигурации, или что-то не так?

Спасибо за помощь.

ubuntu@host:/my/repo# git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working directory clean


ubuntu@host:/my/repo# git pull
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 11 (delta 6), reused 0 (delta 0)
Unpacking objects: 100% (11/11), done.
From bitbucket.org:my/repo
   1234567..abcdefg  master     -> origin/master
Updating 1234567..abcdefg
Fast-forward
 file1        |  1 -
 file2        | 43 +++++++++++++++++++++++++++++++++++++++++++
 file3        | 21 ++++++++++++---------
 file4        | 21 ++++++++++++---------
 4 files changed, 67 insertions(+), 19 deletions(-)
 create mode 100644 file5
GregB
источник

Ответы:

274

Статус говорит вам о том, что вы находитесь за реф-коллом, origin/master который является локальным рефоном в вашем локальном репо . В этом случае этот ref отслеживает ветку в некотором удаленном, вызываемом origin, но состояние ничего не говорит вам о ветке на удаленном. Он рассказывает вам о ссылке, которая является просто идентификатором фиксации, хранящимся в вашей локальной файловой системе (в данном случае обычно это файл, называемый .git/refs/remotes/origin/masterв вашем локальном репо).

git pullделает две операции; сначала выполняется git fetchобновление с коммитами в удаленном репо (которое обновляет origin/masterссылку в вашем локальном репо), затем выполняется git mergeслияние коммитов с текущей веткой.

Пока вы не выполните этот fetchшаг (самостоятельно или через git pull), ваше локальное хранилище не сможет узнать, что есть дополнительные коммиты в восходящем потоке, и git statusтолько смотрит на ваш локальный origin/masterреф.

Когда git statusговорится актуальный, это означает «актуальный с веткой, которую отслеживает текущая ветвь», что в данном случае означает «актуальный с локальным реф вызванным origin/master». Это приравнивается только к «текущему статусу восходящего потока, который был получен в прошлый раз, когда мы сделали fetch», что не совпадает с «текущим последним статусом восходящего потока».

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

Создание и переключение веток (и проверка их состояния) в Git должно быть облегченным, а не тем, что выполняет медленную сетевую работу с централизованной системой. При проектировании Git и его git statusвывода предполагалось , что пользователи это понимают (слишком много функций Git имеют смысл, только если вы уже знаете, как работает Git). С принятием Git многими и многими пользователями, которые не знакомы с DVCS, это предположение не всегда верно.

Джонатан Уэйкли
источник
79
Поздний комментарий, но я столкнулся с той же ситуацией. Я понимаю, почему git не может узнать об изменениях до загрузки. Но тогда не следует говорить «в курсе», что просто не соответствует действительности. Лучше сказать: «Понятия не имею, что могло случиться удаленно».
Дроидум
31
Может быть, это строго логично, но это совсем не разумно для человека. Почему бы вам не спроектировать его, чтобы сделать выборку, а затем объявить, что она актуальна? Или измените сообщение, чтобы сказать, что оно действительно сделало, например, «Ваша ветка была обновлена ​​с« origin / master », когда последний раз проверялась в {timestamp}»? Или даже просто сказать: «Сделайте выборку, чтобы узнать, актуальна ли ваша ветка»?
Колин май
25
зачем вообще показывать сообщение "Ваша ветка актуальна"? Я не вижу смысла в знании статуса источника / мастера, и если он должен представлять фактическую главную ветвь на удаленном источнике, то он явно не имеет никакого представления.
whiterook6
2
@pastullo, поэтому создайте псевдоним.
Джонатан
23
Это прекрасный пример ужасного удобства использования Git. Мне нравится его мощь и гибкость, но я просто изменяю сообщение на что-то вроде «Ваша ветка обновлена ​​с локальной версией« origin / master »». было бы огромным улучшением. Путаница заключается в том, что источник / мастер локальной ветки (шаблон соответствует любым удаленным веткам / веткам, которые вы используете), который отслеживает удаленную ветку.
matthewcummings516
35

Это потому, что ваш локальный репозиторий не зарегистрировался с вышестоящими пультами. Чтобы эта работа работала так, как вы ожидаете, используйте и git fetchзапустите git statusснова.

Райан
источник
7

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

git remote show origin

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

  * remote origin
  Fetch URL: https://github.com/xxxx/xxxx.git
  Push  URL: https://github.com/xxxx/xxxx.git
  HEAD branch: master
  Remote branches:
    master      tracked
    no-payments tracked
  Local branches configured for 'git pull':
    master      merges with remote master
    no-payments merges with remote no-payments
  Local refs configured for 'git push':
    master      pushes to master      (local out of date)
    no-payments pushes to no-payments (local out of date)

Надеюсь, это кому-нибудь поможет.

Skycube
источник
0

«origin / master» относится к ссылке, указывающей на коммит HEAD ветви «origin / master». Ссылка - это понятное человеку имя псевдонима для объекта Git, обычно это объект фиксации. Ссылка «origin / master» обновляется только когда вы подключены git pushк удаленному устройству ( http://git-scm.com/book/en/v2/Git-Internals-Git-References#Remotes ).

В корне вашего проекта запустите:

cat .git/refs/remotes/origin/master

Сравните отображаемый идентификатор фиксации с:

cat .git/refs/heads/master

Они должны быть одинаковыми, и именно поэтому Git говорит, masterчто он в курсе origin/master.

Когда ты бежишь

git fetch origin master

Это позволяет получить новые объекты Git локально в папке .git / objects. И Git обновляет .git / FETCH_HEAD так, что теперь он указывает на последний коммит выбранной ветви.

Таким образом, чтобы увидеть различия между вашей текущей локальной веткой и веткой, выбранной из апстрима, вы можете запустить

git diff HEAD FETCH_HEAD
Марек Стэнли
источник
1
Вы не должны котировать элементы в каталоге .git, это не будет работать с упакованными ссылками. Также описанное вами поведение извлечения относится к более старым версиям git.
Андрей C
разве origin/masterссылка не обновляется ни извлечением, ни нажатием?
Джонатан Уэйкли
Верный. Я использовал Git 1.8.3 до сих пор. Я действительно могу заметить, что с версией 2.2.1 FETCH_HEAD также обновляется во время выборки. Кроме того, когда появляется сообщение «Ваша ветка обновлена ​​с ...» или «Ваша ветка отстает ... от X коммитов», оно появляется, только если ваша локальная ветка отслеживает данную удаленную ветку. Чтобы мастер мог отследить источник / мастера, нужно запустить git branch -u origin / master из ветви master. Если трекинга нет, вам все равно нужно запустить git diff.
Марек Стэнли
Что ж, тогда я предлагаю вам исправить утверждение о том, что ссылка «origin / master» обновляется только тогда, когда вы выполняете команду push на свой пульт »
Джонатан Уэйкли,
0

Давайте посмотрим на пример git-репо, чтобы проверить, если your branch (master)это up to dateс origin/master.

Убедитесь, что локальный мастер отслеживает происхождение / мастер:

$ git branch -vv
* master a357df1eb [origin/master] This is a commit message

Больше информации о местном филиале:

$ git show --summary
commit a357df1eb941beb5cac3601153f063dae7faf5a8 (HEAD -> master, tag: 2.8.0, origin/master, origin/HEAD)
Author: ...
Date:   Tue Dec 11 14:25:52 2018 +0100

    Another commit message

Проверьте, находится ли origin / master на том же коммите:

$ cat .git/packed-refs | grep origin/master
a357df1eb941beb5cac3601153f063dae7faf5a8 refs/remotes/origin/master

Мы можем видеть тот же самый хеш, и можно с уверенностью сказать, что ветка соответствует удаленной, по крайней мере, в текущем git-репо.

themefield
источник
0

попробуйте git add .раньшеgit commit

Деян Барик llevo3
источник
0

Тривиальный ответ, но точный в некоторых случаях, например, тот, который привел меня сюда. Я работал в репо, который был для меня новым, и я добавил файл, который статус не рассматривал как новый.

В итоге файл соответствует шаблону в файле .gitignore.

krustyengineer
источник
0

в этом случае используйте git add и интегрируйте все ожидающие файлы, затем используйте git commit и затем git push

git add - интегрировать все файлы кулонов

git commit - сохранить коммит

git push - сохранить в хранилище

Аиртон Сильвейра
источник