Почему git fetch не всегда обновляет локальную ветку, чтобы показать, когда она не синхронизирована с удаленной

У меня есть сценарий, который автоматизирует некоторые большие задачи запросов на вытягивание, которые мы выполняем. Одна вещь, которую я делаю, это пытаюсь автоматически синхронизировать две ветки, которые мы используем. Раньше я использовал токен для выполнения git fetch, но недавно мне пришлось изменить его из-за некоторых изменений в политике.

Итак, что я делаю сейчас, это ниже.

subprocess.check_call(['git', 'fetch', f'https://{username}:{password}@{repo_url}'], cwd=repo_path)

Но я заметил, что это не всегда видно, когда моя локальная ветка не синхронизирована с удаленной веткой.

Вопрос

Мой вопрос заключается в следующем: чем отличается git fetch от того, когда я использую свое имя пользователя, пароль и repo_url, что заставляет его не замечать удаленные изменения, когда я использую свое имя пользователя и учетные данные для выполнения выборки? Что я должен делать по-другому? И что я должен использовать вместо этого, чтобы гарантировать, что мой скрипт заметит, когда удаленная ветвь не синхронизирована?

Дополнительная информация

Я пробовал написать сценарий git fetch сам по себе, и он отлично работает, только требует, чтобы я снова ввел свое имя пользователя и пароль.

subprocess.check_call(['git', 'fetch'], cwd=repo_path)

person HereForTheAnswers    schedule 29.03.2021    source источник
comment
Не могли бы вы попробовать диспетчер учетных данных?   -  person Cole Tierney    schedule 29.03.2021
comment
Я бы тоже не хотел. Наши ИТ-специалисты не одобряют хранение учетных данных пользователей.   -  person HereForTheAnswers    schedule 29.03.2021
comment
Можете ли вы использовать ssh с аутентификацией по ключу?   -  person Cole Tierney    schedule 29.03.2021
comment
Что именно означает не всегда работает? Вызов git fetch не работает? Выполняется ли обновление некоторых имен удаленного отслеживания, но не всех имен удаленного отслеживания? Он вообще ничего не делает? Какой результат он производит? Поскольку check_call гарантирует, что статус выхода равен нулю (в противном случае возникает исключение), завершается ли он без исключений или заканчивается исключением?   -  person torek    schedule 30.03.2021
comment
(В идеале вы должны включить репродукцию, но если это частное репо, это, очевидно, довольно сложно!)   -  person torek    schedule 30.03.2021
comment
@torek, он не обновляет все имена удаленного отслеживания, когда я вношу изменения и отправляю их из другой системы.   -  person HereForTheAnswers    schedule 30.03.2021
comment
@torek, И да, извините, я не могу предоставить репозиторий, потому что это что-то для работы, поэтому репо является частным. Я опубликовал ответ о том, что сработало для меня. Не стесняйтесь добавлять или объяснять, почему то, что я сделал, работает. Некоторые из них, честно говоря, сбивают меня с толку, почему я должен был добавить явную refspec, когда делал это по сценарию, но ручная выборка git работала просто отлично.   -  person HereForTheAnswers    schedule 30.03.2021
comment
Если вы просматриваете большой хостинг-сайт (GitHub, Bitbucket и т. д.), мне интересно, может ли это быть просто проблемой синхронизации, когда какой-то внешний интерфейс кэширует, когда этого не должно быть. Но даже в этом случае явная спецификация не должна изменять поведение скрипта. Старые (до 1.8.4) версии Git плохо себя ведут с частичными refspecs, но это также не зависит от написания скриптов и вручную.   -  person torek    schedule 30.03.2021


Ответы (1)


Для всех, кто сталкивается с этой проблемой:

Вы хотите сделать что-то вроде этого, где master — это ветка, которую вы хотите обновить.

subprocess.check_call(['git', 'fetch', f'https://{username}:{password}@{repo_url}','origin', master:refs/remotes/origin/master'], cwd=repo_path)

Проблема, по-видимому, связана с тем, что FETCH_HEAD не всегда обновляется при запуске git fetch. Поэтому изменения, которые происходят удаленно, не всегда вступают в силу при запуске git fetch. Почему это сработает при запуске вручную, но не по сценарию, для меня загадка.

См. также этот вопрос здесь и этот один, который привел меня к решению.

Из первого ответа я нашел это:

// Pulls the remote 'master' branch down to the local 'master' branch
git pull origin master:refs/remotes/origin/master

Из второго ответа мне удалось вытащить эту строку:

В качестве решения, если используется git fetch remote_name имя_ветви, извлекается только эта конкретная ветвь, и только эта единственная строка будет отображаться в содержимом .git/FETCH_HEAD, что делает ссылку FETCH_HEAD всегда правильной.

#Will only fetch branchone
git fetch origin branchone

Объединив эти две вещи, я получил работающий синтаксис. Я гарантированно получаю обновления, которые показывают, когда локальная ветвь не синхронизирована, явно указав refspec, который является этой частью master:refs/remotes/origin/master. Замените master именем вашей ветки, и она всегда будет обновлять вашу локальную ветку, чтобы показать, когда она не синхронизирована.

Третий аргумент f'https://{username}:{password}@{repo_url}' нужен только в том случае, если вы хотите собрать имя пользователя и пароль в начале вашего скрипта и использовать их в любых командах git, которым это нужно. В противном случае его можно опустить.

person HereForTheAnswers    schedule 30.03.2021