Как git ничего не зафиксировать без ошибки?

92

Я пытаюсь написать сценарий ткани, который выполняет git commit; однако, если фиксировать нечего, git завершает работу со статусом 1. Сценарий развертывания принимает это как неудачное и завершает работу. Я действительно хочу обнаруживать фактические сбои для фиксации, поэтому я не могу просто дать ткани игнорировать git commitсбои. Как я могу позволить игнорировать сбои при пустой фиксации, чтобы развертывание могло продолжаться, но все же выявлять ошибки, возникающие при сбое реальной фиксации?

def commit():
    local("git add -p && git commit")
Кодзиро
источник

Ответы:

157

Выявить это условие заранее, проверив код выхода git diff?

Например (в оболочке):

git add -A
git diff-index --quiet HEAD || git commit -m 'bla'

РЕДАКТИРОВАТЬ: фиксированная git diffкоманда в соответствии с комментарием Хольгера.

Тоби
источник
64
Обратите внимание, что git diffэто «фарфоровая» команда, которую не следует использовать для написания сценариев. Скорее всего, вы хотите git diff-index --quiet HEAD || git commit -m 'bla'. См. Также этот ответ .
Holger
1
Чтобы объяснить вещи дальше, проблема git diff --quiet --exit-code --cachedзаключается в том, что он будет оценивать 1(false) только для измененных файлов, которые не были подготовлены для фиксации (не добавленные файлы). Проголосовавший за комментарий - лучшее решение для учета новых файлов и удалений.
Хорхе Букаран
2
Комментарий о git diff-index --quiet HEAD || git commit -m 'bla'должен быть ответом на этот вопрос.
Ракиб
1
Поскольку Тоби не хотел исправлять свой ответ в соответствии с комментарием Хольгера, я сам отредактировал его ответ.
ВОГ
Обратите внимание, что git diff-index --quiet HEAD не проверяет, обновлен ли локальный репозиторий с учетом происхождения.
bortzmeyer
62

На git commitстранице руководства :

--allow-empty
    Usually recording a commit that has the exact same tree as its
    sole parent commit is a mistake, and the command prevents you
    from making such a commit. This option bypassesthe safety, and
    is primarily for use by foreign SCM interface scripts.
Свен Марнах
источник
43
Однако это фактически создаст фиксацию.
ThiefMaster
6
@ThiefMaster: Верно. Я не могу сказать из OP, проблема это или нет. Думаю, если вы используете автоматические коммиты, вам все равно не важно, чтобы ваша история была чистой.
Sven Marnach
1
Я бы предпочел, чтобы это не совершалось, если этого можно избежать. Есть способ сделать это?
kojiro
3
Это не ответ на вопрос
manojlds
7
@manojlds: «Конечно, OP не хочет создавать пустую фиксацию». Сегодня я оставил свой хрустальный шар дома, поэтому не знал. -pхоть и пропустил , но все же
Sven Marnach
5
with settings(warn_only=True):
  run('git commit ...')

Это заставляет ткань игнорировать сбой. Имеет то преимущество, что не создает пустых коммитов.

Вы можете обернуть его дополнительным слоем, with hide('warnings'):чтобы полностью подавить вывод, в противном случае вы получите примечание в выводе фабрики, что фиксация не удалась (но fabfile продолжает выполняться).

Тайлер Ивз
источник
3
OP написал: «Я действительно хочу обнаружить фактические ошибки фиксации»; этот код скроет все ошибки фиксации.
bfontaine
-2

попробуй / поймай ребенка!

from fabric.api import local
from fabric.colors import green


def commit(message='updates'):
    try:
        local('git add .')
        local('git commit -m "' + message + '"')
        local('git push')
        print(green('Committed and pushed to git.', bold=False))
    except:
        print(green('Done committing, likely nothing new to commit.', bold=False))
Devpascoe
источник
10
Чтобы объяснить, почему вас проигрывают: могут быть и другие ошибки, которые вы хотите уловить. Вы не хотите просто предполагать, что в случае ошибки может случиться так, что ничего не нужно фиксировать. - Также, но это не связано: никогда не используйте вместо него универсальный except:, используйте except Exceptionили что-то в этом роде.
Альберт