Проверьте, нужно ли тянуть в Git

623

Как проверить, изменился ли удаленный репозиторий и нужно ли его вытащить?

Теперь я использую этот простой скрипт:

git pull --dry-run | grep -q -v 'Already up-to-date.' && changed=1

Но это довольно тяжело.

Есть ли способ лучше? Идеальное решение будет проверять все удаленные ветви и возвращать имена измененных веток и количество новых коммитов в каждой.

takeshin
источник
14
Пожалуйста, обратите внимание: «git pull --dry-run» не работает так, как, вероятно, ожидали. Похоже, что git pull передает неизвестные параметры непосредственно git fetch. Результатом является то, что нормальный git pull.
27
«pull» - это всего лишь короткий способ одновременно выполнить «fetch» ​​и «merge», если вам нужно проверить состояние удаленного репо, вы действительно моделируете «fetch». Так git fetch -v --dry-runэто то, что вам нужно.
Клаудио Флореани

Ответы:

859

Первое использование git remote update, чтобы обновить ваши удаленные ссылки. Затем вы можете сделать одну из нескольких вещей, таких как:

  1. git status -unoсообщит вам, находится ли отслеживаемая вами ветка впереди, позади или разошлась. Если это ничего не говорит, локальный и удаленный - то же самое.

  2. git show-branch *masterпокажет вам коммиты во всех ветвях, имена которых оканчиваются на «master» (например, master и origin / master ).

Если вы используете -vс git remote update( git remote -v update), вы можете увидеть, какие ветви были обновлены, поэтому вам больше не нужны никакие дополнительные команды.

Тем не менее, похоже, что вы хотите сделать это в скрипте или программе и получить значение true / false. Если это так, есть способы проверить взаимосвязь между вашим текущим коммитом HEAD и отслеживаемым заголовком ветви, хотя, поскольку есть четыре возможных результата, вы не можете свести его к ответу да / нет. Однако, если вы готовы сделать это, pull --rebaseвы можете рассматривать «местный позади» и «местный разошелся» как «нужно тянуть», а два других - как «не нужно тянуть».

Вы можете получить идентификатор коммита для любой ссылки с помощью git rev-parse <ref>, так что вы можете сделать это для master и origin / master и сравнить их. Если они равны, ветви одинаковы. Если они неравны, вы хотите знать, что впереди другого. Использование git merge-base master origin/masterскажет вам общего предка обеих ветвей, и если они не разошлись, это будет то же самое, что и та или другая. Если вы получаете три разных идентификатора, ветви разошлись.

Чтобы сделать это правильно, например, в скрипте, вы должны иметь возможность ссылаться на текущую ветку и на удаленную ветку, которую она отслеживает. Функция установки подсказок в bash /etc/bash_completion.dимеет некоторый полезный код для получения имен веток. Тем не менее, вам, вероятно, не нужно получать имена. В Git есть несколько удобных сокращений для ссылок на ветки и коммиты (как описано в git rev-parse --help). В частности, вы можете использовать его @для текущей ветви (при условии, что вы не находитесь в состоянии отсоединенной головы) и @{u}для его ветви восходящего направления (например,origin/master ). Так git merge-base @ @{u}будет возвращать (хэш из) фиксации , при котором ток ветви и ее вверх по течению и расходятся , git rev-parse @и git rev-parse @{u}даст вам хэши двух советов. Это можно обобщить в следующем сценарии:

#!/bin/sh

UPSTREAM=${1:-'@{u}'}
LOCAL=$(git rev-parse @)
REMOTE=$(git rev-parse "$UPSTREAM")
BASE=$(git merge-base @ "$UPSTREAM")

if [ $LOCAL = $REMOTE ]; then
    echo "Up-to-date"
elif [ $LOCAL = $BASE ]; then
    echo "Need to pull"
elif [ $REMOTE = $BASE ]; then
    echo "Need to push"
else
    echo "Diverged"
fi

Примечание: старые версии git не разрешали @сами по себе, поэтому вам, возможно, придется использовать @{0}вместо этого.

Линия UPSTREAM=${1:-'@{u}'} позволяет вам при желании явно передать ветвь вверх по течению, если вы хотите проверить другую удаленную ветвь, отличную от настроенной для текущей ветки. Это, как правило, имеет вид remotename / branchname . Если параметр не указан, по умолчанию используется значение @{u}.

Сценарий предполагает, что вы уже сделали первый git fetchили git remote updateпервый шаг, чтобы обновить ветки отслеживания. Я не встроил это в скрипт, потому что он более гибок, чтобы можно было выполнять выборку и сравнение как отдельные операции, например, если вы хотите сравнить без выборки, потому что вы уже загрузили недавно.

Нил Мэйхью
источник
4
@takeshin Полагаю, вы могли бы объединить git ls-remote origin -h refs /heads / master, как предложено @brool, с git rev-list --max-count = 1 origin / master. Если они возвращают один и тот же хэш, удаленная ветвь не изменилась с тех пор, как вы в последний раз обновляли свои удаленные ссылки (с извлечением, извлечением, удаленным обновлением и т. Д.). Это имело бы то преимущество, что вам не пришлось бы удалять содержимое все коммиты сразу, но могут оставить это на более удобное время. Однако, поскольку удаленное обновление не является разрушительным, вы все равно можете это сделать.
Нил Мэйхью
2
Вы также можете попробовать git status -s -u no, что дает более короткий вывод, чем git status -u no.
Филип Клауд
2
@mhulse, git remote -v update. Посмотрите на вывод git remote --helpдля более полного объяснения.
Нил Мэйхью
1
@ChrisMaes Хороший вопрос. Более явный синтаксис необходим для более старых версий git. Я экспериментировал с различными имеющимися у меня системами и обнаружил, что он @{u}работает с git 1.8.3.2, но @не работает. Однако @работает с 1.8.5.4. Мораль истории: git продолжает улучшаться, и стоит иметь самую последнюю версию, какую только можно.
Нил Мэйхью
1
Спецификатор теперь требуется для @. Вы можете использовать @ {0} вместо @.
Бен Дэвис
132

Если у вас есть ветка upstream

git fetch <remote>
git status

Если у вас нет ветки вверх по течению

Сравните две ветви:

git fetch <remote>
git log <local_branch_name>..<remote_branch_name> --oneline

Например:

git fetch origin

# See if there are any incoming changes
git log HEAD..origin/master --oneline

(Я предполагаю, что origin/masterэто ваша удаленная ветка отслеживания)

Если какие-либо коммиты перечислены в выводе выше, то у вас есть входящие изменения - вам нужно объединить. Если никакие коммиты не перечислены, git logтогда объединять нечего.

Обратите внимание, что это будет работать, даже если вы находитесь в ветви функций - у которой нет удаленного отслеживания, поскольку, если явно ссылается на нее, а не origin/masterкосвенно использует восходящую ветку, запомненную Git.

PlagueHammer
источник
2
git fetch; git log HEAD.. --onelineМожно использовать даже более короткую запись , если для локальной ветки по умолчанию существует удаленная ветвь.
Фил Пирожков
@philpirozhkov Если у вас есть удаленная ветка по умолчанию, я думаю, нужно просто «git status». Мой ответ был общим для любых двух ветвей, где одна может отслеживать, а может и не отслеживать другую.
PlagueHammer
55
git rev-list HEAD...origin/master --countдаст вам общее количество «разных» коммитов между ними.
Джейк Бергер
1
коротко и просто. Мое любимое решение, которое просто показывает новые коммиты (два раза выше)
spankmaster79
Как я могу использовать это в пакетном файле (Ubuntu), чтобы я мог запускать другие команды только в том случае, если эта команда показывает, что требуется извлечение?
Улисс Алвес
69

Если это для скрипта, вы можете использовать:

git fetch
$(git rev-parse HEAD) == $(git rev-parse @{u})

(Примечание: преимущество этого по сравнению с предыдущими ответами состоит в том, что вам не нужна отдельная команда для получения имени текущей ветви. "HEAD" и "@ {u}" (восходящая ветка текущей ветви) позаботятся об этом. См. "git rev-parse --help" для более подробной информации.)

Стивен Хаберман
источник
Я обнаружил @ {u} независимо и обновил свой ответ, прежде чем увидел твой.
Нил Мэйхью
1
Будет ли git rev-parse @{u}показывать последний коммит без git fetch?
Кайл Стрэнд
3
Это был билет! Хотя, ваша логика использует, ==что означает «если нет никаких изменений от восходящего потока». Я использовал !=для проверки «если есть изменения из апстрима» для моего приложения. Не забудьте git fetchсначала!
ChrisPrime
1
Я добавил git fetch, потому что это действительно необходимо, чтобы ответить на оригинальный вопрос. @это сокращение от HEADBtw.
user1338062
Пользователям Windows , потребуется одинарные кавычки , @{u}напримерgit rev-parse '@{u}'
spuder
36

Команда

git ls-remote origin -h refs/heads/master

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

brool
источник
1
Какой-нибудь пример скрипта для сравнения этих значений?
принимает
18
git rev-list HEAD...origin/master --countдаст вам общее количество «разных» коммитов между ними.
Джейк Бергер
3
@jberger, чтобы уточнить, это будет показывать только количество коммитов, которые вы позади (не впереди и сзади), и это работает только если вы git fetchили git remote updateпервый. git statusтакже показывает счет, кстати.
Деннис
1
@ Денис Я думал, что ..это «коммиты в оригинале / мастере, вычитающие ГОЛОВУ» (т.е. количество коммитов позади). Принимая во внимание, что ...есть симметричная разница (то есть впереди и сзади)
Джейк Бергер
3
Отлично. Насколько я могу судить, это единственное решение, которое на самом деле проверяет источник на наличие обновлений, но не делает этого неявно fetch.
Кайл Стрэнд
35

Вот одна строчка Bash, которая сравнивает хэш коммита HEAD текущей ветки с его удаленной веткой восходящей ветки, не требуя тяжелых операций git fetchили git pull --dry-runопераций:

[ $(git rev-parse HEAD) = $(git ls-remote $(git rev-parse --abbrev-ref @{u} | \
sed 's/\// /g') | cut -f1) ] && echo up to date || echo not up to date

Вот как эта несколько плотная линия разбита:

  • Команды сгруппированы и вложены с использованием синтаксиса подстановки команд$(x) Bash .
  • git rev-parse --abbrev-ref @{u}возвращает сокращенный восходящий ref (например origin/master), который затем преобразуется в разделенные пробелами поля с помощью конвейерной sedкоманды, например origin master.
  • Эта строка передается, git ls-remoteкоторая возвращает фиксированный заголовок удаленной ветви. Эта команда будет связываться с удаленным хранилищем. Команда piped cutизвлекает только первое поле (хеш коммита), удаляя разделенную табуляцией справочную строку.
  • git rev-parse HEAD возвращает хеш локального коммита
  • Синтаксис Bash [ a = b ] && x || yзавершает однострочное: это сравнение строк Bash =внутри тестовой конструкции [ test ], за которым следуют конструкции and-list и or-list && true || false.
wjordan
источник
2
Я бы не использовал / g в sed, если вы используете косые черты в именах веток. Это только "sed 's / \ // /".
Мартын Дэвис
@wjordan Ваше решение дает сбой, когда удаленный репозиторий недоступен (или не обслуживается), и будет запускаться «в актуальном состоянии»
кадр
20

Я предлагаю вам посмотреть скрипт https://github.com/badele/gitcheck . Я написал этот сценарий для проверки за один проход всех ваших репозиториев Git, и он показывает, кто не совершал, а кто не выдвигал / вытягивал.

Вот пример результата:

Введите описание изображения здесь

Бруно Адели
источник
6
аккуратный, думая о переписывании его в чистой оболочке
Оливье Рефало
1
Теперь вы также можете использовать gitcheck непосредственно из док-контейнера (с вашими файлами на вашем хосте). Для получения дополнительной информации см. Проект gitcheck github
Bruno Adelé
Подобный инструмент в bash git-multi-repo-tooling . git mrepo -cэто отобразит все ожидающие коммиты.
Грег
11

Я основал это решение на комментариях @jberger.

if git checkout master &&
    git fetch origin master &&
    [ `git rev-list HEAD...origin/master --count` != 0 ] &&
    git merge origin/master
then
    echo 'Updated!'
else
    echo 'Not updated.'
fi
ma11hew28
источник
Ссылаясь на ваш предыдущий комментарий , на данный момент я не могу дать вам точный ответ. В то время, когда я делал эти комментарии, я погружался в глубины мерзавца и особенно отдаленных и различий. С тех пор прошло несколько месяцев, и большая часть этих знаний похоронена в моем мозгу. ;) Если вы ищете количество «разных» коммитов между ними, тогда, ...похоже, это правильная часть вашего решения.
Джейк Бергер
1
Спасибо. Это было чисто.
Шобхит Пури
10

Уже есть много очень богатых и оригинальных ответов. Чтобы обеспечить некоторый контраст, я мог бы обойтись очень простой строкой.

# Check return value to see if there are incoming updates.
if ! git diff --quiet remotes/origin/HEAD; then
 # pull or whatever you want to do
fi
thuovila
источник
2
В оригинальном ответе не было '!' в случае если Возвращаемое значение из git diff равно нулю, когда нет изменений.
Thuovila
IMO лучшее решение, хотя мне нужно заменить «remotes / origin / HEAD» на «origin / master» или другую ревизию
Matthias Michael Engh
9

Я думаю, что лучший способ сделать это будет:

git diff remotes/origin/HEAD

Предполагая, что у вас есть этот refspec зарегистрирован. Если вы клонировали репозиторий, вы должны это сделать в противном случае (т. Е. Если репозиторий был создан de novo локально и перенесен на удаленный компьютер), вам необходимо явно добавить refspec.

Джит
источник
9

Приведенный ниже скрипт работает отлично.

changed=0
git remote update && git status -uno | grep -q 'Your branch is behind' && changed=1
if [ $changed = 1 ]; then
    git pull
    echo "Updated successfully";
else
    echo "Up-to-date"
fi
Харикришна
источник
6

Я бы поступил так, как предложил Броул. Следующий однострочный скрипт берет SHA1 вашей последней зафиксированной версии и сравнивает его с версией удаленного источника, и извлекает изменения, только если они отличаются. И это еще более легкий из решений на основе git pullили git fetch.

[ `git log --pretty=%H ...refs/heads/master^` != `git ls-remote origin
-h refs/heads/master |cut -f1` ] && git pull
Клаудио Флореани
источник
Эта команда не выполняется, если репозиторий git клонирован с «--depth 1» (для ограничения размера загрузки). Знаете ли вы, если есть способ это исправить?
Адам Рычковски
Журнал git возвращает много строк и выдает ошибку «bash: [: слишком много аргументов», на которую я бы переключилсяgit rev-parse --verify HEAD
Дрю Пирс,
1
Это простое сравнение строк, выполненное bash. Если что-то не получается, я бы посоветовал вам проверить свой синтаксис (т.е. вы печатаете неправильно). Сначала запустите, git log --pretty=%H ...refs/heads/master^ чтобы получить SHA1 вашей последней подтвержденной версии, а затем запустите, git ls-remote origin -h refs/heads/master |cut -f1 чтобы получить SHA1 удаленного источника. Эти две команды являются git и не имеют ничего общего с bash. В квадратных скобках bash сравнивает выходные данные первой команды со второй, и, если они равны, возвращает true и запускается git pull.
Клаудио Флореани
msgstr "и если они равны, он возвращает истину и работает git pull". Я знаю, что я придирчив, но просто чтобы спасти кого-то от путаницы, это должно быть "а если они не равны". Кроме того, по какой-то причине первая команда git не работает для меня. (Я на Git 2.4.1.) Так что я просто использую git log --pretty=%H master | head -n1вместо этого. Но я не уверен, что это точно так же.
xd1le
6

Если вы запустите этот скрипт, он проверит, нужна ли текущей ветке git pull:

#!/bin/bash

git fetch -v --dry-run 2>&1 |
    grep -qE "\[up\s+to\s+date\]\s+$(
        git branch 2>/dev/null |
           sed -n '/^\*/s/^\* //p' |
                sed -r 's:(\+|\*|\$):\\\1:g'
    )\s+" || {
        echo >&2 "Current branch need a 'git pull' before commit"
        exit 1
}

Это очень удобно использовать в качестве предварительной фиксации Git, чтобы избежать

Merge branch 'foobar' of url:/path/to/git/foobar into foobar

когда ты commitраньше pulling.

Чтобы использовать этот код в качестве хука, просто скопируйте / вставьте скрипт в

.git/hooks/pre-commit

а также

chmod +x .git/hooks/pre-commit
Жиль Квено
источник
6

Я просто хочу опубликовать это как фактическое сообщение, так как это легко пропустить в комментариях.

Правильный и лучший ответ на этот вопрос дал @Jake Berger, Большое спасибо, чувак, это нужно всем, и все упускают это в комментариях. Поэтому для всех, кто борется с этим, правильный ответ, просто используйте вывод этой команды, чтобы узнать, нужно ли вам делать git pull. если вывод равен 0, то, очевидно, обновлять нечего.

@stackoverflow, дай этому парню колокола. Спасибо @ Джейк Бергер

git rev-list HEAD...origin/master --count will give you the total number of "different" commits between the two.  Jake Berger Feb 5 '13 at 19:23
diegeelvis_SA
источник
4

Запустите git fetch (remote)для обновления ваших удаленных ссылок, он покажет вам, что нового. Затем, когда вы оформите заказ в своем местном отделении, он покажет, находится ли он за апстримом.

че
источник
Я думаю, что он уже проверил местный филиал, поэтому ему нужно что-то еще, чтобы показать, позади ли он и т. Д. Он может сделать это с помощью git status.
Нил Мэйхью
Правда, после того, как вы достали пульты, это git statusтоже покажет.
Че
1
Это что-то в настроении git pull --dry-runделает, но я думаю, что это тяжело для cron-скрипта, запускаемого каждую минуту.
принимает
@takeshin: Вы не можете проверить удаленные репозитории, не выходя в сеть. Если нет ничего нового fetch, то не сделаю ничего, кроме проверки статуса. Если вам нужна очень быстрая и легкая реакция на удаленные обновления, вы можете захотеть подключить какие-то уведомления к удаленному хранилищу.
Че
@takeshin: если вы хотите проверять удаленное репо каждую минуту, я думаю, вы упустили из виду DVCS. Вся идея в том, чтобы иметь возможность самостоятельно развиваться какое-то время, а потом плавно собрать все вместе. Это не похоже на cvs, svn, p4 и т. Д., Где вы всегда должны работать над тем, что является последним в репозитории. Если вам действительно нужно что-то, над чем кто-то еще работает, тогда вам следует использовать другой механизм связи, например, электронную почту, чтобы сообщить вам, когда он будет готов к работе.
Нил Мэйхью
4

Все такие сложные предложения, в то время как решение очень короткое и простое:

#!/bin/bash

BRANCH="<your branch name>"
LAST_UPDATE=`git show --no-notes --format=format:"%H" $BRANCH | head -n 1`
LAST_COMMIT=`git show --no-notes --format=format:"%H" origin/$BRANCH | head -n 1`

git remote update
if [ $LAST_COMMIT != $LAST_UPDATE ]; then
        echo "Updating your branch $BRANCH"
        git pull --no-edit
else
        echo "No updates available"
fi
Цифровой человек
источник
LAST_COMMIT и LAST_UPDATE всегда равны, даже если есть изменения
canbax
Это хорошее и простое решение, git remote updateно для того, чтобы получить последнюю информацию о
коммите
Не git remote updateследует добавлять перед git showкомандами?
Setop
2

Вот моя версия скрипта Bash, который проверяет все репозитории в предопределенной папке:

https://gist.github.com/henryiii/5841984

Он может различать обычные ситуации, такие как «тянуть» и «толкать», и он многопоточный, поэтому выборка происходит сразу. У него есть несколько команд, таких как pull и status.

Поместите символическую ссылку (или скрипт) в папку на вашем пути, тогда она будет работать как git all status(и т. Д.). Он поддерживает только origin / master, но его можно редактировать или комбинировать с другим методом.

Генри Шрайнер
источник
1
git ls-remote | cut -f1 | git cat-file --batch-check >&-

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

git pack-refs --all
mine=`mktemp`
sed '/^#/d;/^^/{G;s/.\(.*\)\n.* \(.*\)/\1 \2^{}/;};h' .git/packed-refs | sort -k2 >$mine
for r in `git remote`; do 
    echo Checking $r ...
    git ls-remote $r | sort -k2 | diff -b - $mine | grep ^\<
done
jthill
источник
1

Может быть, это, если вы хотите добавить задачу как crontab:

#!/bin/bash
dir="/path/to/root"
lock=/tmp/update.lock
msglog="/var/log/update.log"

log()
{
        echo "$(date) ${1:-missing}" >> $msglog
}

if [ -f $lock ]; then
        log "Already run, exiting..."
else
        > $lock
        git -C ~/$dir remote update &> /dev/null
        checkgit=`git -C ~/$dir status`
        if [[ ! "$checkgit" =~ "Your branch is up-to-date" ]]; then
                log "-------------- Update ---------------"
                git -C ~/$dir pull &>> $msglog
                log "-------------------------------------"
        fi
        rm $lock

fi
exit 0
Altzone
источник
1

Используя простое регулярное выражение:

str=$(git status) 
if [[ $str =~ .*Your\ branch\ is\ behind.*by.*commits,\ and\ can\ be\ fast-forwarded ]]; then
    echo `date "+%Y-%m-%d %H:%M:%S"` "Needs pull"
else
    echo "Code is up to date"
fi
Томас Кукис
источник
Так не пойдет. Состояние git - это только локальная проверка, и поэтому она будет сообщать вам только о том, отстает ли ваша ветвь, если вы уже обновили свои удаленные определения.
minhaz1
0

Я использую версию сценария, основанную на ответе Стивена Хабермана:

if [ -n "$1" ]; then
    gitbin="git -C $1"
else
    gitbin="git"
fi

# Fetches from all the remotes, although --all can be replaced with origin
$gitbin fetch --all
if [ $($gitbin rev-parse HEAD) != $($gitbin rev-parse @{u}) ]; then
    $gitbin rebase @{u} --preserve-merges
fi

Предполагая, что этот скрипт вызывается git-fetch-and-rebase, он может быть вызван с необязательным аргументомdirectory name локального репозитория Git для выполнения операции. Если скрипт вызывается без аргументов, предполагается, что текущий каталог является частью репозитория Git.

Примеры:

# Operates on /abc/def/my-git-repo-dir
git-fetch-and-rebase /abc/def/my-git-repo-dir

# Operates on the Git repository which the current working directory is part of
git-fetch-and-rebase

Это доступно и здесь .

Tuxdude
источник
0

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

Если вы работаете в Windows, вы можете запустить этот скрипт в Windows, используя Git Bash, предоставляемый Git для Windows (установка или переносная версия).

Этот скрипт требует аргументов

- локальный путь, например / d / source / project1
- Git URL, например, https: //username@bitbucket.org/username/project1.git
- пароль

если пароль не следует вводить в командной строке в виде простого текста,
затем измените скрипт, чтобы проверить, пуст ли GITPASS; не делайте
замените и позвольте Git запросить пароль

Сценарий будет

- Find the current branch
- Get the SHA1 of the remote on that branch
- Get the SHA1 of the local on that branch
- Compare them.

Если есть изменения, напечатанные сценарием, вы можете приступить к извлечению или извлечению. Сценарий может быть неэффективным, но он выполняет работу за меня.

Обновление - 2015-10-30: stderr в dev null для предотвращения печати URL-адреса с паролем на консоли.

#!/bin/bash

# Shell script to check if a Git pull is required.

LOCALPATH=$1
GITURL=$2
GITPASS=$3

cd $LOCALPATH
BRANCH="$(git rev-parse --abbrev-ref HEAD)"

echo
echo git url = $GITURL
echo branch = $BRANCH

# Bash replace - replace @ with :password@ in the GIT URL
GITURL2="${GITURL/@/:$GITPASS@}"
FOO="$(git ls-remote $GITURL2 -h $BRANCH 2> /dev/null)"
if [ "$?" != "0" ]; then
  echo cannot get remote status
  exit 2
fi
FOO_ARRAY=($FOO)
BAR=${FOO_ARRAY[0]}
echo [$BAR]

LOCALBAR="$(git rev-parse HEAD)"
echo [$LOCALBAR]
echo

if [ "$BAR" == "$LOCALBAR" ]; then
  #read -t10 -n1 -r -p 'Press any key in the next ten seconds...' key
  echo No changes
  exit 0
else
  #read -t10 -n1 -r -p 'Press any key in the next ten seconds...' key
  #echo pressed $key
  echo There are changes between local and remote repositories.
  exit 1
fi
RuntimeException
источник
0

Для пользователей Windows, которые в конечном итоге задают этот вопрос, я модифицировал некоторые ответы в сценарий powershell. Настраивайте по необходимости, сохраняйте в .ps1файл и запускайте по требованию или по расписанию, если хотите.

cd C:\<path to repo>
git remote update                           #update remote
$msg = git remote show origin               #capture status
$update = $msg -like '*local out of date*'
if($update.length -gt 0){                   #if local needs update
    Write-Host ('needs update')
    git pull
    git reset --hard origin/master
    Write-Host ('local updated')
} else {
    Write-Host ('no update needed')
}
Эндрю Грот
источник
0

Поскольку ответ Neils мне очень помог, вот перевод Python без каких-либо зависимостей:

import os
import logging
import subprocess

def check_for_updates(directory:str) -> None:
    """Check git repo state in respect to remote"""
    git_cmd = lambda cmd: subprocess.run(
        ["git"] + cmd,
        cwd=directory,
        stdout=subprocess.PIPE,
        check=True,
        universal_newlines=True).stdout.rstrip("\n")

    origin = git_cmd(["config", "--get", "remote.origin.url"])
    logging.debug("Git repo origin: %r", origin)
    for line in git_cmd(["fetch"]):
        logging.debug(line)
    local_sha = git_cmd(["rev-parse", "@"])
    remote_sha = git_cmd(["rev-parse", "@{u}"])
    base_sha = git_cmd(["merge-base", "@", "@{u}"])
    if local_sha == remote_sha:
        logging.info("Repo is up to date")
    elif local_sha == base_sha:
        logging.info("You need to pull")
    elif remote_sha == base_sha:
        logging.info("You need to push")
    else:
        logging.info("Diverged")

check_for_updates(os.path.dirname(__file__))

НТН

Frans
источник
-5

Вы также можете найти скрипт Phing, который делает это сейчас.

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

Сценарий написан на XML и требует Phing .

Pol Dellaiera
источник
Может быть, это не очень хорошая идея, чтобы скопировать сценарий сюда, я все еще обновляю его ...
Pol Dellaiera