Как исправить «устаревшую» ссылку на удаленную ветку? - PullRequest
1 голос
/ 25 февраля 2020

Git говорит следующее:

On branch f-dbmailer
Your branch and 'origin/DBmailer' have diverged,
and have 7 and 43 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)

Но эта информация устарела: я полностью удалил удаленную ветку и подтвердил, что она действительно исчезла. (Таким образом, у нет «43 коммитов».) Реальная удаленная ветвь теперь имеет имя f-dbmailer ... но Git не забыла ни о старой ветке, ни, по-видимому, количество коммитов, которое было раньше.

Как мне это выяснить?

Ответы [ 2 ]

2 голосов
/ 26 февраля 2020

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

Как я уже упоминал в своем комментарии, эту ситуацию можно определить, выполнив команду git fetch git fetch -p затем git branch -vv (с двумя v, см. Пример ниже), но вместо того, чтобы запускать git branch -d … вручную для каждой подобной ветви, процедура «очистки» локального репо также может быть автоматизирована с использованием Git псевдонима .

Определение новая команда git deldone (полагаясь на Perl)

$ git config --global alias.deldone '!f() { git fetch -p && git branch -vv | \
  perl -wne '\''print "$1\n" if m/^\s*(\S+)\s+[0-9a-f]+\s+\[\S+: gone\]/;'\'' | \
  xargs git branch -d; }; f'

Обратите внимание, что опция git fetch -p (для --prune) необходима в этом псевдониме; см. также @ torek's answer для получения дополнительной информации об этой опции.

Полный пример использования

$ git branch -vv
    feature 12d22c1 [origin/feature] README.md
    fix     275e548 [origin/fix] Fix .gitignore
  * master  49b6c4a [origin/master: ahead 2] Merge branch 'fix'

  # let's remove branches feature and fix in the remote:

$ git push origin :feature
  To github.com:erikmd/demo-branch.git
   - [deleted]         feature
$ git push origin :fix
  To github.com:erikmd/demo-branch.git
   - [deleted]         fix

  # due to the commands above a `git fetch -p` was implied,
  # and you then get:

$ git branch -vv
    feature 12d22c1 [origin/feature: gone] README.md
    fix     275e548 [origin/fix: gone] Fix .gitignore
  * master  49b6c4a [origin/master: ahead 2] Merge branch 'fix'

$ git deldone
  error: The branch 'feature' is not fully merged.
  If you are sure you want to delete it, run 'git branch -D feature'.
  Deleted branch fix (was 275e548).

$ git branch -vv
    feature 12d22c1 [origin/feature: gone] README.md
  * master  49b6c4a [origin/master: ahead 2] Merge branch 'fix'

$ git branch -D feature
  Deleted branch feature (was 12d22c1).

Обратите внимание, что в отличие от ветви fix, feature ветвь была правильно определена как находящаяся в восходящем направлении, но не была удалена автоматически, поскольку Git знал, что это может привести к потере данных, поскольку ветка на карту не была интегрирована. (см. do c)

1 голос
/ 26 февраля 2020

Используйте git fetch --prune (или установите fetch.prune в файле конфигурации Git: я несколько лет установил глобально go, и теперь мне никогда не придется об этом думать).

Что происходит

Когда вы запускаете git fetch или git fetch origin, ваш Git вызывает другой Git, используя удаленное имя, такое как origin. Этот другой Git перечисляет имена его ветвей и соответствующие им идентификаторы ha sh. (В нем также перечислены имена тегов и другие имена, но здесь нас интересуют имена ветвей.)

Ваш Git берет эти имена ветвей и переименовывает их, чтобы сделать ваши имена для удаленного слежения. Это переименование фактически контролируется параметром remote.origin.fetch в вашей конфигурации Git:

$ git config --get remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*

Ведущий знак плюс - это флаг принудительного действия: эти ссылки обновляются, как если бы вы использовали git fetch --force (но другие обновления - нет, если вы не используете git fetch --force или они тоже помечены). Левая сторона двоеточия, refs/heads/*, соответствует всем именам ветвей других Git. Правая сторона двоеточия, refs/remotes/origin/*, обеспечивает переименование: например, refs/heads/master становится вашим refs/remotes/origin/master.

Теперь предположим, что вы запускаете git fetch дважды, с некоторым интервалом времени в в течение которого имена ветвей создаются и / или удаляются в других Git. В первый раз, когда ваш Git позвонит по номеру Git, список включает в себя:

refs/heads/master
refs/heads/br1
refs/heads/br2

Во второй раз, когда ваш Git позвонит им, в списке нет br2 в в нем есть br3:

refs/heads/master
refs/heads/br1
refs/heads/br3

Если коммит га sh ID для любого из них обновлен, ваш Git обновит соответствующее удаленное отслеживание имя. Но br2 просто больше не существует . Таким образом, ваш refs/remotes/origin/br2 не имеет нового значения.

По умолчанию ваш refs/remotes/origin/br2 сохраняет свое старое значение . С --prune в действии ваш Git говорит: Ага, то, что могло бы создать или обновить origin/br2, пропало, поэтому я должен удалить origin/br2 полностью ... и это так.

Опция --prune, вероятно, должна быть значением по умолчанию, но это не так. Вы можете сделать его вашим по умолчанию с помощью:

git config --global fetch.prune true

, и теперь ваш Git автоматически удалит любое имя удаленного отслеживания, у которого больше нет соответствующего имени ветви на пульте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...