Как узнать, что локальное репо отличается от удаленного репо без извлечения?

Я получил десятки репозиториев, мой скрипт должен обновить их, если возникнет какая-либо разница, новые коммиты, новый тег, новая ветка. В моем случае выборка идет медленно для десятков репозиториев, и я хотел бы знать, может ли какая-нибудь быстрая команда удовлетворить мое требование.

3 ответа

Решение

Вы можете использовать git ls-remote Сантехническая команда для получения состояния пультов без извлечения.

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

Поместите следующее в сценарий; Вы можете включить его позже как функцию оболочки git alias для удобства. Беги внутри своего репо.

REMOTE_SUM=$(git ls-remote --tags --heads 2>/dev/null | git hash-object --stdin)
if git cat-file -e $REMOTE_SUM
then
    echo Remote check-summed up-to-date.
else
    echo Remote changed, fetching...
    git ls-remote --tags --heads 2>/dev/null | \
        git hash-object -w --stdin &>/dev/null
    git fetch
fi

Некоторая необходимая проверка ошибок была опущена, а код был продублирован для ясности.

объяснение

Перечисление всех удаленных советов с git ls-remote --tags --heads генерирует выходные данные, такие как:

От /home/user/tmp/repo2
777201715768a4d82f374f7224e68164a916ac1f        refs/heads/bar
78981922613b2afb6025042ff6bd878ac1994e85        refs/heads/master
...

В свою очередь, мы хэшируем вышеописанное изображение удаленного репо как единый хеш через git hash-object --stdin и проверьте, видели ли мы это ранее, запрашивая хеш в git с git cat-file -e, Если мы этого не видели, удаленное изображение должно было измениться, и мы сначала записали его в git с помощью git hash-object -w, чтобы приспособить расы между извлечением и фиксацией на пульте, а затем приступить к извлечению пульта.

Можно интегрировать это с функциональностью git pre-fetch: функциональностью pre-fetch hook в git, но это выходит за рамки этого ответа.

добавление

Обратите внимание, что выше будет генерировать свободные объекты в git, которые иногда нужно будет собирать с git gcи, возможно, --prune в явном виде.

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

Также обратите внимание, что ls-remote работает на одном пульте. Для работы с несколькими пультами вам нужно будет расширить сценарий, создав список пультов с git remote show и работать с каждым по очереди.

У вас нет доступа к origin сервер

Вы не можете использовать только git,

РЕДАКТИРОВАТЬ

Согласно другому ответу, git ls-remote может быть полезным для вас.

Тем не менее, как вы должны ls-remote во всех репозиториях, если ваша проблема связана с задержкой в ​​сети, она не будет решена с помощью ls-remote,


У вас есть доступ к origin сервер

  1. Настройте ловушку, когда на репо на сервере происходит запись. Хук будет помечать репо как измененный. Вы можете, например, создать repo_name__MODIFIED файл где-то на сервере).
  2. Перед обновлением репо проверьте, не модифицирован ли репо. Для данного примера проверьте, является ли файл repo_name__MODIFIED существуют на сервере.
  3. Если хранилище было изменено, перед обновлением отметьте его как неизмененное (непосредственно перед извлечением). В случае нашего примера просто удалите repo_name__MODIFIED файл на сервере.

Заметка

Почему выборка так долго? git будет только получать новые коммиты, если нет изменений в origin, это должно быть очень быстро!

Если вы настроили свои локальные репозитории, используя git clone или же git remote add $REMOTE_NAME $REMOTE_URL, всю информацию, которая вам нужна для сравнения ваших локальных филиалов с их удаленными коллегами (на момент вашего последнего git fetch) уже есть.

Если вы создали удаленные ветви отслеживания, git status говорит вам, если о различиях с удаленной веткой вы отслеживаете, как это.

$ git status
On branch master
Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   perl/Makefile.am

no changes added to commit (use "git add" and/or "git commit -a")

Также есть разбираемая форма:

$ git status --porcelain -b
## master...origin/master [behind 1]
 M perl/Makefile.am
Другие вопросы по тегам